From: Stephen Morris Date: Sun, 4 Nov 2012 19:57:05 +0000 (+0000) Subject: [2342] Add getLease6 selecting by DUID, IAID and Subnet ID X-Git-Tag: trac2487_base~1^2~43 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=eb211d7cfc40962bd64193b3a91ecd2560edf3f3;p=thirdparty%2Fkea.git [2342] Add getLease6 selecting by DUID, IAID and Subnet ID --- diff --git a/src/lib/dhcp/mysql_lease_mgr.cc b/src/lib/dhcp/mysql_lease_mgr.cc index e03237f2e0..0703859cd3 100644 --- a/src/lib/dhcp/mysql_lease_mgr.cc +++ b/src/lib/dhcp/mysql_lease_mgr.cc @@ -532,24 +532,33 @@ MySqlLeaseMgr::prepareStatements() { "SELECT address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len " - "FROM lease6 WHERE address = ?"); + "FROM lease6 " + "WHERE address = ?"); prepareStatement(GET_LEASE6_DUID_IAID, "SELECT address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len " - "FROM lease6 WHERE duid = ? AND iaid = ?"); + "FROM lease6 " + "WHERE duid = ? AND iaid = ?"); + prepareStatement(GET_LEASE6_DUID_IAID_SUBID, + "SELECT address, duid, valid_lifetime, " + "expire, subnet_id, pref_lifetime, " + "lease_type, iaid, prefix_len " + "FROM lease6 " + "WHERE duid = ? AND iaid = ? AND subnet_id = ?"); prepareStatement(GET_VERSION, "SELECT version, minor FROM schema_version"); prepareStatement(INSERT_LEASE6, "INSERT INTO lease6(address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); prepareStatement(UPDATE_LEASE6, "UPDATE lease6 SET address = ?, duid = ?, " "valid_lifetime = ?, expire = ?, subnet_id = ?, " "pref_lifetime = ?, lease_type = ?, iaid = ?, " - "prefix_len = ? WHERE address = ?"); + "prefix_len = ? " + "WHERE address = ?"); } bool @@ -778,11 +787,87 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const { } Lease6Ptr -MySqlLeaseMgr::getLease6(const DUID& /* duid */, uint32_t /* iaid */, - SubnetID /* subnet_id */) const { - isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const DUID&, SubnetID) " - "not implemented yet"); - return (Lease6Ptr()); +MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid, + SubnetID subnet_id) const { + // Set up the WHERE clause value + MYSQL_BIND inbind[3]; + memset(inbind, 0, sizeof(inbind)); + + // DUID. The complex casting is needed to obtain the "const" vector of + // uint8_t from the DUID, point to the start of it (discarding the + // "const"ness) and finally casing it to "char*" for the MySQL buffer + // element. + const vector& duid_vector = duid.getDuid(); + unsigned long duid_length = duid_vector.size(); + inbind[0].buffer_type = MYSQL_TYPE_BLOB; + inbind[0].buffer = reinterpret_cast( + const_cast(&duid_vector[0])); + inbind[0].buffer_length = duid_length; + inbind[0].length = &duid_length; + + // IAID + inbind[1].buffer_type = MYSQL_TYPE_LONG; + inbind[1].buffer = reinterpret_cast(&iaid); + inbind[1].is_unsigned = static_cast(1); + + // Subnet ID + inbind[2].buffer_type = MYSQL_TYPE_LONG; + inbind[2].buffer = reinterpret_cast(&subnet_id); + inbind[2].is_unsigned = static_cast(1); + + // Bind the input parameters to the statement + int status = mysql_stmt_bind_param(statements_[GET_LEASE6_DUID_IAID_SUBID], inbind); + checkError(status, GET_LEASE6_DUID_IAID_SUBID, "unable to bind WHERE clause parameter"); + + // Set up the SELECT clause + MySqlLease6Exchange exchange; + std::vector outbind; + exchange.createBindForReceive(outbind); + + // Bind the output parameters to the statement + status = mysql_stmt_bind_result(statements_[GET_LEASE6_DUID_IAID_SUBID], &outbind[0]); + checkError(status, GET_LEASE6_DUID_IAID_SUBID, "unable to bind SELECT clause parameters"); + + // Execute the query. + status = mysql_stmt_execute(statements_[GET_LEASE6_DUID_IAID_SUBID]); + checkError(status, GET_LEASE6_DUID_IAID_SUBID, "unable to execute"); + + Lease6Ptr result; + status = mysql_stmt_fetch(statements_[GET_LEASE6_DUID_IAID_SUBID]); + if (status == 0) { + try { + result = exchange.getLeaseData(); + + // TODO: check for more than one row returned. At present, just ignore + // the excess and take the first. + + } catch (const isc::BadValue& ex) { + // Free up result set. + + (void) mysql_stmt_free_result(statements_[GET_LEASE6_DUID_IAID_SUBID]); + // Lease type is returned, to rethrow the exception with a bit + // more data. + isc_throw(BadValue, ex.what() << ". Statement is <" << + text_statements_[GET_LEASE6_DUID_IAID_SUBID] << ">"); + } + + // As the address is the primary key in the table, we can't return + // two rows, so we don't bother checking whether multiple rows have + // been returned. + + } else if (status == 1) { + checkError(status, GET_LEASE6_DUID_IAID_SUBID, "unable to fetch results"); + + } else { + // @TODO Handle truncation + // 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 the action is a no-op. + } + + // Free data structures associated with information returned. + (void) mysql_stmt_free_result(statements_[GET_LEASE6_DUID_IAID_SUBID]); + return (result); } void diff --git a/src/lib/dhcp/mysql_lease_mgr.h b/src/lib/dhcp/mysql_lease_mgr.h index 3ecd14f3ea..f00b84ee6c 100644 --- a/src/lib/dhcp/mysql_lease_mgr.h +++ b/src/lib/dhcp/mysql_lease_mgr.h @@ -334,6 +334,7 @@ private: DELETE_LEASE6, // Delete from lease6 by address GET_LEASE6_ADDR, // Get lease6 by address GET_LEASE6_DUID_IAID, // Get lease6 by DUID and IAID + GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and Subnet ID GET_VERSION, // Obtain version number INSERT_LEASE6, // Add entry to lease6 table UPDATE_LEASE6, // Update a Lease6 entry diff --git a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc index b698c8b84b..87afe7848c 100644 --- a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc +++ b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc @@ -541,7 +541,6 @@ TEST_F(MySqlLeaseMgrTest, BasicLease6) { detailCompareLease6(leases[2], l_returned); } - // @brief Check GetLease6 methods - Access by DUID/IAID // // Adds leases to the database and checks that they can be accessed via @@ -573,6 +572,60 @@ TEST_F(MySqlLeaseMgrTest, GetLease6Extended1) { EXPECT_EQ(L1_ADDRESS, addresses[0]); EXPECT_EQ(L4_ADDRESS, addresses[1]); EXPECT_EQ(L5_ADDRESS, addresses[2]); + + // Check that nothing is returned when either the IAID or DUID match + // nothing. + returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1); + EXPECT_EQ(0, returned.size()); + + // Alter the leases[1] DUID to match nothing in the database. + vector duid_vector = leases[1]->duid_->getDuid(); + ++duid_vector[0]; + DUID new_duid(duid_vector); + returned = lmptr_->getLease6(new_duid, leases[1]->iaid_); + EXPECT_EQ(0, returned.size()); +} + + + +// @brief Check GetLease6 methods - Access by DUID/IAID/SubnetID +// +// Adds leases to the database and checks that they can be accessed via +// a combination of DIUID and IAID. +TEST_F(MySqlLeaseMgrTest, GetLease6Extended2) { + // Get the leases to be used for the test. + vector leases = createLeases6(); + EXPECT_LE(6, leases.size()); // Expect to access leases 0 through 5 + + // Add them to the database + for (int i = 0; i < leases.size(); ++i) { + EXPECT_TRUE(lmptr_->addLease(leases[i])); + } + + // Get the leases matching the DUID and IAID of lease[1]. + Lease6Ptr returned = lmptr_->getLease6(*leases[1]->duid_, + leases[1]->iaid_, + leases[1]->subnet_id_); + ASSERT_TRUE(returned); + EXPECT_TRUE(*returned == *leases[1]); + + // Modify each of the three parameters (DUID, IAID, Subnet ID) and + // check that nothing is returned. + returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1, + leases[1]->subnet_id_); + EXPECT_FALSE(returned); + + returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_, + leases[1]->subnet_id_ + 1); + EXPECT_FALSE(returned); + + // Alter the leases[1] DUID to match nothing in the database. + vector duid_vector = leases[1]->duid_->getDuid(); + ++duid_vector[0]; + DUID new_duid(duid_vector); + returned = lmptr_->getLease6(new_duid, leases[1]->iaid_, + leases[1]->subnet_id_); + EXPECT_FALSE(returned); }