2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-02 15:05:16 +00:00

[2342] Move creation of MYSQL_BIND array for lease addition to separate class

This commit is contained in:
Stephen Morris
2012-10-22 10:49:51 +01:00
parent 93ffcbb3ec
commit a64f318cb0
3 changed files with 165 additions and 111 deletions

View File

@@ -25,6 +25,145 @@ using namespace std;
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
/// @brief Exchange MySQL Structure for Lease6
///
/// On the INSERT, SELECT and UPDATE statements, an array of MYSQL_BIND
/// structures must be built to reflect the data being inserted or retrieved
/// from the database.
///
/// Owing to the MySQL API, this process requires some intermediate variables
/// to hold things like length etc. This object holds the intermediate
/// variables and can:
/// 1. Build the MYSQL_BIND structures for a Lease6 object ready for passing
/// in to the MYSQL code.
/// 1. Copy information from the MYSQL_BIND structures into a Lease6 object.
class MySqlLease6Exchange {
public:
/// @brief Constructor
MySqlLease6Exchange() : false_(0), true_(1) {
}
/// @brief Create MYSQL_BIND objects for Lease6 Pointer
///
/// Fills in the bind_ objects for the Lease6 passed to it.
///
/// The MySQL documentation
///
/// @param lease Lease object to be added to the database
///
/// @return Pointer to MYSQL_BIND array holding the bind information.
/// This is a pointer to data internal to this object, and remains
/// valid only for as long as (1) this object is in existence and
/// (2) the lease object passed to it is in existence. The
/// caller should NOT delete it.
MYSQL_BIND* createBindFromLease(const Lease6Ptr& lease) {
// Store lease object to ensure it remains valid.
lease_ = lease;
// Ensure bind array clear.
memset(bind_, 0, sizeof(bind_));
// address: varchar(40)
addr6_ = lease_->addr_.toText();
addr6_length_ = addr6_.size();
bind_[0].buffer_type = MYSQL_TYPE_STRING;
bind_[0].buffer = const_cast<char*>(addr6_.c_str());
bind_[0].buffer_length = addr6_length_;
bind_[0].length = &addr6_length_;
// hwaddr: binary(20)
hwaddr_length_ = lease_->hwaddr_.size();
bind_[1].buffer_type = MYSQL_TYPE_BLOB;
bind_[1].buffer = reinterpret_cast<char*>(&(lease_->hwaddr_[0]));
bind_[1].buffer_length = hwaddr_length_;
bind_[1].length = &hwaddr_length_;
// client_id: varchar(128)
clientid_ = lease_->duid_->getDuid();
clientid_length_ = clientid_.size();
bind_[2].buffer_type = MYSQL_TYPE_BLOB;
bind_[2].buffer = reinterpret_cast<char*>(&(clientid_[0]));
bind_[2].buffer_length = clientid_length_;
bind_[2].length = &clientid_length_;
// The lease structure holds the client last transmission time (cltt_)
// and the valid lifetime (valid_lft_). For convenience for external
// tools, the data stored in the database is expiry time (expire) and
// lease time (lease+time). The relationship is given by:
//
// lease_time - valid_lft_
// expire = cltt_ + valid_lft_
//
MySqlLeaseMgr::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
expire_, lease_time_);
// lease_time: unsigned int
bind_[3].buffer_type = MYSQL_TYPE_LONG;
bind_[3].buffer = reinterpret_cast<char*>(&lease_time_);
bind_[3].is_unsigned = true_;
// expire: timestamp
bind_[4].buffer_type = MYSQL_TYPE_TIMESTAMP;
bind_[4].buffer = reinterpret_cast<char*>(&expire_);
bind_[4].buffer_length = sizeof(expire_);
// subnet_id: unsigned int
// Can use lease_->subnet_id_ directly as it is of type uint32_t.
bind_[5].buffer_type = MYSQL_TYPE_LONG;
bind_[5].buffer = reinterpret_cast<char*>(&lease_->subnet_id_);
bind_[5].is_unsigned = true_;
// pref_lifetime: unsigned int
// Can use lease_->preferred_lft_ directly as it is of type uint32_t.
bind_[6].buffer_type = MYSQL_TYPE_LONG;
bind_[6].buffer = reinterpret_cast<char*>(&lease_->preferred_lft_);
bind_[6].is_unsigned = true_;
// lease_type: tinyint
// Must convert to uint8_t as lease_->type_ is a LeaseType variable
lease_type_ = lease_->type_;
bind_[7].buffer_type = MYSQL_TYPE_TINY;
bind_[7].buffer = reinterpret_cast<char*>(&lease_type_);
bind_[7].is_unsigned = static_cast<my_bool>(1);
// iaid: unsigned int
// Can use lease_->iaid_ directly as it is of type uint32_t.
bind_[8].buffer_type = MYSQL_TYPE_LONG;
bind_[8].buffer = reinterpret_cast<char*>(&lease_->iaid_);
bind_[8].is_unsigned = true_;
// prefix_len: unsigned tinyint
// Can use lease_->prefixlen_ directly as it is uint32_t.
bind_[9].buffer_type = MYSQL_TYPE_TINY;
bind_[9].buffer = reinterpret_cast<char*>(&lease_->prefixlen_);
bind_[9].is_unsigned = true_;
return(bind_);
}
private:
std::string addr6_; ///< String form of address
unsigned long addr6_length_; ///< Length of the address
MYSQL_BIND bind_[10]; ///< Static array for speed of access
std::vector<uint8_t> clientid_; ///< Client identification
unsigned long clientid_length_; ///< Length of client ID
MYSQL_TIME expire_; ///< Lease expiry time
const my_bool false_; ///< "false" for MySql
unsigned long hwaddr_length_; ///< Length of hardware address
Lease6Ptr lease_; ///< Pointer to lease object
uint32_t lease_time_; ///< Lease time
uint8_t lease_type_; ///< Lease type
const my_bool true_; ///< "true_" for MySql
};
///
// Time conversion methods. // Time conversion methods.
// //
// Note that the MySQL TIMESTAMP data type (used for "expire") converts data // Note that the MySQL TIMESTAMP data type (used for "expire") converts data
@@ -33,7 +172,7 @@ namespace dhcp {
// must be local time. // must be local time.
void void
MySqlLeaseMgr::convertFromLeaseTime(time_t cltt, uint32_t valid_lft, MySqlLeaseMgr::convertToDatabaseTime(time_t cltt, uint32_t valid_lft,
MYSQL_TIME& expire, uint32_t& lease_time) { MYSQL_TIME& expire, uint32_t& lease_time) {
// Calculate expiry time and convert to various date/time fields. // Calculate expiry time and convert to various date/time fields.
@@ -56,7 +195,7 @@ MySqlLeaseMgr::convertFromLeaseTime(time_t cltt, uint32_t valid_lft,
} }
void void
MySqlLeaseMgr::convertToLeaseTime(const MYSQL_TIME& expire, uint32_t lease_time, MySqlLeaseMgr::convertFromDatabaseTime(const MYSQL_TIME& expire, uint32_t lease_time,
time_t& cltt, uint32_t& valid_lft) { time_t& cltt, uint32_t& valid_lft) {
valid_lft = lease_time; valid_lft = lease_time;
@@ -219,94 +358,9 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& /* lease */) {
bool bool
MySqlLeaseMgr::addLease(const Lease6Ptr& lease) { MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
my_bool MLM_FALSE = 0; // Create the MYSQL_BIND array for the lease
MYSQL_BIND bind[10]; MySqlLease6Exchange exchange;
memset(bind, 0, sizeof(bind)); MYSQL_BIND* bind = exchange.createBindFromLease(lease);
// address: varchar(40)
std::string addr6 = lease->addr_.toText();
unsigned long addr6_length = addr6.size();
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = const_cast<char*>(addr6.c_str());
bind[0].buffer_length = addr6_length;
bind[0].length = &addr6_length;
bind[0].is_null = &MLM_FALSE;
// hwaddr: binary(20)
unsigned long hwaddr_length = lease->hwaddr_.size();
bind[1].buffer_type = MYSQL_TYPE_BLOB;
bind[1].buffer = reinterpret_cast<char*>(&(lease->hwaddr_[0]));
bind[1].buffer_length = hwaddr_length;
bind[1].length = &hwaddr_length;
bind[1].is_null = &MLM_FALSE;
// client_id: varchar(128)
vector<uint8_t> clientid = lease->duid_->getDuid();
unsigned long clientid_length = clientid.size();
bind[2].buffer_type = MYSQL_TYPE_BLOB;
bind[2].buffer = reinterpret_cast<char*>(&(clientid[0]));
bind[2].buffer_length = clientid_length;
bind[2].length = &clientid_length;
bind[2].is_null = &MLM_FALSE;
// The lease structure holds the client last transmission time (cltt_)
// and the valid lifetime (valid_lft_). For convenience, the data stored
// in the database is expiry time (expire) and lease time (lease+time).
// The relationship is given by:
//
// lease_time - valid_lft_
// expire = cltt_ + valid_lft_
MYSQL_TIME mysql_expire;
uint32_t lease_time;
convertFromLeaseTime(lease->cltt_, lease->valid_lft_,
mysql_expire, lease_time);
// lease_time: unsigned int
bind[3].buffer_type = MYSQL_TYPE_LONG;
bind[3].buffer = reinterpret_cast<char*>(&lease_time);
bind[3].is_unsigned = 1;
bind[3].is_null = &MLM_FALSE;
// expire: timestamp
bind[4].buffer_type = MYSQL_TYPE_TIMESTAMP;
bind[4].buffer = reinterpret_cast<char*>(&mysql_expire);
bind[4].buffer_length = sizeof(mysql_expire);
bind[4].is_null = &MLM_FALSE;
// subnet_id: unsigned int
bind[5].buffer_type = MYSQL_TYPE_LONG;
bind[5].buffer = reinterpret_cast<char*>(&(lease->subnet_id_));
bind[5].is_unsigned = static_cast<my_bool>(1);
bind[5].is_null = &MLM_FALSE;
// pref_lifetime: unsigned int
bind[6].buffer_type = MYSQL_TYPE_LONG;
bind[6].buffer = reinterpret_cast<char*>(&(lease->preferred_lft_));
bind[6].is_unsigned = static_cast<my_bool>(1);
bind[6].is_null = &MLM_FALSE;
// lease_type: tinyint
uint8_t lease_type = lease->type_; // Needed for int -> uint8_t conversion
bind[7].buffer_type = MYSQL_TYPE_TINY;
bind[7].buffer = reinterpret_cast<char*>(&lease_type);
bind[7].is_unsigned = static_cast<my_bool>(1);
bind[7].is_null = &MLM_FALSE;
// iaid: unsigned int
bind[8].buffer_type = MYSQL_TYPE_LONG;
bind[8].buffer = reinterpret_cast<char*>(&(lease->iaid_));
bind[8].is_unsigned = static_cast<my_bool>(1);
bind[8].is_null = &MLM_FALSE;
// prefix_len: unsigned tinyint
bind[9].buffer_type = MYSQL_TYPE_TINY;
bind[9].buffer = reinterpret_cast<char*>(&(lease->prefixlen_));
bind[9].is_unsigned = static_cast<my_bool>(1);
bind[9].is_null = &MLM_FALSE;
// Bind the parameters to the statement // Bind the parameters to the statement
my_bool status = mysql_stmt_bind_param(statements_[INSERT_LEASE6], bind); my_bool status = mysql_stmt_bind_param(statements_[INSERT_LEASE6], bind);
@@ -458,8 +512,8 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
result->addr_ = addr; result->addr_ = addr;
result->hwaddr_ = vector<uint8_t>(&hwaddr[0], &hwaddr[hwaddr_length]); result->hwaddr_ = vector<uint8_t>(&hwaddr[0], &hwaddr[hwaddr_length]);
result->duid_.reset(new DUID(clientid, clientid_length)); result->duid_.reset(new DUID(clientid, clientid_length));
convertToLeaseTime(mysql_expire, lease_time, convertFromDatabaseTime(mysql_expire, lease_time,
result->cltt_, result->valid_lft_); result->cltt_, result->valid_lft_);
result->subnet_id_ = subnet_id; result->subnet_id_ = subnet_id;
result->preferred_lft_ = pref_lifetime; result->preferred_lft_ = pref_lifetime;
switch (lease_type) { switch (lease_type) {

View File

@@ -69,13 +69,13 @@ public:
/// @exception DbOperationError Database function failed /// @exception DbOperationError Database function failed
virtual bool addLease(const Lease6Ptr& lease); virtual bool addLease(const Lease6Ptr& lease);
/// @brief Returns existing IPv4 lease for specified IPv4 address and subnet_id /// @brief Return IPv4 lease for specified IPv4 address and subnet_id
/// ///
/// This method is used to get a lease for specific subnet_id. There can be /// This method is used to get a lease for specific subnet_id. There can be
/// at most one lease for any given subnet, so this method returns a single /// at most one lease for any given subnet, so this method returns a single
/// pointer. /// pointer.
/// ///
/// @param addr address of the searched lease /// @param addr address of the sought lease
/// @param subnet_id ID of the subnet the lease must belong to /// @param subnet_id ID of the subnet the lease must belong to
/// ///
/// @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)
@@ -254,11 +254,11 @@ public:
///@{ ///@{
/// The following methods are used to convert between times and time /// The following methods are used to convert between times and time
/// intervals stored in the server in the Lease object, and the times /// intervals stored in the Lease object, and the times stored in the
/// stored in the database. The reason for the difference is because /// database. The reason for the difference is because in the DHCP server,
/// in the DHCP server, the cltt (Client Time Since Last Transmission) /// the cltt (Client Time Since Last Transmission) is the natural data; in
/// is the natural data: in the lease file - which may be read by the /// the lease file - which may be read by the user - it is the expiry time
/// user - it is the expiry time of the lease. /// of the lease.
/// @brief Convert Lease Time to Database Times /// @brief Convert Lease Time to Database Times
/// ///
@@ -267,8 +267,8 @@ public:
/// is stored as lease_time (lease time) and expire (time of expiry of the /// is stored as lease_time (lease time) and expire (time of expiry of the
/// lease). They are related by the equations: /// lease). They are related by the equations:
/// ///
/// lease_time = valid_lft /// - lease_time = valid_lft
/// expire = cltt + valid_lft /// - expire = cltt + valid_lft
/// ///
/// This method converts from the times in the lease object into times /// This method converts from the times in the lease object into times
/// able to be added to the database. /// able to be added to the database.
@@ -280,7 +280,7 @@ public:
/// @param lease_time Reference to the time_t object where the lease time /// @param lease_time Reference to the time_t object where the lease time
/// will be put. /// will be put.
static static
void convertFromLeaseTime(time_t cltt, uint32_t valid_lft, void convertToDatabaseTime(time_t cltt, uint32_t valid_lft,
MYSQL_TIME& expire, uint32_t& lease_time); MYSQL_TIME& expire, uint32_t& lease_time);
/// @brief Convert Database Time to Lease Times /// @brief Convert Database Time to Lease Times
@@ -288,10 +288,10 @@ public:
/// Within the database, time is stored as lease_time (lease time) and /// Within the database, time is stored as lease_time (lease time) and
/// expire (time of expiry of the lease). In the DHCP server, the /// expire (time of expiry of the lease). In the DHCP server, the
/// information is stored as cltt (client last transmit time) and /// information is stored as cltt (client last transmit time) and
/// valid_lft (valid lifetime). These arr related by the equations: /// valid_lft (valid lifetime). These are related by the equations:
/// ///
/// valid_lft = lease_time /// - valid_lft = lease_time
/// cltt = expire - lease_time /// - cltt = expire - lease_time
/// ///
/// This method converts from the times in the database into times /// This method converts from the times in the database into times
/// able to be inserted into the lease object. /// able to be inserted into the lease object.
@@ -303,16 +303,16 @@ public:
/// is put. /// is put.
/// @param valid_lft Reference to location where valid lifetime is put. /// @param valid_lft Reference to location where valid lifetime is put.
static static
void convertToLeaseTime(const MYSQL_TIME& expire, uint32_t lease_time, void convertFromDatabaseTime(const MYSQL_TIME& expire, uint32_t lease_time,
time_t& cltt, uint32_t& valid_lft); time_t& cltt, uint32_t& valid_lft);
///@} ///@}
private: private:
/// @brief Enum of Statements /// @brief Statement Tags
/// ///
/// This is provided to set indexes into a list of prepared statements. /// The contents of the enum are indexes into the list of SQL statements
enum StatementIndex { enum StatementIndex {
GET_LEASE6, GET_LEASE6,
GET_VERSION, // Obtain version number GET_VERSION, // Obtain version number

View File

@@ -127,7 +127,7 @@ TEST_F(MySqlLeaseMgrTest, CheckTimeConversion) {
MYSQL_TIME expire; MYSQL_TIME expire;
uint32_t lease_time; uint32_t lease_time;
MySqlLeaseMgr::convertFromLeaseTime(cltt, valid_lft, expire, lease_time); MySqlLeaseMgr::convertToDatabaseTime(cltt, valid_lft, expire, lease_time);
EXPECT_EQ(valid_lft, lease_time); EXPECT_EQ(valid_lft, lease_time);
EXPECT_LE(2012, expire.year); // Code was written in 2012 EXPECT_LE(2012, expire.year); // Code was written in 2012
EXPECT_EQ(0, expire.second_part); EXPECT_EQ(0, expire.second_part);
@@ -136,7 +136,7 @@ TEST_F(MySqlLeaseMgrTest, CheckTimeConversion) {
// Convert back // Convert back
time_t converted_cltt = 0; time_t converted_cltt = 0;
uint32_t converted_valid_lft = 0; uint32_t converted_valid_lft = 0;
MySqlLeaseMgr::convertToLeaseTime(expire, lease_time, converted_cltt, MySqlLeaseMgr::convertFromDatabaseTime(expire, lease_time, converted_cltt,
converted_valid_lft); converted_valid_lft);
EXPECT_EQ(cltt, converted_cltt); EXPECT_EQ(cltt, converted_cltt);
EXPECT_EQ(valid_lft, converted_valid_lft); EXPECT_EQ(valid_lft, converted_valid_lft);