namespace isc {
namespace dhcp {
-
-
/// @brief Exchange MySQL and Lease4 Data
///
/// On any MySQL operation, arrays of MYSQL_BIND structures must be built to
MYSQL_TIME expire_; ///< Lease expiry time
const my_bool false_; ///< "false" for MySql
Lease4Ptr lease_; ///< Pointer to lease object
- uint32_t valid_lifetime_; ///< Lease time
uint32_t subnet_id_; ///< Subnet identification
const my_bool true_; ///< "true_" for MySql
+ uint32_t valid_lifetime_; ///< Lease time
};
const my_bool false_; ///< "false" for MySql
uint32_t iaid_; ///< Identity association ID
Lease6Ptr lease_; ///< Pointer to lease object
- uint32_t valid_lifetime_; ///< Lease time
uint8_t lease_type_; ///< Lease type
uint8_t prefixlen_; ///< Prefix length
uint32_t pref_lifetime_; ///< Preferred lifetime
uint32_t subnet_id_; ///< Subnet identification
const my_bool true_; ///< "true_" for MySql
+ uint32_t valid_lifetime_; ///< Lease time
};
///
/// When a MySQL statement is exected, to fetch the results the function
/// mysql_stmt_fetch() must be called. As well as getting data, this
-/// allocated internal state. Subsequent calls to mysql_stmt_fetch
+/// allocates internal state. Subsequent calls to mysql_stmt_fetch
/// can be made, but when all the data is retrieved, mysql_stmt_free_result
/// must be called to free up the resources allocated.
///
};
-// MySqlLeaseMgr Methods
+// MySqlLeaseMgr Constructor and Destructor
MySqlLeaseMgr::MySqlLeaseMgr(const LeaseMgr::ParameterMap& parameters)
: LeaseMgr(parameters), mysql_(NULL) {
}
+
+// Database acess method
+
void
MySqlLeaseMgr::openDatabase() {
// changed and so the "affected rows" (retrievable from MySQL) is zero.
// This makes it hard to distinguish whether the UPDATE changed no rows
// because no row matching the WHERE clause was found, or because a
- // row was found by no data was altered.
+ // row was found but no data was altered.
MYSQL* status = mysql_real_connect(mysql_, host, user, password, name,
0, NULL, CLIENT_FOUND_ROWS);
if (status != mysql_) {
}
}
+// Prepared statement setup. The textual form of the SQL statement is stored
+// in a vector of strings (text_statements_) and is used in the output of
+// error messages. The SQL statement is also compiled into a "prepared
+// statement" (stored in statements_), which avoids the overhead of compilation
+// during use. As these allocate resources, the class destructor explicitly
+// destroys the prepared statements.
void
MySqlLeaseMgr::prepareStatement(StatementIndex index, const char* text) {
}
-// Common add lease code
+// Add leases to the database
bool
MySqlLeaseMgr::addLease(StatementIndex stindex, std::vector<MYSQL_BIND>& bind) {
return (addLease(INSERT_LEASE6, bind));
}
+// A convenience function used in the various getLease() methods. It binds
+// the selection parameters to the prepared statement, and binds the variables
+// that will receive the data. These are stored in the MySqlLease6Exchange
+// object associated with the lease manager and converted to a Lease6 object
+// when retrieved.
+template <typename Exchange>
+void
+MySqlLeaseMgr::bindAndExecute(StatementIndex stindex, Exchange& exchange,
+ MYSQL_BIND* inbind) const {
+
+ // Bind the input parameters to the statement
+ int status = mysql_stmt_bind_param(statements_[stindex], inbind);
+ checkError(status, stindex, "unable to bind WHERE clause parameter");
+
+ // Set up the SELECT clause
+ std::vector<MYSQL_BIND> outbind = exchange->createBindForReceive();
+
+ // Bind the output parameters to the statement
+ status = mysql_stmt_bind_result(statements_[stindex], &outbind[0]);
+ checkError(status, stindex, "unable to bind SELECT caluse parameters");
+
+ // Execute the statement
+ status = mysql_stmt_execute(statements_[stindex]);
+ checkError(status, stindex, "unable to execute");
+}
+
+// Extraction of leases from the database. Much the code has common logic
+// with the difference between V4 and V6 being the data types of the
+// objects involved. For this reason, the common logic is inside a
+// template method.
template <typename Exchange, typename LeasePtr>
void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* inbind,
// to fields in the exchange object, then execute the prepared statement.
bindAndExecute(stindex, exchange, inbind);
- // Fetch the data and set up the "release" object to release associated
+ // Fetch the data and set up the "free result" object to release associated
// resources when this method exits.
MySqlFreeResult fetch_release(statements_[stindex]);
int status = mysql_stmt_fetch(statements_[stindex]);
Lease4Ptr
-MySqlLeaseMgr::getLease4(const isc::asiolink::IOAddress& /* addr */,
- SubnetID /* subnet_id */) const {
- isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const IOAddress&, SubnetID) "
- "not implemented yet");
- return (Lease4Ptr());
+MySqlLeaseMgr::getLease4(const isc::asiolink::IOAddress& addr,
+ SubnetID subnet_id) const {
+
+ // As the address is the unique primary key of the lease4 table, there can
+ // only be one lease with a given address. Therefore we will get that
+ // lease and do the filtering on subnet ID here.
+ Lease4Ptr result = getLease4(addr);
+ if (result && (result->subnet_id_ != subnet_id)) {
+
+ // Lease found but IDs do not match. Return null pointer
+ result.reset();
+ }
+
+ return (result);
}
}
-// A convenience function used in the various getLease() methods. It binds
-// the selection parameters to the prepared statement, and binds the variables
-// that will receive the data. These are stored in the MySqlLease6Exchange
-// object associated with the lease manager and converted to a Lease6 object
-// when retrieved.
-template <typename Exchange>
-void
-MySqlLeaseMgr::bindAndExecute(StatementIndex stindex, Exchange& exchange,
- MYSQL_BIND* inbind) const {
-
- // Bind the input parameters to the statement
- int status = mysql_stmt_bind_param(statements_[stindex], inbind);
- checkError(status, stindex, "unable to bind WHERE clause parameter");
-
- // Set up the SELECT clause
- std::vector<MYSQL_BIND> outbind = exchange->createBindForReceive();
-
- // Bind the output parameters to the statement
- status = mysql_stmt_bind_result(statements_[stindex], &outbind[0]);
- checkError(status, stindex, "unable to bind SELECT caluse parameters");
-
- // Execute the statement
- status = mysql_stmt_execute(statements_[stindex]);
- checkError(status, stindex, "unable to execute");
-}
Lease6Ptr
// Check they were created
for (int i = 0; i < leases.size(); ++i) {
- EXPECT_TRUE(leases[i]);
+ ASSERT_TRUE(leases[i]);
}
// Check they are different
for (int i = 0; i < (leases.size() - 1); ++i) {
for (int j = (i + 1); j < leases.size(); ++j) {
- EXPECT_TRUE(leases[i] != leases[j]);
+ ASSERT_TRUE(leases[i] != leases[j]);
}
}
}
reopen();
Lease4Ptr l_returned = lmptr_->getLease4(ioaddress4_[1]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[1], l_returned);
l_returned = lmptr_->getLease4(ioaddress4_[2]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[2], l_returned);
l_returned = lmptr_->getLease4(ioaddress4_[3]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[3], l_returned);
// Check that we can't add a second lease with the same address
// Check that the second address is still there.
l_returned = lmptr_->getLease4(ioaddress4_[2]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[2], l_returned);
}
reopen();
Lease6Ptr l_returned = lmptr_->getLease6(ioaddress6_[1]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[1], l_returned);
l_returned = lmptr_->getLease6(ioaddress6_[2]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[2], l_returned);
l_returned = lmptr_->getLease6(ioaddress6_[3]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[3], l_returned);
// Check that we can't add a second lease with the same address
// Check that the second address is still there.
l_returned = lmptr_->getLease6(ioaddress6_[2]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[2], l_returned);
}
+// @brief Check GetLease4 methods - Access by Address and SubnetID
+//
+// Adds leases to the database and checks that they can be accessed via
+// a combination of Address, SubnetID
+TEST_F(MySqlLeaseMgrTest, getLease4AddressSubnetId) {
+ // Get the leases to be used for the test.
+ vector<Lease4Ptr> leases = createLeases4();
+
+ // Add just one to the database.
+ EXPECT_TRUE(lmptr_->addLease(leases[1]));
+
+ // Look for a known lease with a valid Subnet ID
+ Lease4Ptr l_returned = lmptr_->getLease4(ioaddress4_[1], 73);
+ ASSERT_TRUE(l_returned);
+ detailCompareLease(leases[1], l_returned);
+
+ // Look for a lease known to be in the database with an invalid Subnet ID
+ l_returned = lmptr_->getLease4(ioaddress4_[1], 74);
+ EXPECT_FALSE(l_returned);
+
+ // Look for a lease known not to be in the database with a valid Subnet ID
+ l_returned = lmptr_->getLease4(ioaddress4_[2], 73);
+ EXPECT_FALSE(l_returned);
+
+ // Look for a lease known not to be in the database with and invalid
+ l_returned = lmptr_->getLease4(ioaddress4_[2], 74);
+ EXPECT_FALSE(l_returned);
+}
+
+// @brief Check GetLease4 methods - Access by Hardware Address
+//
+// Adds leases to the database and checks that they can be accessed via
+// hardware address
+TEST_F(MySqlLeaseMgrTest, getLease4AddressHwaddr) {
+ FAIL() << "Test not complete";
+/*
+ // Get the leases to be used for the test and add to the database.
+ vector<Lease4Ptr> leases = createLeases4();
+ for (int i = 0; i < leases.size(); ++i) {
+ EXPECT_TRUE(lmptr_->addLease(leases[i]));
+ }
+
+ // Get a known hardware address
+ vector<uint8_t> hwaddr = leases[1]->hwaddr_;
+ EXPECT_FALSE(hwaddr.empty());
+
+ // Look for a lease with a valid hardware address
+ Lease4Ptr l_returned = lmptr_->getLease4(hwaddr);
+ ASSERT_TRUE(l_returned);
+ detailCompareLease(leases[1], l_returned);
+
+ // Look for a lease with an invalid valid hardware address
+ hwaddr[0] += 1;
+ Lease4Ptr l_returned = lmptr_->getLease4(hwaddr);
+ EXPECT_FALSE(l_returned);
+
+ // Check it handles an empty hardware address
+ hwaddr.clear();
+ Lease4Ptr l_returned = lmptr_->getLease4(hwaddr);
+ EXPECT_FALSE(l_returned);
+
+ // Add a lease with an empty hardware address to the database and
+ // check that it find that.
+*/
+}
+
// @brief Check GetLease6 methods - Access by DUID/IAID
//
// Adds leases to the database and checks that they can be accessed via
// a combination of DIUID and IAID.
-TEST_F(MySqlLeaseMgrTest, getLease6Extended1) {
+TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) {
// Get the leases to be used for the test.
vector<Lease6Ptr> leases = createLeases6();
- EXPECT_LE(6, leases.size()); // Expect to access leases 0 through 5
+ ASSERT_LE(6, leases.size()); // Expect to access leases 0 through 5
// Add them to the database
for (int i = 0; i < leases.size(); ++i) {
//
// Adds leases to the database and checks that they can be accessed via
// a combination of DIUID and IAID.
-TEST_F(MySqlLeaseMgrTest, getLease6Extended2) {
+TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetId) {
// Get the leases to be used for the test.
vector<Lease6Ptr> leases = createLeases6();
- EXPECT_LE(6, leases.size()); // Expect to access leases 0 through 5
+ ASSERT_LE(6, leases.size()); // Expect to access leases 0 through 5
// Add them to the database
for (int i = 0; i < leases.size(); ++i) {
TEST_F(MySqlLeaseMgrTest, updateLease6) {
// Get the leases to be used for the test.
vector<Lease6Ptr> leases = createLeases6();
- EXPECT_LE(3, leases.size()); // Expect to access leases 0 through 5
+ ASSERT_LE(3, leases.size()); // Expect to access leases 0 through 2
// Add a lease to the database and check that the lease is there.
EXPECT_TRUE(lmptr_->addLease(leases[1]));
reopen();
Lease6Ptr l_returned = lmptr_->getLease6(ioaddress6_[1]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[1], l_returned);
// Modify some fields in lease 1 (not the address) and update it.
// ... and check what is returned is what is expected.
l_returned.reset();
l_returned = lmptr_->getLease6(ioaddress6_[1]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[1], l_returned);
// Alter the lease again and check.
l_returned.reset();
l_returned = lmptr_->getLease6(ioaddress6_[1]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[1], l_returned);
// Check we can do an update without changing data.
lmptr_->updateLease6(leases[1]);
l_returned.reset();
l_returned = lmptr_->getLease6(ioaddress6_[1]);
- EXPECT_TRUE(l_returned);
+ ASSERT_TRUE(l_returned);
detailCompareLease(leases[1], l_returned);
// Try updating a lease not in the database.