Browse Source

[2342] Added deleteLease6 functionality

Stephen Morris 12 years ago
parent
commit
fdbdac116c

+ 49 - 14
src/lib/dhcp/mysql_lease_mgr.cc

@@ -17,6 +17,8 @@
 #include <string>
 #include <string>
 #include <config.h>
 #include <config.h>
 #include <time.h>
 #include <time.h>
+#include <mysql/mysqld_error.h>
+
 #include <dhcp/mysql_lease_mgr.h>
 #include <dhcp/mysql_lease_mgr.h>
 #include <asiolink/io_address.h>
 #include <asiolink/io_address.h>
 
 
@@ -155,7 +157,7 @@ public:
     ///         valid only for as long as this MySqlLease6Exchange object is
     ///         valid only for as long as this MySqlLease6Exchange object is
     ///         in existence.
     ///         in existence.
     MYSQL_BIND* createBindForReceive() {
     MYSQL_BIND* createBindForReceive() {
-        std::cout << "createBindForReceive\n";
+
         // Ensure bind array clear.
         // Ensure bind array clear.
         memset(bind_, 0, sizeof(bind_));
         memset(bind_, 0, sizeof(bind_));
         memset(error_, 0, sizeof(error_));
         memset(error_, 0, sizeof(error_));
@@ -188,9 +190,8 @@ public:
         bind_[2].error = &error_[2];
         bind_[2].error = &error_[2];
 
 
         // lease_time: unsigned int
         // lease_time: unsigned int
-        unsigned lease_time;
         bind_[3].buffer_type = MYSQL_TYPE_LONG;
         bind_[3].buffer_type = MYSQL_TYPE_LONG;
-        bind_[3].buffer = reinterpret_cast<char*>(&lease_time);
+        bind_[3].buffer = reinterpret_cast<char*>(&lease_time_);
         bind_[3].is_unsigned = true_;
         bind_[3].is_unsigned = true_;
         bind_[3].error = &error_[3];
         bind_[3].error = &error_[3];
 
 
@@ -343,8 +344,9 @@ MySqlLeaseMgr::convertToDatabaseTime(time_t cltt, uint32_t valid_lft,
 }
 }
 
 
 void
 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;
     valid_lft = lease_time;
 
 
     // Copy across fields from MYSQL_TIME structure.
     // Copy across fields from MYSQL_TIME structure.
@@ -508,20 +510,30 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& /* lease */) {
 
 
 bool
 bool
 MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
 MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
+
     // Create the MYSQL_BIND array for the lease
     // Create the MYSQL_BIND array for the lease
     MySqlLease6Exchange exchange;
     MySqlLease6Exchange exchange;
     MYSQL_BIND* bind = exchange.CreateBindForSend(lease);
     MYSQL_BIND* bind = exchange.CreateBindForSend(lease);
 
 
     // Bind the parameters to the statement
     // 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");
     checkError(status, INSERT_LEASE6, "unable to bind parameters");
 
 
     // Execute the statement
     // Execute the statement
     status = mysql_stmt_execute(statements_[INSERT_LEASE6]);
     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
 Lease4Ptr
@@ -576,7 +588,7 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
     MYSQL_BIND* outbind = exchange.createBindForReceive();
     MYSQL_BIND* outbind = exchange.createBindForReceive();
 
 
     // Bind the input parameters to the statement
     // 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");
     checkError(status, GET_LEASE6, "unable to bind WHERE clause parameter");
 
 
     // Bind the output parameters to the statement
     // 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");
         checkError(status, GET_LEASE6, "unable to fetch results");
 
 
     } else {
     } else {
-        std::cout << "In the truncation clause\n";
-
     //     We are ignoring truncation for now, so the only other result is
     //     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.
     //     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.
     //     This has already been set, so ther action is a no-op.
@@ -648,8 +658,33 @@ MySqlLeaseMgr::deleteLease4(const isc::asiolink::IOAddress& /* addr */) {
 }
 }
 
 
 bool
 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<char*>(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
 std::string

+ 5 - 2
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)
     /// @return smart pointer to the lease (or NULL if a lease is not found)
     virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
     virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
 
 
