From: Stephen Morris Date: Mon, 22 Oct 2012 15:07:34 +0000 (+0100) Subject: [2342] Added deleteLease6 functionality X-Git-Tag: trac2487_base~1^2~58 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fdbdac116c417a4e3236669554da431c66cbea09;p=thirdparty%2Fkea.git [2342] Added deleteLease6 functionality --- diff --git a/src/lib/dhcp/mysql_lease_mgr.cc b/src/lib/dhcp/mysql_lease_mgr.cc index fecc84eb18..aac06822cf 100644 --- a/src/lib/dhcp/mysql_lease_mgr.cc +++ b/src/lib/dhcp/mysql_lease_mgr.cc @@ -17,6 +17,8 @@ #include #include #include +#include + #include #include @@ -155,7 +157,7 @@ public: /// valid only for as long as this MySqlLease6Exchange object is /// in existence. MYSQL_BIND* createBindForReceive() { - std::cout << "createBindForReceive\n"; + // Ensure bind array clear. memset(bind_, 0, sizeof(bind_)); memset(error_, 0, sizeof(error_)); @@ -188,9 +190,8 @@ public: bind_[2].error = &error_[2]; // lease_time: unsigned int - unsigned lease_time; bind_[3].buffer_type = MYSQL_TYPE_LONG; - bind_[3].buffer = reinterpret_cast(&lease_time); + bind_[3].buffer = reinterpret_cast(&lease_time_); bind_[3].is_unsigned = true_; bind_[3].error = &error_[3]; @@ -343,8 +344,9 @@ MySqlLeaseMgr::convertToDatabaseTime(time_t cltt, uint32_t valid_lft, } void -MySqlLeaseMgr::convertFromDatabaseTime(const MYSQL_TIME& expire, uint32_t lease_time, - time_t& cltt, uint32_t& valid_lft) { +MySqlLeaseMgr::convertFromDatabaseTime(const MYSQL_TIME& expire, + uint32_t lease_time, time_t& cltt, + uint32_t& valid_lft) { valid_lft = lease_time; // Copy across fields from MYSQL_TIME structure. @@ -508,20 +510,30 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& /* lease */) { bool MySqlLeaseMgr::addLease(const Lease6Ptr& lease) { + // Create the MYSQL_BIND array for the lease MySqlLease6Exchange exchange; MYSQL_BIND* bind = exchange.CreateBindForSend(lease); // Bind the parameters to the statement - my_bool status = mysql_stmt_bind_param(statements_[INSERT_LEASE6], bind); + int status = mysql_stmt_bind_param(statements_[INSERT_LEASE6], bind); checkError(status, INSERT_LEASE6, "unable to bind parameters"); // Execute the statement status = mysql_stmt_execute(statements_[INSERT_LEASE6]); - checkError(status, INSERT_LEASE6, "unable to execute"); + if (status != 0) { + + // Failure: check for the special case of duplicate entry. If this is + // the case, we return false to indicate that the row was not added. + // Otherwise we throw an exception. + if (mysql_errno(mysql_) == ER_DUP_ENTRY) { + return (false); + } + checkError(status, INSERT_LEASE6, "unable to execute"); + } - // ... and find out whether a row as inserted. - return (mysql_stmt_affected_rows(statements_[INSERT_LEASE6]) == 1); + // Insert succeeded + return (true); } Lease4Ptr @@ -576,7 +588,7 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const { MYSQL_BIND* outbind = exchange.createBindForReceive(); // Bind the input parameters to the statement - my_bool status = mysql_stmt_bind_param(statements_[GET_LEASE6], inbind); + int status = mysql_stmt_bind_param(statements_[GET_LEASE6], inbind); checkError(status, GET_LEASE6, "unable to bind WHERE clause parameter"); // Bind the output parameters to the statement @@ -612,8 +624,6 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const { checkError(status, GET_LEASE6, "unable to fetch results"); } else { - std::cout << "In the truncation clause\n"; - // We are ignoring truncation for now, so the only other result is // no data was found. In that case, we return a null Lease6 structure. // This has already been set, so ther action is a no-op. @@ -648,8 +658,33 @@ MySqlLeaseMgr::deleteLease4(const isc::asiolink::IOAddress& /* addr */) { } bool -MySqlLeaseMgr::deleteLease6(const isc::asiolink::IOAddress& /* addr */) { - return (false); +MySqlLeaseMgr::deleteLease6(const isc::asiolink::IOAddress& addr) { + + // Set up the WHERE clause value + MYSQL_BIND inbind[1]; + memset(inbind, 0, sizeof(inbind)); + + std::string addr6 = addr.toText(); + unsigned long addr6_length = addr6.size(); + + inbind[0].buffer_type = MYSQL_TYPE_STRING; + inbind[0].buffer = const_cast(addr6.c_str()); + inbind[0].buffer_length = addr6_length; + inbind[0].length = &addr6_length; + + // Bind the input parameters to the statement + int status = mysql_stmt_bind_param(statements_[DELETE_LEASE6], inbind); + checkError(status, DELETE_LEASE6, "unable to bind WHERE clause parameter"); + + // Execute + status = mysql_stmt_execute(statements_[DELETE_LEASE6]); + checkError(status, DELETE_LEASE6, "unable to execute"); + + // See how many rows were affected. Note that the statement may delete + // multiple rows. + return (mysql_stmt_affected_rows(statements_[DELETE_LEASE6]) > 0); + + return false; } std::string diff --git a/src/lib/dhcp/mysql_lease_mgr.h b/src/lib/dhcp/mysql_lease_mgr.h index 9f55b9adc7..50ccb72ec5 100644 --- a/src/lib/dhcp/mysql_lease_mgr.h +++ b/src/lib/dhcp/mysql_lease_mgr.h @@ -97,6 +97,7 @@ public: /// @return smart pointer to the lease (or NULL if a lease is not found) virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const; + /// @brief Returns existing IPv4 leases for specified hardware address. /// /// Although in the usual case there will be only one lease, for mobile @@ -314,6 +315,7 @@ private: /// /// The contents of the enum are indexes into the list of SQL statements enum StatementIndex { + DELETE_LEASE6, // Delete from lease6 by address GET_LEASE6, // Get lease 6 by address GET_VERSION, // Obtain version number INSERT_LEASE6, // Add entry to lease6 table @@ -360,12 +362,13 @@ private: /// @param what High-level description of the error /// /// @exception DbOperationError Error doing a database operation - inline void checkError(my_bool status, StatementIndex index, + inline void checkError(int status, StatementIndex index, const char* what) const { if (status != 0) { isc_throw(DbOperationError, what << " for <" << raw_statements_[index] << ">, reason: " << - mysql_error(mysql_)); + mysql_error(mysql_) << " (error code " << + mysql_errno(mysql_) << ")"); } } diff --git a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc index 30b7023479..03e6a29940 100644 --- a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc +++ b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc @@ -151,36 +151,72 @@ TEST_F(MySqlLeaseMgrTest, CheckVersion) { EXPECT_EQ(1, version.second); } +/// @brief Print Elements of Lease6 Structure +/// +/// @param lease Pointer to lease to print +/// @param title Title to print before the lease information +void +printLease6(const Lease6Ptr& lease, const char* title = NULL) { + if (title != NULL) { + cout << title << "\n"; + } + + cout << " Type: "; + switch (lease->type_) { + case Lease6::LEASE_IA_NA: + cout << "IA_NA\n"; + break; + case Lease6::LEASE_IA_TA: + cout << "IA_TA\n"; + break; + case Lease6::LEASE_IA_PD: + cout << "IA_PD\n"; + break; + default: + cout << "unknown (" << static_cast(lease->type_) << ")\n"; + } + cout << " Address: " << lease->addr_.toText() << "\n"; + cout << " Prefix length: " << static_cast(lease->prefixlen_) << "\n"; + cout << " IAID: " << lease->iaid_ << "\n"; + cout << " Pref life: " << lease->preferred_lft_ << "\n"; + cout << " Valid life: " << lease->valid_lft_ << "\n"; + cout << " Cltt: " << lease->cltt_ << "\n"; + cout << " Subnet ID: " << lease->subnet_id_ << "\n"; +} /// @brief Compare Lease4 Structure bool -compareLease6(const Lease6Ptr& l1, const Lease6Ptr& l2) { +compareLease6(const Lease6Ptr& first, const Lease6Ptr& second) { return ( - l1->type_ == l2->type_ && - l1->addr_ == l2->addr_ && - l1->prefixlen_ == l2->prefixlen_ && - l1->iaid_ == l2->iaid_ && - l1->hwaddr_ == l2->hwaddr_ && - *l1->duid_ == *l2->duid_ && - l1->preferred_lft_ == l2->preferred_lft_ && - l1->valid_lft_ == l2->valid_lft_ && - l1->cltt_ == l2->cltt_ && - l1->subnet_id_ == l2->subnet_id_ + first->type_ == second->type_ && + first->addr_ == second->addr_ && + first->prefixlen_ == second->prefixlen_ && + first->iaid_ == second->iaid_ && + first->hwaddr_ == second->hwaddr_ && + *first->duid_ == *second->duid_ && + first->preferred_lft_ == second->preferred_lft_ && + first->valid_lft_ == second->valid_lft_ && + first->cltt_ == second->cltt_ && + first->subnet_id_ == second->subnet_id_ ); } void -detailCompareLease6(const Lease6Ptr& l1, const Lease6Ptr& l2) { - EXPECT_EQ(l1->type_, l2->type_); - EXPECT_EQ(l1->addr_, l2->addr_); - EXPECT_EQ(l1->prefixlen_, l2->prefixlen_); - EXPECT_EQ(l1->iaid_, l2->iaid_); - EXPECT_TRUE(l1->hwaddr_ == l2->hwaddr_); - EXPECT_TRUE(*l1->duid_ == *l2->duid_); - EXPECT_EQ(l1->preferred_lft_, l2->preferred_lft_); - EXPECT_EQ(l1->valid_lft_, l2->valid_lft_); - EXPECT_EQ(l1->cltt_, l2->cltt_); - EXPECT_EQ(l1->subnet_id_, l2->subnet_id_); +detailCompareLease6(const Lease6Ptr& first, const Lease6Ptr& second) { + EXPECT_EQ(first->type_, second->type_); + + // Compare address strings - odd things happen when they are different + // as the EXPECT_EQ appears to call the operator uint32_t() function, + // which causes an exception to be thrown for IPv6 addresses. + EXPECT_EQ(first->addr_.toText(), second->addr_.toText()); + EXPECT_EQ(first->prefixlen_, second->prefixlen_); + EXPECT_EQ(first->iaid_, second->iaid_); + EXPECT_TRUE(first->hwaddr_ == second->hwaddr_); + EXPECT_TRUE(*first->duid_ == *second->duid_); + EXPECT_EQ(first->preferred_lft_, second->preferred_lft_); + EXPECT_EQ(first->valid_lft_, second->valid_lft_); + EXPECT_EQ(first->cltt_, second->cltt_); + EXPECT_EQ(first->subnet_id_, second->subnet_id_); } /// @brief Initialize Lease @@ -219,7 +255,7 @@ TEST_F(MySqlLeaseMgrTest, BasicLease6) { l1->hwaddr_ = std::vector(6, 0x42); // Six hex 42's l1->duid_ = boost::shared_ptr(new DUID(vector(8, 0x42))); l1->preferred_lft_ = 3600; // Preferred lifetime - l1->valid_lft_ = 3600; // Actual lifetime + l1->valid_lft_ = 3677; // Actual lifetime l1->cltt_ = 123456; // Current time of day l1->subnet_id_ = 73; // Arbitrary number @@ -227,47 +263,49 @@ TEST_F(MySqlLeaseMgrTest, BasicLease6) { Lease6Ptr l2(new Lease6()); initializeUnusedLease6(l2); - l2->type_ = Lease6::LEASE_IA_TA; - l2->addr_ = L1_ADDRESS; - l2->prefixlen_ = 0; + l2->type_ = Lease6::LEASE_IA_PD; + l2->addr_ = L2_ADDRESS; + l2->prefixlen_ = 7; l2->iaid_ = 89; l2->hwaddr_ = std::vector(6, 0xf43); // Six hex 42's l2->duid_ = boost::shared_ptr(new DUID(vector(8, 0x3a))); l2->preferred_lft_ = 1800; // Preferred lifetime - l2->valid_lft_ = 5400; // Actual lifetime + l2->valid_lft_ = 5412; // Actual lifetime l2->cltt_ = 234567; // Current time of day l2->subnet_id_ = l1->subnet_id_; // Same as l1 // Sanity check that the leases are different ASSERT_FALSE(compareLease6(l1, l2)); - // Start the tests. Add the first lease to the database. Then read it - // back to see whether it is what we think it is. + // Start the tests. Add two leases to the database, read them back and + // check they are what we think they are. Lease6Ptr l_returned; - ASSERT_TRUE(lmptr_->addLease(l1)); - lmptr_->commit(); + EXPECT_TRUE(lmptr_->addLease(l1)); + EXPECT_TRUE(lmptr_->addLease(l2)); + l_returned = lmptr_->getLease6(L1_ADDRESS); EXPECT_TRUE(l_returned); detailCompareLease6(l1, l_returned); - lmptr_->rollback(); -/* - // Delete the lease and check that it has been deleted. - EXPECT_TRUE(lmptr_->deleteLease6(L1_ADDRESS)); - l_returned = lmptr_->getLease6(L1_ADDRESS); - EXPECT_FALSE(l_returned); - // Add the address again and check that we can't add it a second time - ASSERT_TRUE(lmptr_->addLease(l1)); - ASSERT_FALSE(lmptr_->addLease(l1)); + l_returned = lmptr_->getLease6(L2_ADDRESS); + EXPECT_TRUE(l_returned); + detailCompareLease6(l2, l_returned); - // Add the second lease - ASSERT_TRUE(lmptr_->addLease(l2)); + // Check that we can't add a second lease with the same address + EXPECT_FALSE(lmptr_->addLease(l1)); - // Finally, delete the lease and check we can't delete it again. + // Delete a lease, check that it's gone, and that we can't delete it + // a second time. EXPECT_TRUE(lmptr_->deleteLease6(L1_ADDRESS)); + l_returned = lmptr_->getLease6(L1_ADDRESS); + EXPECT_FALSE(l_returned); EXPECT_FALSE(lmptr_->deleteLease6(L1_ADDRESS)); - */ + + // Check that the second address is still there. + l_returned = lmptr_->getLease6(L2_ADDRESS); + EXPECT_TRUE(l_returned); + detailCompareLease6(l2, l_returned); } }; // end of anonymous namespace