Browse Source

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

Stephen Morris 12 years ago
parent
commit
a64f318cb0

+ 146 - 92
src/lib/dhcp/mysql_lease_mgr.cc

@@ -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;
-    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<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;
+    // Create the MYSQL_BIND array for the lease
+    MySqlLease6Exchange exchange;
+    MYSQL_BIND* bind = exchange.createBindFromLease(lease);
 
 
     // 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,
-                           result->cltt_, result->valid_lft_);
+        convertFromDatabaseTime(mysql_expire, lease_time,
+                                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) {

+ 17 - 17
src/lib/dhcp/mysql_lease_mgr.h

@@ -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
-    /// 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
     /// @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
-    /// expire = cltt + valid_lft
+    /// - lease_time = 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
-    /// cltt = expire - lease_time
+    /// - valid_lft = 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,
-                            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:
 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

+ 2 - 2
src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc

@@ -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);