+
     /// @brief Returns existing IPv4 leases for specified hardware address.
     /// @brief Returns existing IPv4 leases for specified hardware address.
     ///
     ///
     /// Although in the usual case there will be only one lease, for mobile
     /// 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
     /// The contents of the enum are indexes into the list of SQL statements
     enum StatementIndex {
     enum StatementIndex {
+        DELETE_LEASE6,      // Delete from lease6 by address
         GET_LEASE6,         // Get lease 6 by address
         GET_LEASE6,         // Get lease 6 by address
         GET_VERSION,        // Obtain version number
         GET_VERSION,        // Obtain version number
         INSERT_LEASE6,      // Add entry to lease6 table
         INSERT_LEASE6,      // Add entry to lease6 table
@@ -360,12 +362,13 @@ private:
     /// @param what High-level description of the error
     /// @param what High-level description of the error
     ///
     ///
     /// @exception DbOperationError Error doing a database operation
     /// @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 {
                            const char* what) const {
         if (status != 0) {
         if (status != 0) {
             isc_throw(DbOperationError, what << " for <" <<
             isc_throw(DbOperationError, what << " for <" <<
                       raw_statements_[index] << ">, reason: " <<
                       raw_statements_[index] << ">, reason: " <<
-                      mysql_error(mysql_));
+                      mysql_error(mysql_) << " (error code " <<
+                      mysql_errno(mysql_) << ")");
         }
         }
     }
     }
 
 

+ 82 - 44
src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc

@@ -151,36 +151,72 @@ TEST_F(MySqlLeaseMgrTest, CheckVersion) {
     EXPECT_EQ(1, version.second);
     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<int>(lease->type_) << ")\n";
+    }
+    cout << "   Address:       " << lease->addr_.toText() << "\n";
+    cout << "   Prefix length: " << static_cast<int>(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
 /// @brief Compare Lease4 Structure
 bool
 bool
-compareLease6(const Lease6Ptr& l1, const Lease6Ptr& l2) {
+compareLease6(const Lease6Ptr& first, const Lease6Ptr& second) {
     return (
     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
 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
 /// @brief Initialize Lease
@@ -219,7 +255,7 @@ TEST_F(MySqlLeaseMgrTest, BasicLease6) {
     l1->hwaddr_ = std::vector<uint8_t>(6, 0x42);     // Six hex 42's
     l1->hwaddr_ = std::vector<uint8_t>(6, 0x42);     // Six hex 42's
     l1->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
     l1->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
     l1->preferred_lft_ = 3600;  // Preferred lifetime
     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->cltt_ = 123456;         // Current time of day
     l1->subnet_id_ = 73;        // Arbitrary number
     l1->subnet_id_ = 73;        // Arbitrary number
 
 
@@ -227,47 +263,49 @@ TEST_F(MySqlLeaseMgrTest, BasicLease6) {
     Lease6Ptr l2(new Lease6());
     Lease6Ptr l2(new Lease6());
     initializeUnusedLease6(l2);
     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->iaid_ = 89;
     l2->hwaddr_ = std::vector<uint8_t>(6, 0xf43);     // Six hex 42's
     l2->hwaddr_ = std::vector<uint8_t>(6, 0xf43);     // Six hex 42's
     l2->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x3a)));
     l2->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x3a)));
     l2->preferred_lft_ = 1800;  // Preferred lifetime
     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->cltt_ = 234567;         // Current time of day
     l2->subnet_id_ = l1->subnet_id_;    // Same as l1
     l2->subnet_id_ = l1->subnet_id_;    // Same as l1
 
 
     // Sanity check that the leases are different
     // Sanity check that the leases are different
     ASSERT_FALSE(compareLease6(l1, l2));
     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;
     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);
     l_returned = lmptr_->getLease6(L1_ADDRESS);
     EXPECT_TRUE(l_returned);
     EXPECT_TRUE(l_returned);
     detailCompareLease6(l1, 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));
     EXPECT_TRUE(lmptr_->deleteLease6(L1_ADDRESS));
+    l_returned = lmptr_->getLease6(L1_ADDRESS);
+    EXPECT_FALSE(l_returned);
     EXPECT_FALSE(lmptr_->deleteLease6(L1_ADDRESS));
     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
 }; // end of anonymous namespace