From: Stephen Morris Date: Mon, 22 Oct 2012 09:49:51 +0000 (+0100) Subject: [2342] Move creation of MYSQL_BIND array for lease addition to separate class X-Git-Tag: trac2487_base~1^2~60 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a64f318cb0ea2ea0ef73145071fb04b85f5853ec;p=thirdparty%2Fkea.git [2342] Move creation of MYSQL_BIND array for lease addition to separate class --- diff --git a/src/lib/dhcp/mysql_lease_mgr.cc b/src/lib/dhcp/mysql_lease_mgr.cc index 31fcfa8b08..d411e36d2d 100644 --- a/src/lib/dhcp/mysql_lease_mgr.cc +++ b/src/lib/dhcp/mysql_lease_mgr.cc @@ -25,6 +25,145 @@ using namespace std; namespace isc { 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(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(&(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(&(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(&lease_time_); + bind_[3].is_unsigned = true_; + + // expire: timestamp + bind_[4].buffer_type = MYSQL_TYPE_TIMESTAMP; + bind_[4].buffer = reinterpret_cast(&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(&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(&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(&lease_type_); + bind_[7].is_unsigned = static_cast(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(&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(&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 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. // // Note that the MySQL TIMESTAMP data type (used for "expire") converts data @@ -33,7 +172,7 @@ namespace dhcp { // must be local time. 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) { // Calculate expiry time and convert to various date/time fields. @@ -56,7 +195,7 @@ MySqlLeaseMgr::convertFromLeaseTime(time_t cltt, uint32_t valid_lft, } 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) { valid_lft = lease_time; @@ -219,94 +358,9 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& /* lease */) { bool MySqlLeaseMgr::addLease(const Lease6Ptr& lease) { - my_bool MLM_FALSE = 0; - MYSQL_BIND bind[10]; - memset(bind, 0, sizeof(bind)); - - // 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(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(&(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 clientid = lease->duid_->getDuid(); - unsigned long clientid_length = clientid.size(); - - bind[2].buffer_type = MYSQL_TYPE_BLOB; - bind[2].buffer = reinterpret_cast(&(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(&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(&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(&(lease->subnet_id_)); - bind[5].is_unsigned = static_cast(1); - bind[5].is_null = &MLM_FALSE; - - // pref_lifetime: unsigned int - bind[6].buffer_type = MYSQL_TYPE_LONG; - bind[6].buffer = reinterpret_cast(&(lease->preferred_lft_)); - bind[6].is_unsigned = static_cast(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(&lease_type); - bind[7].is_unsigned = static_cast(1); - bind[7].is_null = &MLM_FALSE; - - // iaid: unsigned int - bind[8].buffer_type = MYSQL_TYPE_LONG; - bind[8].buffer = reinterpret_cast(&(lease->iaid_)); - bind[8].is_unsigned = static_cast(1); - bind[8].is_null = &MLM_FALSE; - - // prefix_len: unsigned tinyint - bind[9].buffer_type = MYSQL_TYPE_TINY; - bind[9].buffer = reinterpret_cast(&(lease->prefixlen_)); - bind[9].is_unsigned = static_cast(1); - bind[9].is_null = &MLM_FALSE; + // Create the MYSQL_BIND array for the lease + MySqlLease6Exchange exchange; + MYSQL_BIND* bind = exchange.createBindFromLease(lease); // Bind the parameters to the statement 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->hwaddr_ = vector(&hwaddr[0], &hwaddr[hwaddr_length]); result->duid_.reset(new DUID(clientid, clientid_length)); - convertToLeaseTime(mysql_expire, lease_time, - result->cltt_, result->valid_lft_); + convertFromDatabaseTime(mysql_expire, lease_time, + result->cltt_, result->valid_lft_); result->subnet_id_ = subnet_id; result->preferred_lft_ = pref_lifetime; switch (lease_type) { diff --git a/src/lib/dhcp/mysql_lease_mgr.h b/src/lib/dhcp/mysql_lease_mgr.h index 1633d625b9..cebe1ecb14 100644 --- a/src/lib/dhcp/mysql_lease_mgr.h +++ b/src/lib/dhcp/mysql_lease_mgr.h @@ -69,13 +69,13 @@ public: /// @exception DbOperationError Database function failed 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 /// at most one lease for any given subnet, so this method returns a single /// 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 /// /// @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 - /// intervals stored in the server in the Lease object, and the times - /// stored in the database. The reason for the difference is because - /// in the DHCP server, the cltt (Client Time Since Last Transmission) - /// is the natural data: in the lease file - which may be read by the - /// user - it is the expiry time of the lease. + /// intervals stored in the Lease object, and the times stored in the + /// database. The reason for the difference is because in the DHCP server, + /// the cltt (Client Time Since Last Transmission) is the natural data; in + /// the lease file - which may be read by the user - it is the expiry time + /// of the lease. /// @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 /// lease). They are related by the equations: /// - /// lease_time = valid_lft - /// expire = cltt + valid_lft + /// - lease_time = valid_lft + /// - expire = cltt + valid_lft /// /// This method converts from the times in the lease object into times /// 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 /// will be put. 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); /// @brief Convert Database Time to Lease Times @@ -288,10 +288,10 @@ public: /// Within the database, time is stored as lease_time (lease time) and /// expire (time of expiry of the lease). In the DHCP server, the /// 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 - /// cltt = expire - lease_time + /// - valid_lft = lease_time + /// - cltt = expire - lease_time /// /// This method converts from the times in the database into times /// able to be inserted into the lease object. @@ -303,16 +303,16 @@ public: /// is put. /// @param valid_lft Reference to location where valid lifetime is put. static - void convertToLeaseTime(const MYSQL_TIME& expire, uint32_t lease_time, - time_t& cltt, uint32_t& valid_lft); + void convertFromDatabaseTime(const MYSQL_TIME& expire, uint32_t lease_time, + time_t& cltt, uint32_t& valid_lft); ///@} 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 { GET_LEASE6, GET_VERSION, // Obtain version number diff --git a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc index a4626d8278..c1fdc02aa1 100644 --- a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc +++ b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc @@ -127,7 +127,7 @@ TEST_F(MySqlLeaseMgrTest, CheckTimeConversion) { MYSQL_TIME expire; 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_LE(2012, expire.year); // Code was written in 2012 EXPECT_EQ(0, expire.second_part); @@ -136,7 +136,7 @@ TEST_F(MySqlLeaseMgrTest, CheckTimeConversion) { // Convert back time_t converted_cltt = 0; uint32_t converted_valid_lft = 0; - MySqlLeaseMgr::convertToLeaseTime(expire, lease_time, converted_cltt, + MySqlLeaseMgr::convertFromDatabaseTime(expire, lease_time, converted_cltt, converted_valid_lft); EXPECT_EQ(cltt, converted_cltt); EXPECT_EQ(valid_lft, converted_valid_lft);