BIND 10 trac2342, updated. 47be873b787d2a1a355b04cb6e4ec5dce905f180 [2342] Incorporate Trac2142 changes
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Oct 22 19:45:46 UTC 2012
The branch, trac2342 has been updated
via 47be873b787d2a1a355b04cb6e4ec5dce905f180 (commit)
via 1d70d3df4d008f881ab31dfed3e8805da63a3c65 (commit)
via fdbdac116c417a4e3236669554da431c66cbea09 (commit)
via 599bfb2239028e494c88143cc9c0a708f8b7f24b (commit)
via a64f318cb0ea2ea0ef73145071fb04b85f5853ec (commit)
from 93ffcbb3ecdb4f882bb833addb68908446f7ae77 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 47be873b787d2a1a355b04cb6e4ec5dce905f180
Author: Stephen Morris <stephen at isc.org>
Date: Mon Oct 22 20:43:49 2012 +0100
[2342] Incorporate Trac2142 changes
commit 1d70d3df4d008f881ab31dfed3e8805da63a3c65
Author: Stephen Morris <stephen at isc.org>
Date: Mon Oct 22 20:05:35 2012 +0100
[2342] Enable MySQL support with flag in configure.ac
commit fdbdac116c417a4e3236669554da431c66cbea09
Author: Stephen Morris <stephen at isc.org>
Date: Mon Oct 22 16:07:34 2012 +0100
[2342] Added deleteLease6 functionality
commit 599bfb2239028e494c88143cc9c0a708f8b7f24b
Author: Stephen Morris <stephen at isc.org>
Date: Mon Oct 22 13:01:40 2012 +0100
[2342] INSERT and GET tests now working
... after moving creation of MYSQL_BIND structures to a separate class.
commit a64f318cb0ea2ea0ef73145071fb04b85f5853ec
Author: Stephen Morris <stephen at isc.org>
Date: Mon Oct 22 10:49:51 2012 +0100
[2342] Move creation of MYSQL_BIND array for lease addition to separate class
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 63 ++-
src/lib/dhcp/Makefile.am | 25 +-
src/lib/dhcp/dhcpdb_create.mysql | 92 ++++
src/lib/dhcp/lease_mgr_factory.cc | 7 +-
src/lib/dhcp/mysql_lease_mgr.cc | 563 +++++++++++++++---------
src/lib/dhcp/mysql_lease_mgr.h | 43 +-
src/lib/dhcp/tests/Makefile.am | 9 +
src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc | 130 ++++--
8 files changed, 655 insertions(+), 277 deletions(-)
create mode 100644 src/lib/dhcp/dhcpdb_create.mysql
-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 72c7be2..11ecbe4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,4 @@
-# -*- Autoconf -*-
-# Process this file with autoconf to produce a configure script.
+CXXFLAGS Process this file with autoconf to produce a configure script.
AC_PREREQ([2.59])
AC_INIT(bind10-devel, 20120817, bind10-dev at isc.org)
@@ -730,6 +729,64 @@ AC_LINK_IFELSE(
)
CPPFLAGS=$CPPFLAGS_SAVED
LIBS=$LIBS_SAVED
+#===
+
+# Check for MySql. The path to the mysql_config program is given with
+# the --with-mysql-config (default to /usr/bin/mysql-config).
+
+mysql_config="no"
+AC_ARG_WITH([mysql-config],
+ AC_HELP_STRING([--with-mysql-config=PATH],
+ [specify the path to the mysql_config script]),
+ [mysql_config="$withval"])
+
+if test "${mysql_config}" = "yes" ; then
+ MYSQL_CONFIG="/usr/bin/mysql_config"
+elif test "${mysql_config}" != "no" ; then
+ MYSQL_CONFIG="${withval}"
+fi
+
+if test "$MYSQL_CONFIG" != "" ; then
+ if test -d "$MYSQL_CONFIG" ; then
+ AC_MSG_ERROR([Specified mysql_config program ${MYSQL_CONFIG} is a directory])
+ fi
+ if ! test -x "$MYSQL_CONFIG" ; then
+ AC_MSG_ERROR([--with-mysql-config should point to a mysql_config program])
+ fi
+
+ MYSQL_CPPFLAGS=`$MYSQL_CONFIG --cflags`
+ MYSQL_LIBS=`$MYSQL_CONFIG --libs`
+
+ AC_SUBST(MYSQL_CPPFLAGS)
+ AC_SUBST(MYSQL_LIBS)
+
+ # Check that a simple program using MySQL functions can compile and link.
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ LIBS_SAVED="$LIBS"
+
+ CPPFLAGS="$MYSQL_CPPFLAGS $CPPFLAGS"
+ LIBS="$MYSQL_LIBS $LIBS"
+
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([#include <mysql/mysql.h>],
+ [MYSQL mysql_handle;
+ (void) mysql_init(&mysql_handle);
+ ])],
+ [AC_MSG_RESULT([checking for MySQL headers and library... yes])],
+ [AC_MSG_RESULT([checking for MySQL headers and library... no])
+ AC_MSG_ERROR([Needs MySQL library])]
+ )
+
+ CPPFLAGS=$CPPFLAGS_SAVED
+ LIBS=$LIBS_SAVED
+
+ # Note that MYSQL is present in the config.h file
+ AC_DEFINE([HAVE_MYSQL], [1], [MySQL is present])
+fi
+
+# ... and at the shell level, so Makefile.am can take action depending on this.
+AM_CONDITIONAL(HAVE_MYSQL, test "$MYSQL_CONFIG" != "")
+
# Check for log4cplus
log4cplus_path="yes"
@@ -1409,6 +1466,8 @@ dnl includes too
${LOG4CPLUS_LIBS}
SQLite: $SQLITE_CFLAGS
$SQLITE_LIBS
+ MySQL: $MYSQL_CPPFLAGS
+ $MYSQL_LIBS
Features:
$enable_features
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index e208884..74c4491 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -2,6 +2,9 @@ SUBDIRS = . tests
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
+if HAVE_MYSQL
+AM_CPPFLAGS += $(MYSQL_CPPFLAGS)
+endif
AM_CXXFLAGS = $(B10_CXXFLAGS)
@@ -24,7 +27,9 @@ libb10_dhcp___la_SOURCES += iface_mgr_sun.cc
libb10_dhcp___la_SOURCES += lease_mgr.cc lease_mgr.h
libb10_dhcp___la_SOURCES += lease_mgr_factory.cc lease_mgr_factory.h
libb10_dhcp___la_SOURCES += libdhcp++.cc libdhcp++.h
+if HAVE_MYSQL
libb10_dhcp___la_SOURCES += mysql_lease_mgr.cc mysql_lease_mgr.h
+endif
libb10_dhcp___la_SOURCES += option4_addrlst.cc option4_addrlst.h
libb10_dhcp___la_SOURCES += option6_addrlst.cc option6_addrlst.h
libb10_dhcp___la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
@@ -33,11 +38,21 @@ libb10_dhcp___la_SOURCES += option.cc option.h
libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
libb10_dhcp___la_SOURCES += pkt6.cc pkt6.h
+libb10_dhcp___la_CXXFLAGS = $(AM_CXXFLAGS)
+libb10_dhcp___la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
+libb10_dhcp___la_LIBADD = $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
+libb10_dhcp___la_LIBADD += $(top_builddir)/src/lib/util/libb10-util.la
+libb10_dhcp___la_LDFLAGS = -no-undefined -version-info 2:0:0
+if HAVE_MYSQL
+libb10_dhcp___la_LDFLAGS += $(MYSQL_LIBS)
+endif
+
libb10_dhcpsrv_la_SOURCES = cfgmgr.cc cfgmgr.h
libb10_dhcpsrv_la_SOURCES += pool.cc pool.h
libb10_dhcpsrv_la_SOURCES += subnet.cc subnet.h
libb10_dhcpsrv_la_SOURCES += triplet.h
libb10_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
+
libb10_dhcpsrv_la_CXXFLAGS = $(AM_CXXFLAGS)
libb10_dhcpsrv_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
libb10_dhcpsrv_la_LIBADD = $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
@@ -46,14 +61,12 @@ libb10_dhcpsrv_la_LDFLAGS = -no-undefined -version-info 2:0:0
EXTRA_DIST = README
-libb10_dhcp___la_CXXFLAGS = $(AM_CXXFLAGS)
-libb10_dhcp___la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
-libb10_dhcp___la_LIBADD = $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
-libb10_dhcp___la_LIBADD += $(top_builddir)/src/lib/util/libb10-util.la
-libb10_dhcp___la_LDFLAGS = -no-undefined -version-info 2:0:0
-
if USE_CLANGPP
# Disable unused parameter warning caused by some of the
# Boost headers when compiling with clang.
libb10_dhcp___la_CXXFLAGS += -Wno-unused-parameter
endif
+
+# Distribute MySQL schema creation script
+EXTRA_DIST += dhcpdb_create.mysql
+dist_pkgdata_DATA = dhcpdb_create.mysql
diff --git a/src/lib/dhcp/dhcpdb_create.mysql b/src/lib/dhcp/dhcpdb_create.mysql
new file mode 100644
index 0000000..e4b7771
--- /dev/null
+++ b/src/lib/dhcp/dhcpdb_create.mysql
@@ -0,0 +1,92 @@
+# Copyright (C) 2012 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# This is the BIND 10 DHCP schema specification for MySQL.
+#
+# The schema is reasonably portable (with the exception of the engine
+# specification, which is MySQL-specific). Minor changes might be needed for
+# other databases.
+
+# To create the schema, either type the command:
+#
+# mysql -u <user> -p <password> <database> < dhcpdb_create.mysql
+#
+# ... at the command prompt, or log in to the MySQL database and at the "mysql>"
+# prompt, issue the command:
+#
+# source dhcpdb_create.mysql
+
+# Holds the IPv4 leases.
+CREATE TABLE lease4 (
+ address INT UNSIGNED UNIQUE NOT NULL, # IPv4 address
+ hwaddr VARBINARY(20), # Hardware address
+ client_id VARBINARY(128), # Client ID
+ lease_time INT UNSIGNED, # Length of the lease (seconds)
+ expire TIMESTAMP, # Expiration time of the lease
+ subnet_id INT UNSIGNED # Subnet identification
+ ) ENGINE = INNODB;
+
+# Holds the IPv6 leases
+CREATE TABLE lease6 (
+ address VARCHAR(40) UNIQUE NOT NULL, # IPv6 address (actually 39 is max)
+ hwaddr VARBINARY(20), # Hardware address
+ client_id VARBINARY(128), # Client ID
+ lease_time INT UNSIGNED, # Length of the lease (seconds)
+ expire TIMESTAMP, # Expiration time of the lease
+ subnet_id INT UNSIGNED, # Subnet identification
+ pref_lifetime INT UNSIGNED, # Preferred lifetime
+ lease_type TINYINT, # Lease type
+ iaid INT UNSIGNED, # IA ID
+ prefix_len TINYINT UNSIGNED # For IA_PD only
+ ) ENGINE = INNODB;
+
+# ... and a definition of lease6 types. This table is a convenience for
+# users of the database - if they want to view the lease table and use the
+# type names, they can join this table with the lease6 table
+CREATE TABLE lease6_types (
+ lease_type TINYINT UNIQUE NOT NULL, # Lease type code
+ name VARCHAR(5) # Name of the lease type
+ );
+INSERT INTO lease6_types VALUES (0, "IA_NA"); # Non-temporary v6 addresses
+INSERT INTO lease6_types VALUES (1, "IA_TA"); # Temporary v6 addresses
+INSERT INTO lease6_types VALUES (2, "IA_PD"); # Prefix delegations
+
+# Finally, the version of the schema. We start at 0.1 during development.
+# This table is only modified during schema upgrades. For historical reasons
+# (related to the names of the columns in the BIND 10 DNS database file), the
+# first column is called "version" and not "major".
+CREATE TABLE schema_version (
+ version INT NOT NULL, # Major version number
+ minor INT NOT NULL # Minor version number
+ );
+INSERT INTO schema_version VALUES (0, 1);
+
+COMMIT;
+
+# It is likely that additional indexes will be needed. However, the
+# increase in lookup performance from these will come at the expense
+# of a decrease in performance during insert operations due to the need
+# to update the indexes. For this reason, the need for additional indexes
+# will be determined by experiment during performance tests.
+#
+# The most likely additional indexes will cover the following columns:
+#
+# expire
+# To speed up the deletion of expired leases from the database.
+#
+# hwaddr and client_id
+# For lease stability: if a client requests a new lease, try to find an
+# existing or recently expired lease for it so that it can keep using the
+# same IP address.
diff --git a/src/lib/dhcp/lease_mgr_factory.cc b/src/lib/dhcp/lease_mgr_factory.cc
index 0a8c3aa..d69f8af 100644
--- a/src/lib/dhcp/lease_mgr_factory.cc
+++ b/src/lib/dhcp/lease_mgr_factory.cc
@@ -14,10 +14,6 @@
#include "config.h"
-// TEMP
-#define HAVE_MYSQL 1
-
-
#include <algorithm>
#include <iostream>
#include <iterator>
@@ -30,7 +26,10 @@
#include <boost/algorithm/string.hpp>
#include <exceptions/exceptions.h>
#include <dhcp/lease_mgr_factory.h>
+
+#ifdef HAVE_MYSQL
#include <dhcp/mysql_lease_mgr.h>
+#endif
using namespace std;
diff --git a/src/lib/dhcp/mysql_lease_mgr.cc b/src/lib/dhcp/mysql_lease_mgr.cc
index 31fcfa8..aac0682 100644
--- a/src/lib/dhcp/mysql_lease_mgr.cc
+++ b/src/lib/dhcp/mysql_lease_mgr.cc
@@ -17,6 +17,8 @@
#include <string>
#include <config.h>
#include <time.h>
+#include <mysql/mysqld_error.h>
+
#include <dhcp/mysql_lease_mgr.h>
#include <asiolink/io_address.h>
@@ -25,6 +27,292 @@ using namespace std;
namespace isc {
namespace dhcp {
+/// @brief Exchange MySQL and Lease6 Data
+///
+/// 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, the 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* CreateBindForSend(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_);
+ }
+
+ /// @brief Create BIND array to receive data
+ ///
+ /// Creates a MYSQL_BIND array to receive Lease6 data from the database.
+ /// After data is successfully received, getLeaseData() is used to copy
+ /// it to a Lease6 object.
+ ///
+ /// @return Pointer to MYSQL_BIND array for data reception. This array is
+ /// valid only for as long as this MySqlLease6Exchange object is
+ /// in existence.
+ MYSQL_BIND* createBindForReceive() {
+
+ // Ensure bind array clear.
+ memset(bind_, 0, sizeof(bind_));
+ memset(error_, 0, sizeof(error_));
+
+ // address: varchar
+ // A Lease6_ address has a maximum of 39 characters. The array is
+ // a few bites longer than this to guarantee that we can always null
+ // terminate it.
+ addr6_length_ = sizeof(addr6_buffer_) - 1;
+ bind_[0].buffer_type = MYSQL_TYPE_STRING;
+ bind_[0].buffer = addr6_buffer_;
+ bind_[0].buffer_length = addr6_length_;
+ bind_[0].length = &addr6_length_;
+ bind_[0].error = &error_[0];
+
+ // hwaddr: varbinary(20)
+ hwaddr_length_ = sizeof(hwaddr_buffer_);
+ bind_[1].buffer_type = MYSQL_TYPE_BLOB;
+ bind_[1].buffer = reinterpret_cast<char*>(hwaddr_buffer_);
+ bind_[1].buffer_length = hwaddr_length_;
+ bind_[1].length = &hwaddr_length_;
+ bind_[2].error = &error_[1];
+
+ // client_id: varbinary(128)
+ clientid_length_ = sizeof(clientid_buffer_);
+ bind_[2].buffer_type = MYSQL_TYPE_BLOB;
+ bind_[2].buffer = reinterpret_cast<char*>(clientid_buffer_);
+ bind_[2].buffer_length = clientid_length_;
+ bind_[2].length = &clientid_length_;
+ bind_[2].error = &error_[2];
+
+ // lease_time: unsigned int
+ bind_[3].buffer_type = MYSQL_TYPE_LONG;
+ bind_[3].buffer = reinterpret_cast<char*>(&lease_time_);
+ bind_[3].is_unsigned = true_;
+ bind_[3].error = &error_[3];
+
+ // expire: timestamp
+ bind_[4].buffer_type = MYSQL_TYPE_TIMESTAMP;
+ bind_[4].buffer = reinterpret_cast<char*>(&expire_);
+ bind_[4].buffer_length = sizeof(expire_);
+ bind_[4].error = &error_[4];
+
+ // subnet_id: unsigned int
+ bind_[5].buffer_type = MYSQL_TYPE_LONG;
+ bind_[5].buffer = reinterpret_cast<char*>(&subnet_id_);
+ bind_[5].is_unsigned = true_;
+ bind_[5].error = &error_[5];
+
+ // pref_lifetime: unsigned int
+ bind_[6].buffer_type = MYSQL_TYPE_LONG;
+ bind_[6].buffer = reinterpret_cast<char*>(&pref_lifetime_);
+ bind_[6].is_unsigned = true_;
+ bind_[6].error = &error_[6];
+
+ // lease_type: tinyint
+ bind_[7].buffer_type = MYSQL_TYPE_TINY;
+ bind_[7].buffer = reinterpret_cast<char*>(&lease_type_);
+ bind_[7].is_unsigned = true_;
+ bind_[7].error = &error_[7];
+
+ // iaid: unsigned int
+ bind_[8].buffer_type = MYSQL_TYPE_LONG;
+ bind_[8].buffer = reinterpret_cast<char*>(&iaid_);
+ bind_[8].is_unsigned = true_;
+ bind_[8].error = &error_[8];
+
+ // prefix_len: unsigned tinyint
+ bind_[9].buffer_type = MYSQL_TYPE_TINY;
+ bind_[9].buffer = reinterpret_cast<char*>(&prefixlen_);
+ bind_[9].is_unsigned = true_;
+ bind_[9].error = &error_[9];
+
+ return (bind_);
+ }
+
+ /// @brief Copy Received Data into Lease6 Object
+ ///
+ /// Called after the MYSQL_BIND array created by createBindForReceive()
+ /// has been used, this copies data from the internal member vairables
+ /// into a Lease6 object.
+ ///
+ /// @return Lease6Ptr Pointer to a Lease6 object holding the relevant
+ /// data.
+ ///
+ /// @exception BadValue Unable to convert Lease Type value in database
+ Lease6Ptr getLeaseData() {
+
+ // Create the object to be returned.
+ Lease6Ptr result(new Lease6());
+
+ // Success - put the data in the lease object
+ addr6_buffer_[addr6_length_] = '\0';
+ std::string address = addr6_buffer_;
+ result->addr_ = isc::asiolink::IOAddress(address);
+
+ result->hwaddr_ = vector<uint8_t>(&hwaddr_buffer_[0],
+ &hwaddr_buffer_[hwaddr_length_]);
+ result->duid_.reset(new DUID(clientid_buffer_, clientid_length_));
+ MySqlLeaseMgr::convertFromDatabaseTime(expire_, lease_time_,
+ result->cltt_,
+ result->valid_lft_);
+ result->subnet_id_ = subnet_id_;
+ result->preferred_lft_ = pref_lifetime_;
+
+ // We can't convert from a numeric value to an enum, hence:
+ switch (lease_type_) {
+ case Lease6::LEASE_IA_NA:
+ result->type_ = Lease6::LEASE_IA_NA;
+ break;
+
+ case Lease6::LEASE_IA_TA:
+ result->type_ = Lease6::LEASE_IA_TA;
+ break;
+
+ case Lease6::LEASE_IA_PD:
+ result->type_ = Lease6::LEASE_IA_PD;
+ break;
+
+ default:
+ isc_throw(BadValue, "invalid lease type returned");
+ }
+ result->iaid_ = iaid_;
+ result->prefixlen_ = prefixlen_;
+
+ return (result);
+ }
+
+private:
+ // Note: All array legths are equal to the corresponding variable in the
+ // schema.
+ std::string addr6_; ///< String form of address
+ char addr6_buffer_[42]; ///< Character array form of V6 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
+ uint8_t clientid_buffer_[128]; ///< Buffer form of client ID
+ unsigned long clientid_length_; ///< Length of client ID
+ my_bool error_[10]; ///< For error reporting
+ MYSQL_TIME expire_; ///< Lease expiry time
+ const my_bool false_; ///< "false" for MySql
+ uint8_t hwaddr_buffer_[20]; ///< Hardware address buffer
+ unsigned long hwaddr_length_; ///< Length of hardware address
+ uint32_t iaid_; ///< Identity association ID
+ Lease6Ptr lease_; ///< Pointer to lease object
+ uint32_t lease_time_; ///< 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
+};
+
+
+
// Time conversion methods.
//
// Note that the MySQL TIMESTAMP data type (used for "expire") converts data
@@ -33,7 +321,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,8 +344,9 @@ MySqlLeaseMgr::convertFromLeaseTime(time_t cltt, uint32_t valid_lft,
}
void
-MySqlLeaseMgr::convertToLeaseTime(const MYSQL_TIME& expire, uint32_t lease_time,
- time_t& cltt, uint32_t& valid_lft) {
+MySqlLeaseMgr::convertFromDatabaseTime(const MYSQL_TIME& expire,
+ uint32_t lease_time, time_t& cltt,
+ uint32_t& valid_lft) {
valid_lft = lease_time;
// Copy across fields from MYSQL_TIME structure.
@@ -161,8 +450,10 @@ MySqlLeaseMgr::prepareStatements() {
raw_statements_.resize(NUM_STATEMENTS, std::string(""));
// Now allocate the statements
+ prepareStatement(DELETE_LEASE6,
+ "DELETE FROM lease6 WHERE address = ?");
prepareStatement(GET_LEASE6,
- "SELECT hwaddr, client_id, "
+ "SELECT address, hwaddr, client_id, "
"lease_time, expire, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len "
"FROM lease6 WHERE address = ?");
@@ -219,105 +510,30 @@ 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<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.CreateBindForSend(lease);
// Bind the parameters to the statement
- my_bool status = mysql_stmt_bind_param(statements_[INSERT_LEASE6], bind);
+ int status = mysql_stmt_bind_param(statements_[INSERT_LEASE6], bind);
checkError(status, INSERT_LEASE6, "unable to bind parameters");
// Execute the statement
status = mysql_stmt_execute(statements_[INSERT_LEASE6]);
- checkError(status, INSERT_LEASE6, "unable to execute");
+ if (status != 0) {
- // ... and find out whether a row as inserted.
- return (mysql_stmt_affected_rows(statements_[INSERT_LEASE6]) == 1);
+ // Failure: check for the special case of duplicate entry. If this is
+ // the case, we return false to indicate that the row was not added.
+ // Otherwise we throw an exception.
+ if (mysql_errno(mysql_) == ER_DUP_ENTRY) {
+ return (false);
+ }
+ checkError(status, INSERT_LEASE6, "unable to execute");
+ }
+
+ // Insert succeeded
+ return (true);
}
Lease4Ptr
@@ -355,9 +571,6 @@ MySqlLeaseMgr::getLease4(const ClientId& /* clientid */,
Lease6Ptr
MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
- my_bool MLM_FALSE = 0; // MySqlLeaseMgr false
- my_bool MLM_TRUE = 1; // MySqlLeaseMgr true
-
// Set up the WHERE clause value
MYSQL_BIND inbind[1];
memset(inbind, 0, sizeof(inbind));
@@ -369,80 +582,16 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
inbind[0].buffer = const_cast<char*>(addr6.c_str());
inbind[0].buffer_length = addr6_length;
inbind[0].length = &addr6_length;
- inbind[0].is_null = &MLM_FALSE;
- // Bind the parameters to the statement
- my_bool status = mysql_stmt_bind_param(statements_[GET_LEASE6], inbind);
- checkError(status, GET_LEASE6, "unable to bind WHERE clause parameter");
+ // Set up the SELECT clause
+ MySqlLease6Exchange exchange;
+ MYSQL_BIND* outbind = exchange.createBindForReceive();
- // Output values
- MYSQL_BIND outbind[9];
- memset(outbind, 0, sizeof(outbind));
-
- // address: Not obtained - because of the WHERE clause, it will always be
- // the same as the input parameter.
-
- // hwaddr: varbinary(20)
- uint8_t hwaddr[20];
- unsigned long hwaddr_length;
-
- outbind[0].buffer_type = MYSQL_TYPE_BLOB;
- outbind[0].buffer = reinterpret_cast<char*>(hwaddr);
- outbind[0].buffer_length = sizeof(hwaddr);
- outbind[0].length = &hwaddr_length;
-
- // client_id: varbinary(128)
- uint8_t clientid[128];
- unsigned long clientid_length;
-
- outbind[1].buffer_type = MYSQL_TYPE_BLOB;
- outbind[1].buffer = reinterpret_cast<char*>(clientid);
- outbind[1].buffer_length = sizeof(clientid);
- outbind[1].length = &clientid_length;
-
- // lease_time: unsigned int
- unsigned lease_time;
- outbind[2].buffer_type = MYSQL_TYPE_LONG;
- outbind[2].buffer = reinterpret_cast<char*>(&lease_time);
- outbind[2].is_unsigned = MLM_TRUE;
-
- // expire: timestamp
- MYSQL_TIME mysql_expire;
- outbind[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
- outbind[3].buffer = reinterpret_cast<char*>(&mysql_expire);
- outbind[3].buffer_length = sizeof(mysql_expire);
-
- // subnet_id: unsigned int
- unsigned subnet_id;
- outbind[4].buffer_type = MYSQL_TYPE_LONG;
- outbind[4].buffer = reinterpret_cast<char*>(&subnet_id);
- outbind[4].is_unsigned = MLM_TRUE;
-
- // pref_lifetime: unsigned int
- unsigned pref_lifetime;
- outbind[5].buffer_type = MYSQL_TYPE_LONG;
- outbind[5].buffer = reinterpret_cast<char*>(&pref_lifetime);
- outbind[5].is_unsigned = MLM_TRUE;
-
- // lease_type: tinyint
- uint8_t lease_type;
- outbind[6].buffer_type = MYSQL_TYPE_TINY;
- outbind[6].buffer = reinterpret_cast<char*>(&lease_type);
- outbind[6].is_unsigned = MLM_TRUE;
-
- // iaid: unsigned int
- unsigned iaid;
- outbind[7].buffer_type = MYSQL_TYPE_LONG;
- outbind[7].buffer = reinterpret_cast<char*>(&iaid);
- outbind[7].is_unsigned = MLM_TRUE;
-
- // prefix_len: unsigned tinyint
- uint8_t prefixlen;
- outbind[8].buffer_type = MYSQL_TYPE_TINY;
- outbind[8].buffer = reinterpret_cast<char*>(&prefixlen);
- outbind[8].is_unsigned = MLM_TRUE;
+ // Bind the input parameters to the statement
+ int status = mysql_stmt_bind_param(statements_[GET_LEASE6], inbind);
+ checkError(status, GET_LEASE6, "unable to bind WHERE clause parameter");
- // Bind the parameters to the statement
+ // Bind the output parameters to the statement
status = mysql_stmt_bind_result(statements_[GET_LEASE6], outbind);
checkError(status, GET_LEASE6, "unable to bind SELECT caluse parameters");
@@ -451,49 +600,36 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
checkError(status, GET_LEASE6, "unable to execute");
// Fetch the data.
- Lease6Ptr result(new Lease6());
status = mysql_stmt_fetch(statements_[GET_LEASE6]);
- if (status == 0) {
- // Success - put the data in the lease object
- result->addr_ = addr;
- result->hwaddr_ = vector<uint8_t>(&hwaddr[0], &hwaddr[hwaddr_length]);
- result->duid_.reset(new DUID(clientid, clientid_length));
- convertToLeaseTime(mysql_expire, lease_time,
- result->cltt_, result->valid_lft_);
- result->subnet_id_ = subnet_id;
- result->preferred_lft_ = pref_lifetime;
- switch (lease_type) {
- case Lease6::LEASE_IA_NA:
- result->type_ = Lease6::LEASE_IA_NA;
- break;
- case Lease6::LEASE_IA_TA:
- result->type_ = Lease6::LEASE_IA_TA;
- break;
-
- case Lease6::LEASE_IA_PD:
- result->type_ = Lease6::LEASE_IA_PD;
- break;
-
- default:
- isc_throw(BadValue, "invalid lease type returned for <" <<
- raw_statements_[GET_LEASE6] << ">");
+ Lease6Ptr result;
+ if (status == 0) {
+ try {
+ result = exchange.getLeaseData();
+ } catch (isc::BadValue) {
+ // Free up result set.
+
+ (void) mysql_stmt_free_result(statements_[GET_LEASE6]);
+ // Lease type is returned, to rethrow the exception with a bit
+ // more data.
+ isc_throw(BadValue, "invalid lease type returned for <" <<
+ raw_statements_[GET_LEASE6] << ">");
}
- result->iaid_ = iaid;
- result->prefixlen_ = prefixlen;
// As the address is the primary key in the table, we can't return
- // two rows, so we don't bother checking.
+ // two rows, so we don't bother checking whether multiple rows have
+ // been returned.
} else if (status == 1) {
checkError(status, GET_LEASE6, "unable to fetch results");
} else {
// We are ignoring truncation for now, so the only other result is
- // no data was found. In that case, we returrn a null Lease6 structure.
+ // no data was found. In that case, we return a null Lease6 structure.
// This has already been set, so ther action is a no-op.
}
+ (void) mysql_stmt_free_result(statements_[GET_LEASE6]);
return (result);
}
@@ -522,8 +658,33 @@ MySqlLeaseMgr::deleteLease4(const isc::asiolink::IOAddress& /* addr */) {
}
bool
-MySqlLeaseMgr::deleteLease6(const isc::asiolink::IOAddress& /* addr */) {
- return (false);
+MySqlLeaseMgr::deleteLease6(const isc::asiolink::IOAddress& addr) {
+
+ // Set up the WHERE clause value
+ MYSQL_BIND inbind[1];
+ memset(inbind, 0, sizeof(inbind));
+
+ std::string addr6 = addr.toText();
+ unsigned long addr6_length = addr6.size();
+
+ inbind[0].buffer_type = MYSQL_TYPE_STRING;
+ inbind[0].buffer = const_cast<char*>(addr6.c_str());
+ inbind[0].buffer_length = addr6_length;
+ inbind[0].length = &addr6_length;
+
+ // Bind the input parameters to the statement
+ int status = mysql_stmt_bind_param(statements_[DELETE_LEASE6], inbind);
+ checkError(status, DELETE_LEASE6, "unable to bind WHERE clause parameter");
+
+ // Execute
+ status = mysql_stmt_execute(statements_[DELETE_LEASE6]);
+ checkError(status, DELETE_LEASE6, "unable to execute");
+
+ // See how many rows were affected. Note that the statement may delete
+ // multiple rows.
+ return (mysql_stmt_affected_rows(statements_[DELETE_LEASE6]) > 0);
+
+ return false;
}
std::string
@@ -572,10 +733,12 @@ MySqlLeaseMgr::getVersion() const {
// Get the result
status = mysql_stmt_fetch(statements_[GET_VERSION]);
if (status != 0) {
+ (void) mysql_stmt_free_result(statements_[GET_VERSION]);
isc_throw(DbOperationError, "unable to obtain result set: " <<
mysql_error(mysql_));
}
+ (void) mysql_stmt_free_result(statements_[GET_VERSION]);
return (std::make_pair(major, minor));
}
diff --git a/src/lib/dhcp/mysql_lease_mgr.h b/src/lib/dhcp/mysql_lease_mgr.h
index 1633d62..50ccb72 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)
@@ -97,6 +97,7 @@ public:
/// @return smart pointer to the lease (or NULL if a lease is not found)
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
+
/// @brief Returns existing IPv4 leases for specified hardware address.
///
/// Although in the usual case there will be only one lease, for mobile
@@ -254,11 +255,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 +268,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 +281,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 +289,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,18 +304,19 @@ 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,
+ DELETE_LEASE6, // Delete from lease6 by address
+ GET_LEASE6, // Get lease 6 by address
GET_VERSION, // Obtain version number
INSERT_LEASE6, // Add entry to lease6 table
NUM_STATEMENTS // Number of statements
@@ -360,12 +362,13 @@ private:
/// @param what High-level description of the error
///
/// @exception DbOperationError Error doing a database operation
- inline void checkError(my_bool status, StatementIndex index,
+ inline void checkError(int status, StatementIndex index,
const char* what) const {
if (status != 0) {
isc_throw(DbOperationError, what << " for <" <<
raw_statements_[index] << ">, reason: " <<
- mysql_error(mysql_));
+ mysql_error(mysql_) << " (error code " <<
+ mysql_errno(mysql_) << ")");
}
}
diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am
index 2f7ba45..931940f 100644
--- a/src/lib/dhcp/tests/Makefile.am
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -4,6 +4,9 @@ AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/dhcp/tests\"
AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
+# Temp
+AM_CPPFLAGS += -I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing
+AM_CPPFLAGS += -DUNIV_LINUX
AM_CXXFLAGS = $(B10_CXXFLAGS)
@@ -30,7 +33,9 @@ libdhcp___unittests_SOURCES += duid_unittest.cc
libdhcp___unittests_SOURCES += iface_mgr_unittest.cc
libdhcp___unittests_SOURCES += lease_mgr_factory_unittest.cc
libdhcp___unittests_SOURCES += lease_mgr_unittest.cc
+if HAVE_MYSQL
libdhcp___unittests_SOURCES += mysql_lease_mgr_unittest.cc
+endif
libdhcp___unittests_SOURCES += libdhcp++_unittest.cc
libdhcp___unittests_SOURCES += option4_addrlst_unittest.cc
libdhcp___unittests_SOURCES += option6_addrlst_unittest.cc
@@ -43,6 +48,10 @@ libdhcp___unittests_SOURCES += pkt6_unittest.cc
libdhcp___unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
libdhcp___unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
libdhcp___unittests_CXXFLAGS = $(AM_CXXFLAGS)
+if HAVE_MYSQL
+libdhcp___unittests_CPPFLAGS += $(MYSQL_CPPFLAGS)
+libdhcp___unittests_LDFLAGS += $(MYSQL_LIBS)
+endif
libdhcpsrv_unittests_SOURCES = run_unittests.cc
libdhcpsrv_unittests_SOURCES += addr_utilities_unittest.cc
diff --git a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc
index a4626d8..03e6a29 100644
--- a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc
@@ -77,7 +77,7 @@ public:
/// lmptr_ member variable will close the database.
virtual ~MySqlLeaseMgrTest() {
- //lmptr_->rollback();
+ lmptr_->rollback();
}
LeaseMgrPtr lmptr_; // Pointer to the lease manager
@@ -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);
@@ -151,36 +151,72 @@ TEST_F(MySqlLeaseMgrTest, CheckVersion) {
EXPECT_EQ(1, version.second);
}
+/// @brief Print Elements of Lease6 Structure
+///
+/// @param lease Pointer to lease to print
+/// @param title Title to print before the lease information
+void
+printLease6(const Lease6Ptr& lease, const char* title = NULL) {
+ if (title != NULL) {
+ cout << title << "\n";
+ }
+
+ cout << " Type: ";
+ switch (lease->type_) {
+ case Lease6::LEASE_IA_NA:
+ cout << "IA_NA\n";
+ break;
+ case Lease6::LEASE_IA_TA:
+ cout << "IA_TA\n";
+ break;
+ case Lease6::LEASE_IA_PD:
+ cout << "IA_PD\n";
+ break;
+ default:
+ cout << "unknown (" << static_cast<int>(lease->type_) << ")\n";
+ }
+ cout << " Address: " << lease->addr_.toText() << "\n";
+ cout << " Prefix length: " << static_cast<int>(lease->prefixlen_) << "\n";
+ cout << " IAID: " << lease->iaid_ << "\n";
+ cout << " Pref life: " << lease->preferred_lft_ << "\n";
+ cout << " Valid life: " << lease->valid_lft_ << "\n";
+ cout << " Cltt: " << lease->cltt_ << "\n";
+ cout << " Subnet ID: " << lease->subnet_id_ << "\n";
+}
/// @brief Compare Lease4 Structure
bool
-compareLease6(const Lease6Ptr& l1, const Lease6Ptr& l2) {
+compareLease6(const Lease6Ptr& first, const Lease6Ptr& second) {
return (
- l1->type_ == l2->type_ &&
- l1->addr_ == l2->addr_ &&
- l1->prefixlen_ == l2->prefixlen_ &&
- l1->iaid_ == l2->iaid_ &&
- l1->hwaddr_ == l2->hwaddr_ &&
- *l1->duid_ == *l2->duid_ &&
- l1->preferred_lft_ == l2->preferred_lft_ &&
- l1->valid_lft_ == l2->valid_lft_ &&
- l1->cltt_ == l2->cltt_ &&
- l1->subnet_id_ == l2->subnet_id_
+ first->type_ == second->type_ &&
+ first->addr_ == second->addr_ &&
+ first->prefixlen_ == second->prefixlen_ &&
+ first->iaid_ == second->iaid_ &&
+ first->hwaddr_ == second->hwaddr_ &&
+ *first->duid_ == *second->duid_ &&
+ first->preferred_lft_ == second->preferred_lft_ &&
+ first->valid_lft_ == second->valid_lft_ &&
+ first->cltt_ == second->cltt_ &&
+ first->subnet_id_ == second->subnet_id_
);
}
void
-detailCompareLease6(const Lease6Ptr& l1, const Lease6Ptr& l2) {
- EXPECT_EQ(l1->type_, l2->type_);
- EXPECT_EQ(l1->addr_, l2->addr_);
- EXPECT_EQ(l1->prefixlen_, l2->prefixlen_);
- EXPECT_EQ(l1->iaid_, l2->iaid_);
- EXPECT_TRUE(l1->hwaddr_ == l2->hwaddr_);
- EXPECT_TRUE(*l1->duid_ == *l2->duid_);
- EXPECT_EQ(l1->preferred_lft_, l2->preferred_lft_);
- EXPECT_EQ(l1->valid_lft_, l2->valid_lft_);
- EXPECT_EQ(l1->cltt_, l2->cltt_);
- EXPECT_EQ(l1->subnet_id_, l2->subnet_id_);
+detailCompareLease6(const Lease6Ptr& first, const Lease6Ptr& second) {
+ EXPECT_EQ(first->type_, second->type_);
+
+ // Compare address strings - odd things happen when they are different
+ // as the EXPECT_EQ appears to call the operator uint32_t() function,
+ // which causes an exception to be thrown for IPv6 addresses.
+ EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
+ EXPECT_EQ(first->prefixlen_, second->prefixlen_);
+ EXPECT_EQ(first->iaid_, second->iaid_);
+ EXPECT_TRUE(first->hwaddr_ == second->hwaddr_);
+ EXPECT_TRUE(*first->duid_ == *second->duid_);
+ EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
+ EXPECT_EQ(first->valid_lft_, second->valid_lft_);
+ EXPECT_EQ(first->cltt_, second->cltt_);
+ EXPECT_EQ(first->subnet_id_, second->subnet_id_);
}
/// @brief Initialize Lease
@@ -219,7 +255,7 @@ TEST_F(MySqlLeaseMgrTest, BasicLease6) {
l1->hwaddr_ = std::vector<uint8_t>(6, 0x42); // Six hex 42's
l1->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
l1->preferred_lft_ = 3600; // Preferred lifetime
- l1->valid_lft_ = 3600; // Actual lifetime
+ l1->valid_lft_ = 3677; // Actual lifetime
l1->cltt_ = 123456; // Current time of day
l1->subnet_id_ = 73; // Arbitrary number
@@ -227,45 +263,49 @@ TEST_F(MySqlLeaseMgrTest, BasicLease6) {
Lease6Ptr l2(new Lease6());
initializeUnusedLease6(l2);
- l2->type_ = Lease6::LEASE_IA_TA;
- l2->addr_ = L1_ADDRESS;
- l2->prefixlen_ = 0;
+ l2->type_ = Lease6::LEASE_IA_PD;
+ l2->addr_ = L2_ADDRESS;
+ l2->prefixlen_ = 7;
l2->iaid_ = 89;
l2->hwaddr_ = std::vector<uint8_t>(6, 0xf43); // Six hex 42's
l2->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x3a)));
l2->preferred_lft_ = 1800; // Preferred lifetime
- l2->valid_lft_ = 5400; // Actual lifetime
+ l2->valid_lft_ = 5412; // Actual lifetime
l2->cltt_ = 234567; // Current time of day
l2->subnet_id_ = l1->subnet_id_; // Same as l1
// Sanity check that the leases are different
ASSERT_FALSE(compareLease6(l1, l2));
- // Start the tests. Add the first lease to the database. Then read it
- // back to see whether it is what we think it is.
+ // Start the tests. Add two leases to the database, read them back and
+ // check they are what we think they are.
Lease6Ptr l_returned;
- ASSERT_TRUE(lmptr_->addLease(l1));
+ EXPECT_TRUE(lmptr_->addLease(l1));
+ EXPECT_TRUE(lmptr_->addLease(l2));
+
l_returned = lmptr_->getLease6(L1_ADDRESS);
EXPECT_TRUE(l_returned);
detailCompareLease6(l1, l_returned);
-/*
- // Delete the lease and check that it has been deleted.
- EXPECT_TRUE(lmptr_->deleteLease6(L1_ADDRESS));
- l_returned = lmptr_->getLease6(L1_ADDRESS);
- EXPECT_FALSE(l_returned);
- // Add the address again and check that we can't add it a second time
- ASSERT_TRUE(lmptr_->addLease(l1));
- ASSERT_FALSE(lmptr_->addLease(l1));
+ l_returned = lmptr_->getLease6(L2_ADDRESS);
+ EXPECT_TRUE(l_returned);
+ detailCompareLease6(l2, l_returned);
- // Add the second lease
- ASSERT_TRUE(lmptr_->addLease(l2));
+ // Check that we can't add a second lease with the same address
+ EXPECT_FALSE(lmptr_->addLease(l1));
- // Finally, delete the lease and check we can't delete it again.
+ // Delete a lease, check that it's gone, and that we can't delete it
+ // a second time.
EXPECT_TRUE(lmptr_->deleteLease6(L1_ADDRESS));
+ l_returned = lmptr_->getLease6(L1_ADDRESS);
+ EXPECT_FALSE(l_returned);
EXPECT_FALSE(lmptr_->deleteLease6(L1_ADDRESS));
- */
+
+ // Check that the second address is still there.
+ l_returned = lmptr_->getLease6(L2_ADDRESS);
+ EXPECT_TRUE(l_returned);
+ detailCompareLease6(l2, l_returned);
}
}; // end of anonymous namespace
More information about the bind10-changes
mailing list