Browse Source

[3681] DataSource class added.

 - code refactoring after last commit, clean-up, compilation fixes
 - Makefile updates
 - Added new unit-tests for DataSource (mostly moved from LeaseMgr
   unit-tests)
Tomek Mrugalski 10 years ago
parent
commit
373aa0a40e

+ 2 - 0
src/lib/dhcpsrv/Makefile.am

@@ -92,6 +92,7 @@ libkea_dhcpsrv_la_SOURCES += csv_lease_file6.cc csv_lease_file6.h
 libkea_dhcpsrv_la_SOURCES += d2_client_cfg.cc d2_client_cfg.h
 libkea_dhcpsrv_la_SOURCES += d2_client_cfg.cc d2_client_cfg.h
 libkea_dhcpsrv_la_SOURCES += d2_client_mgr.cc d2_client_mgr.h
 libkea_dhcpsrv_la_SOURCES += d2_client_mgr.cc d2_client_mgr.h
 libkea_dhcpsrv_la_SOURCES += daemon.cc daemon.h
 libkea_dhcpsrv_la_SOURCES += daemon.cc daemon.h
+libkea_dhcpsrv_la_SOURCES += data_source.cc data_source.h
 libkea_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h
 libkea_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h
 libkea_dhcpsrv_la_SOURCES += host.cc host.h
 libkea_dhcpsrv_la_SOURCES += host.cc host.h
 libkea_dhcpsrv_la_SOURCES += host_container.h
 libkea_dhcpsrv_la_SOURCES += host_container.h
@@ -110,6 +111,7 @@ libkea_dhcpsrv_la_SOURCES += memfile_lease_storage.h
 
 
 if HAVE_MYSQL
 if HAVE_MYSQL
 libkea_dhcpsrv_la_SOURCES += mysql_lease_mgr.cc mysql_lease_mgr.h
 libkea_dhcpsrv_la_SOURCES += mysql_lease_mgr.cc mysql_lease_mgr.h
+libkea_dhcpsrv_la_SOURCES += mysql_connection.cc mysql_connection.h
 endif
 endif
 if HAVE_PGSQL
 if HAVE_PGSQL
 libkea_dhcpsrv_la_SOURCES += pgsql_lease_mgr.cc pgsql_lease_mgr.h
 libkea_dhcpsrv_la_SOURCES += pgsql_lease_mgr.cc pgsql_lease_mgr.h

+ 30 - 0
src/lib/dhcpsrv/data_source.cc

@@ -0,0 +1,30 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC 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.
+
+#include <dhcpsrv/data_source.h>
+#include <exceptions/exceptions.h>
+
+namespace isc {
+namespace dhcp {
+
+std::string DataSource::getParameter(const std::string& name) const {
+    ParameterMap::const_iterator param = parameters_.find(name);
+    if (param == parameters_.end()) {
+        isc_throw(BadValue, "Parameter not found");
+    }
+    return (param->second);
+}
+
+};
+};

+ 76 - 0
src/lib/dhcpsrv/data_source.h

@@ -0,0 +1,76 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC 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.
+
+#ifndef DATA_SOURCE_H
+#define DATA_SOURCE_H
+
+#include <boost/noncopyable.hpp>
+#include <exceptions/exceptions.h>
+#include <map>
+#include <string>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Exception thrown if name of database is not specified
+class NoDatabaseName : public Exception {
+public:
+    NoDatabaseName(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Exception thrown on failure to open database
+class DbOpenError : public Exception {
+public:
+    DbOpenError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Exception thrown on failure to execute a database function
+class DbOperationError : public Exception {
+public:
+    DbOperationError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+class DataSource : public boost::noncopyable {
+
+public:
+    /// Database configuration parameter map
+    typedef std::map<std::string, std::string> ParameterMap;
+
+    DataSource(const ParameterMap& parameters)
+        :parameters_(parameters) {
+    }
+
+    /// @brief returns value of the parameter
+    /// @throw BadValue if parameter is not found
+    /// @return parameter
+    std::string getParameter(const std::string& name) const;
+
+protected:
+
+    /// @brief list of parameters passed in dbconfig
+    ///
+    /// That will be mostly used for storing database name, username,
+    /// password and other parameters required for DB access. It is not
+    /// intended to keep any DHCP-related parameters.
+    ParameterMap parameters_;
+
+};
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
+
+#endif // DATA_SOURCE_H

+ 2 - 0
src/lib/dhcpsrv/lease_mgr.cc

@@ -36,6 +36,8 @@ using namespace std;
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
+const time_t LeaseMgr::MAX_DB_TIME = 2147483647;
+
 Lease6Ptr
 Lease6Ptr
 LeaseMgr::getLease6(Lease::Type type, const DUID& duid,
 LeaseMgr::getLease6(Lease::Type type, const DUID& duid,
                     uint32_t iaid, SubnetID subnet_id) const {
                     uint32_t iaid, SubnetID subnet_id) const {

+ 4 - 0
src/lib/dhcpsrv/lease_mgr.h

@@ -112,6 +112,10 @@ public:
 /// of those classes for details.
 /// of those classes for details.
 class LeaseMgr {
 class LeaseMgr {
 public:
 public:
+    /// @brief Defines maximum value for time that can be reliably stored.
+    // If I'm still alive I'll be too old to care. You fix it.
+    static const time_t MAX_DB_TIME;
+
     /// @brief Constructor
     /// @brief Constructor
     ///
     ///
     /// @param parameters A data structure relating keywords and values
     /// @param parameters A data structure relating keywords and values

+ 5 - 5
src/lib/dhcpsrv/lease_mgr_factory.cc

@@ -46,9 +46,9 @@ LeaseMgrFactory::getLeaseMgrPtr() {
     return (leaseMgrPtr);
     return (leaseMgrPtr);
 }
 }
 
 
-LeaseMgr::ParameterMap
+DataSource::ParameterMap
 LeaseMgrFactory::parse(const std::string& dbaccess) {
 LeaseMgrFactory::parse(const std::string& dbaccess) {
-    LeaseMgr::ParameterMap mapped_tokens;
+    DataSource::ParameterMap mapped_tokens;
 
 
     if (!dbaccess.empty()) {
     if (!dbaccess.empty()) {
         vector<string> tokens;
         vector<string> tokens;
@@ -76,11 +76,11 @@ LeaseMgrFactory::parse(const std::string& dbaccess) {
 }
 }
 
 
 std::string
 std::string
-LeaseMgrFactory::redactedAccessString(const LeaseMgr::ParameterMap& parameters) {
+LeaseMgrFactory::redactedAccessString(const DataSource::ParameterMap& parameters) {
     // Reconstruct the access string: start of with an empty string, then
     // Reconstruct the access string: start of with an empty string, then
     // work through all the parameters in the original string and add them.
     // work through all the parameters in the original string and add them.
     std::string access;
     std::string access;
-    for (LeaseMgr::ParameterMap::const_iterator i = parameters.begin();
+    for (DataSource::ParameterMap::const_iterator i = parameters.begin();
          i != parameters.end(); ++i) {
          i != parameters.end(); ++i) {
 
 
         // Separate second and subsequent tokens are preceded by a space.
         // Separate second and subsequent tokens are preceded by a space.
@@ -109,7 +109,7 @@ LeaseMgrFactory::create(const std::string& dbaccess) {
     const std::string type = "type";
     const std::string type = "type";
 
 
     // Parse the access string and create a redacted string for logging.
     // Parse the access string and create a redacted string for logging.
-    LeaseMgr::ParameterMap parameters = parse(dbaccess);
+    DataSource::ParameterMap parameters = parse(dbaccess);
     std::string redacted = redactedAccessString(parameters);
     std::string redacted = redactedAccessString(parameters);
 
 
     // Is "type" present?
     // Is "type" present?

+ 3 - 2
src/lib/dhcpsrv/lease_mgr_factory.h

@@ -16,6 +16,7 @@
 #define LEASE_MGR_FACTORY_H
 #define LEASE_MGR_FACTORY_H
 
 
 #include <dhcpsrv/lease_mgr.h>
 #include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/data_source.h>
 #include <exceptions/exceptions.h>
 #include <exceptions/exceptions.h>
 
 
 #include <string>
 #include <string>
@@ -106,7 +107,7 @@ public:
     /// @param dbaccess Database access string.
     /// @param dbaccess Database access string.
     ///
     ///
     /// @return std::map<std::string, std::string> Map of keyword/value pairs.
     /// @return std::map<std::string, std::string> Map of keyword/value pairs.
-    static LeaseMgr::ParameterMap parse(const std::string& dbaccess);
+    static DataSource::ParameterMap parse(const std::string& dbaccess);
 
 
     /// @brief Redact database access string
     /// @brief Redact database access string
     ///
     ///
@@ -117,7 +118,7 @@ public:
     ///
     ///
     /// @return Redacted database access string.
     /// @return Redacted database access string.
     static std::string redactedAccessString(
     static std::string redactedAccessString(
-            const LeaseMgr::ParameterMap& parameters);
+            const DataSource::ParameterMap& parameters);
 
 
 private:
 private:
     /// @brief Hold pointer to lease manager
     /// @brief Hold pointer to lease manager

+ 5 - 232
src/lib/dhcpsrv/mysql_connection.cc

@@ -33,115 +33,6 @@ using namespace isc;
 using namespace isc::dhcp;
 using namespace isc::dhcp;
 using namespace std;
 using namespace std;
 
 
-
-namespace {
-
-const time_t MySqlConnection::MAX_DB_TIME = 2147483647;
-
-/// @brief MySQL Selection Statements
-///
-/// Each statement is associated with an index, which is used to reference the
-/// associated prepared statement.
-
-struct TaggedStatement {
-    MySqlConnection::StatementIndex index;
-    const char*                   text;
-};
-
-TaggedStatement tagged_statements[] = {
-    {MySqlLeaseMgr::DELETE_LEASE4,
-                    "DELETE FROM lease4 WHERE address = ?"},
-    {MySqlLeaseMgr::DELETE_LEASE6,
-                    "DELETE FROM lease6 WHERE address = ?"},
-    {MySqlLeaseMgr::GET_LEASE4_ADDR,
-                    "SELECT address, hwaddr, client_id, "
-                        "valid_lifetime, expire, subnet_id, "
-                        "fqdn_fwd, fqdn_rev, hostname "
-                            "FROM lease4 "
-                            "WHERE address = ?"},
-    {MySqlLeaseMgr::GET_LEASE4_CLIENTID,
-                    "SELECT address, hwaddr, client_id, "
-                        "valid_lifetime, expire, subnet_id, "
-                        "fqdn_fwd, fqdn_rev, hostname "
-                            "FROM lease4 "
-                            "WHERE client_id = ?"},
-    {MySqlLeaseMgr::GET_LEASE4_CLIENTID_SUBID,
-                    "SELECT address, hwaddr, client_id, "
-                        "valid_lifetime, expire, subnet_id, "
-                        "fqdn_fwd, fqdn_rev, hostname "
-                            "FROM lease4 "
-                            "WHERE client_id = ? AND subnet_id = ?"},
-    {MySqlLeaseMgr::GET_LEASE4_HWADDR,
-                    "SELECT address, hwaddr, client_id, "
-                        "valid_lifetime, expire, subnet_id, "
-                        "fqdn_fwd, fqdn_rev, hostname "
-                            "FROM lease4 "
-                            "WHERE hwaddr = ?"},
-    {MySqlLeaseMgr::GET_LEASE4_HWADDR_SUBID,
-                    "SELECT address, hwaddr, client_id, "
-                        "valid_lifetime, expire, subnet_id, "
-                        "fqdn_fwd, fqdn_rev, hostname "
-                            "FROM lease4 "
-                            "WHERE hwaddr = ? AND subnet_id = ?"},
-    {MySqlLeaseMgr::GET_LEASE6_ADDR,
-                    "SELECT address, duid, valid_lifetime, "
-                        "expire, subnet_id, pref_lifetime, "
-                        "lease_type, iaid, prefix_len, "
-                        "fqdn_fwd, fqdn_rev, hostname, "
-                        "hwaddr, hwtype, hwaddr_source "
-                            "FROM lease6 "
-                            "WHERE address = ? AND lease_type = ?"},
-    {MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
-                    "SELECT address, duid, valid_lifetime, "
-                        "expire, subnet_id, pref_lifetime, "
-                        "lease_type, iaid, prefix_len, "
-                        "fqdn_fwd, fqdn_rev, hostname, "
-                        "hwaddr, hwtype, hwaddr_source "
-                            "FROM lease6 "
-                            "WHERE duid = ? AND iaid = ? AND lease_type = ?"},
-    {MySqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID,
-                    "SELECT address, duid, valid_lifetime, "
-                        "expire, subnet_id, pref_lifetime, "
-                        "lease_type, iaid, prefix_len, "
-                        "fqdn_fwd, fqdn_rev, hostname, "
-                        "hwaddr, hwtype, hwaddr_source "
-                            "FROM lease6 "
-                            "WHERE duid = ? AND iaid = ? AND subnet_id = ? "
-                            "AND lease_type = ?"},
-    {MySqlLeaseMgr::GET_VERSION,
-                    "SELECT version, minor FROM schema_version"},
-    {MySqlLeaseMgr::INSERT_LEASE4,
-                    "INSERT INTO lease4(address, hwaddr, client_id, "
-                        "valid_lifetime, expire, subnet_id, "
-                        "fqdn_fwd, fqdn_rev, hostname) "
-                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"},
-    {MySqlLeaseMgr::INSERT_LEASE6,
-                    "INSERT INTO lease6(address, duid, valid_lifetime, "
-                        "expire, subnet_id, pref_lifetime, "
-                        "lease_type, iaid, prefix_len, "
-                        "fqdn_fwd, fqdn_rev, hostname, "
-                        "hwaddr, hwtype, hwaddr_source) "
-                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"},
-    {MySqlLeaseMgr::UPDATE_LEASE4,
-                    "UPDATE lease4 SET address = ?, hwaddr = ?, "
-                        "client_id = ?, valid_lifetime = ?, expire = ?, "
-                        "subnet_id = ?, fqdn_fwd = ?, fqdn_rev = ?, "
-                        "hostname = ? "
-                            "WHERE address = ?"},
-    {MySqlLeaseMgr::UPDATE_LEASE6,
-                    "UPDATE lease6 SET address = ?, duid = ?, "
-                        "valid_lifetime = ?, expire = ?, subnet_id = ?, "
-                        "pref_lifetime = ?, lease_type = ?, iaid = ?, "
-                        "prefix_len = ?, fqdn_fwd = ?, fqdn_rev = ?, "
-                        "hostname = ?, hwaddr = ?, hwtype = ?, hwaddr_source = ? "
-                            "WHERE address = ?"},
-    // End of list sentinel
-    {MySqlLeaseMgr::NUM_STATEMENTS, NULL}
-};
-
-
-};  // Anonymous namespace
-
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
@@ -155,39 +46,12 @@ namespace dhcp {
 /// be set greater than or equal to the length of the field plus 1: this allows
 /// be set greater than or equal to the length of the field plus 1: this allows
 /// for the insertion of a trailing null whatever data is returned.
 /// for the insertion of a trailing null whatever data is returned.
 
 
-/// @brief Maximum size of an IPv6 address represented as a text string.
-///
-/// This is 32 hexadecimal characters written in 8 groups of four, plus seven
-/// colon separators.
-const size_t ADDRESS6_TEXT_MAX_LEN = 39;
-
-/// @brief MySQL True/False constants
-///
-/// Declare typed values so as to avoid problems of data conversion.  These
-/// are local to the file but are given the prefix MLM (MySql Lease Manager) to
-/// avoid any likely conflicts with variables in header files named TRUE or
-/// FALSE.
-
 const my_bool MLM_FALSE = 0;                ///< False value
 const my_bool MLM_FALSE = 0;                ///< False value
 const my_bool MLM_TRUE = 1;                 ///< True value
 const my_bool MLM_TRUE = 1;                 ///< True value
 
 
-/// @brief Maximum length of the hostname stored in DNS.
-///
-/// This length is restricted by the length of the domain-name carried
-/// in the Client FQDN %Option (see RFC4702 and RFC4704).
-const size_t HOSTNAME_MAX_LEN = 255;
-
 ///@}
 ///@}
 
 
 
 
-std::string MySqlConnection::getParameter(const std::string& name) const {
-    ParameterMap::const_iterator param = parameters_.find(name);
-    if (param == parameters_.end()) {
-        isc_throw(BadValue, "Parameter not found");
-    }
-    return (param->second);
-}
-
 // Open the database using the parameters passed to the constructor.
 // Open the database using the parameters passed to the constructor.
 
 
 void
 void
@@ -280,7 +144,7 @@ MySqlConnection::openDatabase() {
 // class destructor explicitly destroys them.
 // class destructor explicitly destroys them.
 
 
 void
 void
-MySqlConnection::prepareStatement(StatementIndex index, const char* text) {
+MySqlConnection::prepareStatement(uint32_t index, const char* text) {
     // Validate that there is space for the statement in the statements array
     // Validate that there is space for the statement in the statements array
     // and that nothing has been placed there before.
     // and that nothing has been placed there before.
     if ((index >= this->statements_.size()) || (this->statements_[index] != NULL)) {
     if ((index >= this->statements_.size()) || (this->statements_[index] != NULL)) {
@@ -304,16 +168,15 @@ MySqlConnection::prepareStatement(StatementIndex index, const char* text) {
     }
     }
 }
 }
 
 
-
 void
 void
-MySqlConnection::prepareStatements() {
+MySqlConnection::prepareStatements(const TaggedStatement tagged_statements[],
+                                   size_t num_statements) {
     // Allocate space for all statements
     // Allocate space for all statements
     statements_.clear();
     statements_.clear();
-    statements_.resize(NUM_STATEMENTS, NULL);
+    statements_.resize(num_statements, NULL);
 
 
     text_statements_.clear();
     text_statements_.clear();
-    text_statements_.resize(NUM_STATEMENTS, std::string(""));
-
+    text_statements_.resize(num_statements, std::string(""));
 
 
     // Created the MySQL prepared statements for each DML statement.
     // Created the MySQL prepared statements for each DML statement.
     for (int i = 0; tagged_statements[i].text != NULL; ++i) {
     for (int i = 0; tagged_statements[i].text != NULL; ++i) {
@@ -322,95 +185,5 @@ MySqlConnection::prepareStatements() {
     }
     }
 }
 }
 
 
-
-
-// Miscellaneous database methods.
-
-std::string
-MySqlConnection::getName() const {
-    std::string name = "";
-    try {
-        name = getParameter("name");
-    } catch (...) {
-        // Return an empty name
-    }
-    return (name);
-}
-
-
-std::string
-MySqlConnection::getDescription() const {
-    return (std::string("MySQL Database"));
-}
-
-
-std::pair<uint32_t, uint32_t>
-MySqlConnection::getVersion() const {
-    const StatementIndex stindex = GET_VERSION;
-
-    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
-              DHCPSRV_MYSQL_GET_VERSION);
-
-    uint32_t    major;      // Major version number
-    uint32_t    minor;      // Minor version number
-
-    // Execute the prepared statement
-    int status = mysql_stmt_execute(statements_[stindex]);
-    if (status != 0) {
-        isc_throw(DbOperationError, "unable to execute <"
-                  << text_statements_[stindex] << "> - reason: " <<
-                  mysql_error(mysql_));
-    }
-
-    // Bind the output of the statement to the appropriate variables.
-    MYSQL_BIND bind[2];
-    memset(bind, 0, sizeof(bind));
-
-    bind[0].buffer_type = MYSQL_TYPE_LONG;
-    bind[0].is_unsigned = 1;
-    bind[0].buffer = &major;
-    bind[0].buffer_length = sizeof(major);
-
-    bind[1].buffer_type = MYSQL_TYPE_LONG;
-    bind[1].is_unsigned = 1;
-    bind[1].buffer = &minor;
-    bind[1].buffer_length = sizeof(minor);
-
-    status = mysql_stmt_bind_result(statements_[stindex], bind);
-    if (status != 0) {
-        isc_throw(DbOperationError, "unable to bind result set: " <<
-                  mysql_error(mysql_));
-    }
-
-    // Fetch the data and set up the "release" object to release associated
-    // resources when this method exits then retrieve the data.
-    MySqlFreeResult fetch_release(statements_[stindex]);
-    status = mysql_stmt_fetch(statements_[stindex]);
-    if (status != 0) {
-        isc_throw(DbOperationError, "unable to obtain result set: " <<
-                  mysql_error(mysql_));
-    }
-
-    return (std::make_pair(major, minor));
-}
-
-
-void
-MySqlConnection::commit() {
-    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_COMMIT);
-    if (mysql_commit(mysql_) != 0) {
-        isc_throw(DbOperationError, "commit failed: " << mysql_error(mysql_));
-    }
-}
-
-
-void
-MySqlConnection::rollback() {
-    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_ROLLBACK);
-    if (mysql_rollback(mysql_) != 0) {
-        isc_throw(DbOperationError, "rollback failed: " << mysql_error(mysql_));
-    }
-}
-
 } // namespace isc::dhcp
 } // namespace isc::dhcp
 } // namespace isc
 } // namespace isc

+ 28 - 123
src/lib/dhcpsrv/mysql_connection.h

@@ -17,9 +17,8 @@
 
 
 #include <dhcp/hwaddr.h>
 #include <dhcp/hwaddr.h>
 #include <dhcpsrv/lease_mgr.h>
 #include <dhcpsrv/lease_mgr.h>
-
+#include <dhcpsrv/data_source.h>
 #include <boost/scoped_ptr.hpp>
 #include <boost/scoped_ptr.hpp>
-#include <boost/utility.hpp>
 #include <mysql/mysql.h>		// TODO poprawić przed oddaniem
 #include <mysql/mysql.h>		// TODO poprawić przed oddaniem
 
 
 #include <time.h>
 #include <time.h>
@@ -27,26 +26,14 @@
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
-/// @brief Exception thrown if name of database is not specified
-class NoDatabaseName : public Exception {
-public:
-    NoDatabaseName(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @brief Exception thrown on failure to open database
-class DbOpenError : public Exception {
-public:
-    DbOpenError(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @brief Exception thrown on failure to execute a database function
-class DbOperationError : public Exception {
-public:
-    DbOperationError(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
+/// @brief MySQL True/False constants
+///
+/// Declare typed values so as to avoid problems of data conversion.  These
+/// are local to the file but are given the prefix MLM (MySql Lease Manager) to
+/// avoid any likely conflicts with variables in header files named TRUE or
+/// FALSE.
+extern const my_bool MLM_FALSE;
+extern const my_bool MLM_TRUE;
 
 
 /// @brief Fetch and Release MySQL Results
 /// @brief Fetch and Release MySQL Results
 ///
 ///
@@ -89,6 +76,16 @@ private:
     MYSQL_STMT*     statement_;     ///< Statement for which results are freed
     MYSQL_STMT*     statement_;     ///< Statement for which results are freed
 };
 };
 
 
+/// @brief MySQL Selection Statements
+///
+/// Each statement is associated with an index, which is used to reference the
+/// associated prepared statement.
+
+struct TaggedStatement {
+    uint32_t index;
+    const char* text;
+};
+
 /// @brief MySQL Handle Holder
 /// @brief MySQL Handle Holder
 ///
 ///
 /// Small RAII object for safer initialization, will close the database
 /// Small RAII object for safer initialization, will close the database
@@ -139,100 +136,15 @@ private:
 
 
 // Define the current database schema values
 // Define the current database schema values
 
 
-const uint32_t CURRENT_VERSION_VERSION = 3;		// version 3: adding host managment features
-const uint32_t CURRENT_VERSION_MINOR = 0;
-
-
-
-class MySqlConnection {
+class MySqlConnection : public DataSource {
 public:
 public:
 
 
-    /// @brief Defines maximum value for time that can be reliably stored.
-    // If I'm still alive I'll be too old to care. You fix it.
-    static const time_t MAX_DB_TIME;
-
-    /// Database configuration parameter map
-    typedef std::map<std::string, std::string> ParameterMap;
-
-	MySqlConnection(const ParameterMap& parameters)
-    	: parameters_(parameters)
-    {}
-
-	virtual ~MySqlConnection()
-	{}
-
-    /// @brief Statement Tags
-    ///
-    /// The contents of the enum are indexes into the list of SQL statements
-    enum StatementIndex {
-        DELETE_LEASE4,              // Delete from lease4 by address
-        DELETE_LEASE6,              // Delete from lease6 by address
-        GET_LEASE4_ADDR,            // Get lease4 by address
-        GET_LEASE4_CLIENTID,        // Get lease4 by client ID
-        GET_LEASE4_CLIENTID_SUBID,  // Get lease4 by client ID & subnet ID
-        GET_LEASE4_HWADDR,          // Get lease4 by HW address
-        GET_LEASE4_HWADDR_SUBID,    // Get lease4 by HW address & subnet ID
-        GET_LEASE6_ADDR,            // Get lease6 by address
-        GET_LEASE6_DUID_IAID,       // Get lease6 by DUID and IAID
-        GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID
-        GET_VERSION,                // Obtain version number
-        INSERT_LEASE4,              // Add entry to lease4 table
-        INSERT_LEASE6,              // Add entry to lease6 table
-        UPDATE_LEASE4,              // Update a Lease4 entry
-        UPDATE_LEASE6,              // Update a Lease6 entry
-        NUM_STATEMENTS              // Number of statements
-    };
-
-    /// @brief returns value of the parameter
-    virtual std::string getParameter(const std::string& name) const;
-
-    /// @brief Return backend type
-    ///
-    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
-    ///
-    /// @return Type of the backend.
-    virtual std::string getType() const {
-        return (std::string("mysql"));
+    MySqlConnection(const ParameterMap& parameters)
+        : DataSource(parameters) {
     }
     }
 
 
-    /// @brief Returns backend name.
-    ///
-    /// Each backend have specific name, e.g. "mysql" or "sqlite".
-    ///
-    /// @return Name of the backend.
-    virtual std::string getName() const;
-
-    /// @brief Returns description of the backend.
-    ///
-    /// This description may be multiline text that describes the backend.
-    ///
-    /// @return Description of the backend.
-    virtual std::string getDescription() const;
-
-    /// @brief Returns backend version.
-    ///
-    /// @return Version number as a pair of unsigned integers.  "first" is the
-    ///         major version number, "second" the minor number.
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    virtual std::pair<uint32_t, uint32_t> getVersion() const;
-
-    /// @brief Commit Transactions
-    ///
-    /// Commits all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
-    ///
-    /// @throw DbOperationError Iif the commit failed.
-    virtual void commit();
-
-    /// @brief Rollback Transactions
-    ///
-    /// Rolls back all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
-    ///
-    /// @throw DbOperationError If the rollback failed.
-    virtual void rollback();
+    virtual ~MySqlConnection() {
+    }
 
 
     /// @brief Prepare Single Statement
     /// @brief Prepare Single Statement
     ///
     ///
@@ -247,7 +159,7 @@ public:
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
     /// @throw isc::InvalidParameter 'index' is not valid for the vector.
     /// @throw isc::InvalidParameter 'index' is not valid for the vector.
-    void prepareStatement(StatementIndex index, const char* text);
+    void prepareStatement(uint32_t index, const char* text);
 
 
     /// @brief Prepare statements
     /// @brief Prepare statements
     ///
     ///
@@ -258,7 +170,8 @@ public:
     ///        failed.
     ///        failed.
     /// @throw isc::InvalidParameter 'index' is not valid for the vector.  This
     /// @throw isc::InvalidParameter 'index' is not valid for the vector.  This
     ///        represents an internal error within the code.
     ///        represents an internal error within the code.
-    void prepareStatements();
+    void prepareStatements(const TaggedStatement tagged_statements[],
+                           size_t num_statements);
 
 
     /// @brief Open Database
     /// @brief Open Database
     ///
     ///
@@ -272,15 +185,7 @@ public:
     std::vector<MYSQL_STMT*> statements_;       ///< Prepared statements
     std::vector<MYSQL_STMT*> statements_;       ///< Prepared statements
     std::vector<std::string> text_statements_;  ///< Raw text of statements
     std::vector<std::string> text_statements_;  ///< Raw text of statements
 
 
-
-private:
-    /// @brief list of parameters passed in dbconfig
-    ///
-    /// That will be mostly used for storing database name, username,
-    /// password and other parameters required for DB access. It is not
-    /// intended to keep any DHCP-related parameters.
-    ParameterMap parameters_;
-
+protected:
 
 
     MySqlHolder mysql_;
     MySqlHolder mysql_;
 
 

+ 192 - 1
src/lib/dhcpsrv/mysql_lease_mgr.cc

@@ -76,6 +76,111 @@ using namespace std;
 /// - If there is output, copy the data from the bound variables to the output
 /// - If there is output, copy the data from the bound variables to the output
 ///   lease object.
 ///   lease object.
 
 
+namespace {
+/// @brief Maximum length of the hostname stored in DNS.
+///
+/// This length is restricted by the length of the domain-name carried
+/// in the Client FQDN %Option (see RFC4702 and RFC4704).
+const size_t HOSTNAME_MAX_LEN = 255;
+
+/// @brief Maximum size of an IPv6 address represented as a text string.
+///
+/// This is 32 hexadecimal characters written in 8 groups of four, plus seven
+/// colon separators.
+const size_t ADDRESS6_TEXT_MAX_LEN = 39;
+
+TaggedStatement tagged_statements[] = {
+    {MySqlLeaseMgr::DELETE_LEASE4,
+                    "DELETE FROM lease4 WHERE address = ?"},
+    {MySqlLeaseMgr::DELETE_LEASE6,
+                    "DELETE FROM lease6 WHERE address = ?"},
+    {MySqlLeaseMgr::GET_LEASE4_ADDR,
+                    "SELECT address, hwaddr, client_id, "
+                        "valid_lifetime, expire, subnet_id, "
+                        "fqdn_fwd, fqdn_rev, hostname "
+                            "FROM lease4 "
+                            "WHERE address = ?"},
+    {MySqlLeaseMgr::GET_LEASE4_CLIENTID,
+                    "SELECT address, hwaddr, client_id, "
+                        "valid_lifetime, expire, subnet_id, "
+                        "fqdn_fwd, fqdn_rev, hostname "
+                            "FROM lease4 "
+                            "WHERE client_id = ?"},
+    {MySqlLeaseMgr::GET_LEASE4_CLIENTID_SUBID,
+                    "SELECT address, hwaddr, client_id, "
+                        "valid_lifetime, expire, subnet_id, "
+                        "fqdn_fwd, fqdn_rev, hostname "
+                            "FROM lease4 "
+                            "WHERE client_id = ? AND subnet_id = ?"},
+    {MySqlLeaseMgr::GET_LEASE4_HWADDR,
+                    "SELECT address, hwaddr, client_id, "
+                        "valid_lifetime, expire, subnet_id, "
+                        "fqdn_fwd, fqdn_rev, hostname "
+                            "FROM lease4 "
+                            "WHERE hwaddr = ?"},
+    {MySqlLeaseMgr::GET_LEASE4_HWADDR_SUBID,
+                    "SELECT address, hwaddr, client_id, "
+                        "valid_lifetime, expire, subnet_id, "
+                        "fqdn_fwd, fqdn_rev, hostname "
+                            "FROM lease4 "
+                            "WHERE hwaddr = ? AND subnet_id = ?"},
+    {MySqlLeaseMgr::GET_LEASE6_ADDR,
+                    "SELECT address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len, "
+                        "fqdn_fwd, fqdn_rev, hostname, "
+                        "hwaddr, hwtype, hwaddr_source "
+                            "FROM lease6 "
+                            "WHERE address = ? AND lease_type = ?"},
+    {MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
+                    "SELECT address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len, "
+                        "fqdn_fwd, fqdn_rev, hostname, "
+                        "hwaddr, hwtype, hwaddr_source "
+                            "FROM lease6 "
+                            "WHERE duid = ? AND iaid = ? AND lease_type = ?"},
+    {MySqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID,
+                    "SELECT address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len, "
+                        "fqdn_fwd, fqdn_rev, hostname, "
+                        "hwaddr, hwtype, hwaddr_source "
+                            "FROM lease6 "
+                            "WHERE duid = ? AND iaid = ? AND subnet_id = ? "
+                            "AND lease_type = ?"},
+    {MySqlLeaseMgr::GET_VERSION,
+                    "SELECT version, minor FROM schema_version"},
+    {MySqlLeaseMgr::INSERT_LEASE4,
+                    "INSERT INTO lease4(address, hwaddr, client_id, "
+                        "valid_lifetime, expire, subnet_id, "
+                        "fqdn_fwd, fqdn_rev, hostname) "
+                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"},
+    {MySqlLeaseMgr::INSERT_LEASE6,
+                    "INSERT INTO lease6(address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len, "
+                        "fqdn_fwd, fqdn_rev, hostname, "
+                        "hwaddr, hwtype, hwaddr_source) "
+                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"},
+    {MySqlLeaseMgr::UPDATE_LEASE4,
+                    "UPDATE lease4 SET address = ?, hwaddr = ?, "
+                        "client_id = ?, valid_lifetime = ?, expire = ?, "
+                        "subnet_id = ?, fqdn_fwd = ?, fqdn_rev = ?, "
+                        "hostname = ? "
+                            "WHERE address = ?"},
+    {MySqlLeaseMgr::UPDATE_LEASE6,
+                    "UPDATE lease6 SET address = ?, duid = ?, "
+                        "valid_lifetime = ?, expire = ?, subnet_id = ?, "
+                        "pref_lifetime = ?, lease_type = ?, iaid = ?, "
+                        "prefix_len = ?, fqdn_fwd = ?, fqdn_rev = ?, "
+                        "hostname = ?, hwaddr = ?, hwtype = ?, hwaddr_source = ? "
+                            "WHERE address = ?"},
+    // End of list sentinel
+    {MySqlLeaseMgr::NUM_STATEMENTS, NULL}
+};
+
+};
 
 
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
@@ -1062,7 +1167,7 @@ MySqlLeaseMgr::MySqlLeaseMgr(const MySqlConnection::ParameterMap& parameters)
     }
     }
 
 
     // Prepare all statements likely to be used.
     // Prepare all statements likely to be used.
-    prepareStatements();
+    prepareStatements(tagged_statements, MySqlLeaseMgr::NUM_STATEMENTS);
 
 
     // Create the exchange objects for use in exchanging data between the
     // Create the exchange objects for use in exchanging data between the
     // program and the database.
     // program and the database.
@@ -1759,7 +1864,93 @@ MySqlLeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
     }
     }
 }
 }
 
 
+// Miscellaneous database methods.
+
+std::string
+MySqlLeaseMgr::getName() const {
+    std::string name = "";
+    try {
+        name = getParameter("name");
+    } catch (...) {
+        // Return an empty name
+    }
+    return (name);
+}
+
+
+std::string
+MySqlLeaseMgr::getDescription() const {
+    return (std::string("MySQL Database"));
+}
+
+
+std::pair<uint32_t, uint32_t>
+MySqlLeaseMgr::getVersion() const {
+    const StatementIndex stindex = GET_VERSION;
+
+    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
+              DHCPSRV_MYSQL_GET_VERSION);
+
+    uint32_t    major;      // Major version number
+    uint32_t    minor;      // Minor version number
+
+    // Execute the prepared statement
+    int status = mysql_stmt_execute(statements_[stindex]);
+    if (status != 0) {
+        isc_throw(DbOperationError, "unable to execute <"
+                  << text_statements_[stindex] << "> - reason: " <<
+                  mysql_error(mysql_));
+    }
 
 
+    // Bind the output of the statement to the appropriate variables.
+    MYSQL_BIND bind[2];
+    memset(bind, 0, sizeof(bind));
+
+    bind[0].buffer_type = MYSQL_TYPE_LONG;
+    bind[0].is_unsigned = 1;
+    bind[0].buffer = &major;
+    bind[0].buffer_length = sizeof(major);
+
+    bind[1].buffer_type = MYSQL_TYPE_LONG;
+    bind[1].is_unsigned = 1;
+    bind[1].buffer = &minor;
+    bind[1].buffer_length = sizeof(minor);
+
+    status = mysql_stmt_bind_result(statements_[stindex], bind);
+    if (status != 0) {
+        isc_throw(DbOperationError, "unable to bind result set: " <<
+                  mysql_error(mysql_));
+    }
+
+    // Fetch the data and set up the "release" object to release associated
+    // resources when this method exits then retrieve the data.
+    MySqlFreeResult fetch_release(statements_[stindex]);
+    status = mysql_stmt_fetch(statements_[stindex]);
+    if (status != 0) {
+        isc_throw(DbOperationError, "unable to obtain result set: " <<
+                  mysql_error(mysql_));
+    }
+
+    return (std::make_pair(major, minor));
+}
+
+
+void
+MySqlLeaseMgr::commit() {
+    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_COMMIT);
+    if (mysql_commit(mysql_) != 0) {
+        isc_throw(DbOperationError, "commit failed: " << mysql_error(mysql_));
+    }
+}
+
+
+void
+MySqlLeaseMgr::rollback() {
+    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_ROLLBACK);
+    if (mysql_rollback(mysql_) != 0) {
+        isc_throw(DbOperationError, "rollback failed: " << mysql_error(mysql_));
+    }
+}
 
 
 }; // end of isc::dhcp namespace
 }; // end of isc::dhcp namespace
 }; // end of isc namespace
 }; // end of isc namespace

+ 70 - 50
src/lib/dhcpsrv/mysql_lease_mgr.h

@@ -28,57 +28,9 @@
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
-/// @brief MySQL Handle Holder
-///
-/// Small RAII object for safer initialization, will close the database
-/// connection upon destruction.  This means that if an exception is thrown
-/// during database initialization, resources allocated to the database are
-/// guaranteed to be freed.
-///
-/// It makes no sense to copy an object of this class.  After the copy, both
-/// objects would contain pointers to the same MySql context object.  The
-/// destruction of one would invalidate the context in the remaining object.
-/// For this reason, the class is declared noncopyable.
-class MySqlHolder : public boost::noncopyable {
-public:
-
-    /// @brief Constructor
-    ///
-    /// Initialize MySql and store the associated context object.
-    ///
-    /// @throw DbOpenError Unable to initialize MySql handle.
-    MySqlHolder() : mysql_(mysql_init(NULL)) {
-        if (mysql_ == NULL) {
-            isc_throw(DbOpenError, "unable to initialize MySQL");
-        }
-    }
-
-    /// @brief Destructor
-    ///
-    /// Frees up resources allocated by the initialization of MySql.
-    ~MySqlHolder() {
-        if (mysql_ != NULL) {
-            mysql_close(mysql_);
-        }
-        // The library itself shouldn't be needed anymore
-        mysql_library_end();
-    }
-
-    /// @brief Conversion Operator
-    ///
-    /// Allows the MySqlHolder object to be passed as the context argument to
-    /// mysql_xxx functions.
-    operator MYSQL*() const {
-        return (mysql_);
-    }
-
-private:
-    MYSQL* mysql_;      ///< Initialization context
-};
-
 // Define the current database schema values
 // Define the current database schema values
 
 
-const uint32_t CURRENT_VERSION_VERSION = 2;
+const uint32_t CURRENT_VERSION_VERSION = 3;
 const uint32_t CURRENT_VERSION_MINOR = 0;
 const uint32_t CURRENT_VERSION_MINOR = 0;
 
 
 
 
@@ -356,6 +308,54 @@ public:
     ///        failed.
     ///        failed.
     virtual bool deleteLease(const isc::asiolink::IOAddress& addr);
     virtual bool deleteLease(const isc::asiolink::IOAddress& addr);
 
 
+    /// @brief Return backend type
+    ///
+    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
+    ///
+    /// @return Type of the backend.
+    virtual std::string getType() const {
+        return (std::string("mysql"));
+    }
+
+    /// @brief Returns backend name.
+    ///
+    /// Each backend have specific name, e.g. "mysql" or "sqlite".
+    ///
+    /// @return Name of the backend.
+    virtual std::string getName() const;
+
+    /// @brief Returns description of the backend.
+    ///
+    /// This description may be multiline text that describes the backend.
+    ///
+    /// @return Description of the backend.
+    virtual std::string getDescription() const;
+
+    /// @brief Returns backend version.
+    ///
+    /// @return Version number as a pair of unsigned integers.  "first" is the
+    ///         major version number, "second" the minor number.
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    virtual std::pair<uint32_t, uint32_t> getVersion() const;
+
+    /// @brief Commit Transactions
+    ///
+    /// Commits all pending database operations.  On databases that don't
+    /// support transactions, this is a no-op.
+    ///
+    /// @throw DbOperationError Iif the commit failed.
+    virtual void commit();
+
+    /// @brief Rollback Transactions
+    ///
+    /// Rolls back all pending database operations.  On databases that don't
+    /// support transactions, this is a no-op.
+    ///
+    /// @throw DbOperationError If the rollback failed.
+    virtual void rollback();
+
     ///@{
     ///@{
     /// 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 Lease object, and the times stored in the
     /// intervals stored in the Lease object, and the times stored in the
@@ -409,7 +409,27 @@ public:
                                  uint32_t valid_lifetime, time_t& cltt);
                                  uint32_t valid_lifetime, time_t& cltt);
     ///@}
     ///@}
 
 
-
+    /// @brief Statement Tags
+    ///
+    /// The contents of the enum are indexes into the list of SQL statements
+    enum StatementIndex {
+        DELETE_LEASE4,              // Delete from lease4 by address
+        DELETE_LEASE6,              // Delete from lease6 by address
+        GET_LEASE4_ADDR,            // Get lease4 by address
+        GET_LEASE4_CLIENTID,        // Get lease4 by client ID
+        GET_LEASE4_CLIENTID_SUBID,  // Get lease4 by client ID & subnet ID
+        GET_LEASE4_HWADDR,          // Get lease4 by HW address
+        GET_LEASE4_HWADDR_SUBID,    // Get lease4 by HW address & subnet ID
+        GET_LEASE6_ADDR,            // Get lease6 by address
+        GET_LEASE6_DUID_IAID,       // Get lease6 by DUID and IAID
+        GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID
+        GET_VERSION,                // Obtain version number
+        INSERT_LEASE4,              // Add entry to lease4 table
+        INSERT_LEASE6,              // Add entry to lease6 table
+        UPDATE_LEASE4,              // Update a Lease4 entry
+        UPDATE_LEASE6,              // Update a Lease6 entry
+        NUM_STATEMENTS              // Number of statements
+    };
 
 
 private:
 private:
 
 

+ 2 - 2
src/lib/dhcpsrv/pgsql_lease_mgr.cc

@@ -942,8 +942,8 @@ private:
     //@}
     //@}
 };
 };
 
 
-PgSqlLeaseMgr::PgSqlLeaseMgr(const LeaseMgr::ParameterMap& parameters)
-    : LeaseMgr(parameters), exchange4_(new PgSqlLease4Exchange()),
+PgSqlLeaseMgr::PgSqlLeaseMgr(const DataSource::ParameterMap& parameters)
+    : LeaseMgr(), DataSource(parameters), exchange4_(new PgSqlLease4Exchange()),
     exchange6_(new PgSqlLease6Exchange()), conn_(NULL) {
     exchange6_(new PgSqlLease6Exchange()), conn_(NULL) {
     openDatabase();
     openDatabase();
     prepareStatements();
     prepareStatements();

+ 3 - 3
src/lib/dhcpsrv/pgsql_lease_mgr.h

@@ -17,7 +17,7 @@
 
 
 #include <dhcp/hwaddr.h>
 #include <dhcp/hwaddr.h>
 #include <dhcpsrv/lease_mgr.h>
 #include <dhcpsrv/lease_mgr.h>
-
+#include <dhcpsrv/data_source.h>
 #include <boost/scoped_ptr.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <boost/utility.hpp>
 #include <boost/utility.hpp>
 #include <libpq-fe.h>
 #include <libpq-fe.h>
@@ -121,7 +121,7 @@ const uint32_t PG_CURRENT_MINOR = 0;
 /// This class provides the \ref isc::dhcp::LeaseMgr interface to the PostgreSQL
 /// This class provides the \ref isc::dhcp::LeaseMgr interface to the PostgreSQL
 /// database.  Use of this backend presupposes that a PostgreSQL database is
 /// database.  Use of this backend presupposes that a PostgreSQL database is
 /// available and that the Kea schema has been created within it.
 /// available and that the Kea schema has been created within it.
-class PgSqlLeaseMgr : public LeaseMgr {
+class PgSqlLeaseMgr : public LeaseMgr, DataSource {
 public:
 public:
 
 
     /// @brief Constructor
     /// @brief Constructor
@@ -146,7 +146,7 @@ public:
     /// @throw isc::dhcp::DbOpenError Error opening the database
     /// @throw isc::dhcp::DbOpenError Error opening the database
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     /// @throw isc::dhcp::DbOperationError An operation on the open database has
     ///        failed.
     ///        failed.
-    PgSqlLeaseMgr(const ParameterMap& parameters);
+    PgSqlLeaseMgr(const DataSource::ParameterMap& parameters);
 
 
     /// @brief Destructor (closes database)
     /// @brief Destructor (closes database)
     virtual ~PgSqlLeaseMgr();
     virtual ~PgSqlLeaseMgr();

+ 1 - 0
src/lib/dhcpsrv/tests/Makefile.am

@@ -73,6 +73,7 @@ libdhcpsrv_unittests_SOURCES += csv_lease_file6_unittest.cc
 libdhcpsrv_unittests_SOURCES += d2_client_unittest.cc
 libdhcpsrv_unittests_SOURCES += d2_client_unittest.cc
 libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc
 libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc
 libdhcpsrv_unittests_SOURCES += daemon_unittest.cc
 libdhcpsrv_unittests_SOURCES += daemon_unittest.cc
+libdhcpsrv_unittests_SOURCES += data_source_unittest.cc
 libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc
 libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc
 libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc
 libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc
 libdhcpsrv_unittests_SOURCES += host_unittest.cc
 libdhcpsrv_unittests_SOURCES += host_unittest.cc

+ 1 - 1
src/lib/dhcpsrv/tests/dbaccess_parser_unittest.cc

@@ -161,7 +161,7 @@ public:
 
 
         // Check that the keywords and keyword values are the same: loop
         // Check that the keywords and keyword values are the same: loop
         // through the keywords in the database access string.
         // through the keywords in the database access string.
-        for (LeaseMgr::ParameterMap::const_iterator actual = parameters.begin();
+        for (DataSource::ParameterMap::const_iterator actual = parameters.begin();
              actual != parameters.end(); ++actual) {
              actual != parameters.end(); ++actual) {
 
 
             // Does the keyword exist in the set of expected keywords?
             // Does the keyword exist in the set of expected keywords?

+ 1 - 0
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc

@@ -15,6 +15,7 @@
 #include <config.h>
 #include <config.h>
 #include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
 #include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
 #include <dhcpsrv/tests/test_utils.h>
 #include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/data_source.h>
 #include <asiolink/io_address.h>
 #include <asiolink/io_address.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <sstream>
 #include <sstream>

+ 5 - 5
src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc

@@ -41,7 +41,7 @@ public:
 // This test checks that a database access string can be parsed correctly.
 // This test checks that a database access string can be parsed correctly.
 TEST_F(LeaseMgrFactoryTest, parse) {
 TEST_F(LeaseMgrFactoryTest, parse) {
 
 
-    LeaseMgr::ParameterMap parameters = LeaseMgrFactory::parse(
+    DataSource::ParameterMap parameters = LeaseMgrFactory::parse(
         "user=me password=forbidden name=kea somethingelse= type=mysql");
         "user=me password=forbidden name=kea somethingelse= type=mysql");
 
 
     EXPECT_EQ(5, parameters.size());
     EXPECT_EQ(5, parameters.size());
@@ -57,7 +57,7 @@ TEST_F(LeaseMgrFactoryTest, parseInvalid) {
 
 
     // No tokens in the string, so we expect no parameters
     // No tokens in the string, so we expect no parameters
     std::string invalid = "";
     std::string invalid = "";
-    LeaseMgr::ParameterMap parameters = LeaseMgrFactory::parse(invalid);
+    DataSource::ParameterMap parameters = LeaseMgrFactory::parse(invalid);
     EXPECT_EQ(0, parameters.size());
     EXPECT_EQ(0, parameters.size());
 
 
     // With spaces, there are some tokens so we expect invalid parameter
     // With spaces, there are some tokens so we expect invalid parameter
@@ -82,7 +82,7 @@ TEST_F(LeaseMgrFactoryTest, parseInvalid) {
 /// as a set of asterisks.
 /// as a set of asterisks.
 TEST_F(LeaseMgrFactoryTest, redactAccessString) {
 TEST_F(LeaseMgrFactoryTest, redactAccessString) {
 
 
-    LeaseMgr::ParameterMap parameters =
+    DataSource::ParameterMap parameters =
         LeaseMgrFactory::parse("user=me password=forbidden name=kea type=mysql");
         LeaseMgrFactory::parse("user=me password=forbidden name=kea type=mysql");
     EXPECT_EQ(4, parameters.size());
     EXPECT_EQ(4, parameters.size());
     EXPECT_EQ("me", parameters["user"]);
     EXPECT_EQ("me", parameters["user"]);
@@ -108,7 +108,7 @@ TEST_F(LeaseMgrFactoryTest, redactAccessString) {
 /// as a set of asterisks, even if the password is null.
 /// as a set of asterisks, even if the password is null.
 TEST_F(LeaseMgrFactoryTest, redactAccessStringEmptyPassword) {
 TEST_F(LeaseMgrFactoryTest, redactAccessStringEmptyPassword) {
 
 
-    LeaseMgr::ParameterMap parameters =
+    DataSource::ParameterMap parameters =
         LeaseMgrFactory::parse("user=me name=kea type=mysql password=");
         LeaseMgrFactory::parse("user=me name=kea type=mysql password=");
     EXPECT_EQ(4, parameters.size());
     EXPECT_EQ(4, parameters.size());
     EXPECT_EQ("me", parameters["user"]);
     EXPECT_EQ("me", parameters["user"]);
@@ -152,7 +152,7 @@ TEST_F(LeaseMgrFactoryTest, redactAccessStringEmptyPassword) {
 /// was no password to begin with.
 /// was no password to begin with.
 TEST_F(LeaseMgrFactoryTest, redactAccessStringNoPassword) {
 TEST_F(LeaseMgrFactoryTest, redactAccessStringNoPassword) {
 
 
-    LeaseMgr::ParameterMap parameters =
+    DataSource::ParameterMap parameters =
         LeaseMgrFactory::parse("user=me name=kea type=mysql");
         LeaseMgrFactory::parse("user=me name=kea type=mysql");
     EXPECT_EQ(3, parameters.size());
     EXPECT_EQ(3, parameters.size());
     EXPECT_EQ("me", parameters["user"]);
     EXPECT_EQ("me", parameters["user"]);

+ 3 - 22
src/lib/dhcpsrv/tests/lease_mgr_unittest.cc

@@ -43,11 +43,8 @@ public:
     /// dbconfig is a generic way of passing parameters. Parameters
     /// dbconfig is a generic way of passing parameters. Parameters
     /// are passed in the "name=value" format, separated by spaces.
     /// are passed in the "name=value" format, separated by spaces.
     /// Values may be enclosed in double quotes, if needed.
     /// Values may be enclosed in double quotes, if needed.
-    ///
-    /// @param parameters A data structure relating keywords and values
-    ///        concerned with the database.
-    ConcreteLeaseMgr(const LeaseMgr::ParameterMap& parameters)
-        : LeaseMgr(parameters)
+    ConcreteLeaseMgr(const DataSource::ParameterMap&)
+        : LeaseMgr()
     {}
     {}
 
 
     /// @brief Destructor
     /// @brief Destructor
@@ -260,27 +257,11 @@ public:
 
 
 namespace {
 namespace {
 
 
-/// @brief getParameter test
-///
-/// This test checks if the LeaseMgr can be instantiated and that it
-/// parses parameters string properly.
-TEST_F(LeaseMgrTest, getParameter) {
-
-    LeaseMgr::ParameterMap pmap;
-    pmap[std::string("param1")] = std::string("value1");
-    pmap[std::string("param2")] = std::string("value2");
-    ConcreteLeaseMgr leasemgr(pmap);
-
-    EXPECT_EQ("value1", leasemgr.getParameter("param1"));
-    EXPECT_EQ("value2", leasemgr.getParameter("param2"));
-    EXPECT_THROW(leasemgr.getParameter("param3"), BadValue);
-}
-
 // This test checks if getLease6() method is working properly for 0 (NULL),
 // This test checks if getLease6() method is working properly for 0 (NULL),
 // 1 (return the lease) and more than 1 leases (throw).
 // 1 (return the lease) and more than 1 leases (throw).
 TEST_F(LeaseMgrTest, getLease6) {
 TEST_F(LeaseMgrTest, getLease6) {
 
 
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     boost::scoped_ptr<ConcreteLeaseMgr> mgr(new ConcreteLeaseMgr(pmap));
     boost::scoped_ptr<ConcreteLeaseMgr> mgr(new ConcreteLeaseMgr(pmap));
 
 
     vector<Lease6Ptr> leases = createLeases6();
     vector<Lease6Ptr> leases = createLeases6();

+ 13 - 13
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc

@@ -257,7 +257,7 @@ public:
 // This test checks if the LeaseMgr can be instantiated and that it
 // This test checks if the LeaseMgr can be instantiated and that it
 // parses parameters string properly.
 // parses parameters string properly.
 TEST_F(MemfileLeaseMgrTest, constructor) {
 TEST_F(MemfileLeaseMgrTest, constructor) {
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     pmap["persist"] = "false";
     pmap["persist"] = "false";
     boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr;
     boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr;
@@ -295,7 +295,7 @@ TEST_F(MemfileLeaseMgrTest, getLeaseFilePath) {
     LeaseFileIO io4(getLeaseFilePath("leasefile4_1.csv"));
     LeaseFileIO io4(getLeaseFilePath("leasefile4_1.csv"));
     LeaseFileIO io6(getLeaseFilePath("leasefile6_1.csv"));
     LeaseFileIO io6(getLeaseFilePath("leasefile6_1.csv"));
 
 
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     pmap["name"] = getLeaseFilePath("leasefile4_1.csv");
     pmap["name"] = getLeaseFilePath("leasefile4_1.csv");
     boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap));
     boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap));
@@ -317,7 +317,7 @@ TEST_F(MemfileLeaseMgrTest, persistLeases) {
     LeaseFileIO io4(getLeaseFilePath("leasefile4_1.csv"));
     LeaseFileIO io4(getLeaseFilePath("leasefile4_1.csv"));
     LeaseFileIO io6(getLeaseFilePath("leasefile6_1.csv"));
     LeaseFileIO io6(getLeaseFilePath("leasefile6_1.csv"));
 
 
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     // Specify the names of the lease files. Leases will be written.
     // Specify the names of the lease files. Leases will be written.
     pmap["name"] = getLeaseFilePath("leasefile4_1.csv");
     pmap["name"] = getLeaseFilePath("leasefile4_1.csv");
@@ -343,7 +343,7 @@ TEST_F(MemfileLeaseMgrTest, persistLeases) {
 // Check if it is possible to schedule the timer to perform the Lease
 // Check if it is possible to schedule the timer to perform the Lease
 // File Cleanup periodically.
 // File Cleanup periodically.
 TEST_F(MemfileLeaseMgrTest, lfcTimer) {
 TEST_F(MemfileLeaseMgrTest, lfcTimer) {
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     // Specify the names of the lease files. Leases will be written.
     // Specify the names of the lease files. Leases will be written.
@@ -372,7 +372,7 @@ TEST_F(MemfileLeaseMgrTest, lfcTimer) {
 // This test checks if the LFC timer is disabled (doesn't trigger)
 // This test checks if the LFC timer is disabled (doesn't trigger)
 // cleanups when the lfc-interval is set to 0.
 // cleanups when the lfc-interval is set to 0.
 TEST_F(MemfileLeaseMgrTest, lfcTimerDisabled) {
 TEST_F(MemfileLeaseMgrTest, lfcTimerDisabled) {
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
@@ -422,7 +422,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup4) {
     previous_file.writeFile(previous_file_contents);
     previous_file.writeFile(previous_file_contents);
 
 
     // Create the backend.
     // Create the backend.
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
@@ -502,7 +502,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup6) {
     previous_file.writeFile(previous_file_contents);
     previous_file.writeFile(previous_file_contents);
 
 
     // Create the backend.
     // Create the backend.
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "6";
     pmap["universe"] = "6";
     pmap["name"] = getLeaseFilePath("leasefile6_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile6_0.csv");
@@ -577,7 +577,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanupStartFail) {
     setenv("KEA_LFC_EXECUTABLE", "foobar", 1);
     setenv("KEA_LFC_EXECUTABLE", "foobar", 1);
 
 
     // Create the backend.
     // Create the backend.
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
@@ -626,7 +626,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileFinish) {
     finish_file.writeFile(finish_file_contents);
     finish_file.writeFile(finish_file_contents);
 
 
     // Create the backend.
     // Create the backend.
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "6";
     pmap["universe"] = "6";
     pmap["name"] = getLeaseFilePath("leasefile6_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile6_0.csv");
@@ -691,7 +691,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCopy) {
     input_file.writeFile(input_file_contents);
     input_file.writeFile(input_file_contents);
 
 
     // Create the backend.
     // Create the backend.
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "6";
     pmap["universe"] = "6";
     pmap["name"] = getLeaseFilePath("leasefile6_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile6_0.csv");
@@ -729,7 +729,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCopy) {
 // at which the IOService must be executed to run the handlers
 // at which the IOService must be executed to run the handlers
 // for the installed timers.
 // for the installed timers.
 TEST_F(MemfileLeaseMgrTest, getIOServiceExecInterval) {
 TEST_F(MemfileLeaseMgrTest, getIOServiceExecInterval) {
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
@@ -1139,7 +1139,7 @@ TEST_F(MemfileLeaseMgrTest, load4CompletedFile) {
 // lease files if the LFC is in progress.
 // lease files if the LFC is in progress.
 TEST_F(MemfileLeaseMgrTest, load4LFCInProgress) {
 TEST_F(MemfileLeaseMgrTest, load4LFCInProgress) {
     // Create the backend configuration.
     // Create the backend configuration.
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "4";
     pmap["universe"] = "4";
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
@@ -1378,7 +1378,7 @@ TEST_F(MemfileLeaseMgrTest, load6CompletedFile) {
 // lease files if the LFC is in progress.
 // lease files if the LFC is in progress.
 TEST_F(MemfileLeaseMgrTest, load6LFCInProgress) {
 TEST_F(MemfileLeaseMgrTest, load6LFCInProgress) {
     // Create the backend configuration.
     // Create the backend configuration.
-    LeaseMgr::ParameterMap pmap;
+    DataSource::ParameterMap pmap;
     pmap["type"] = "memfile";
     pmap["type"] = "memfile";
     pmap["universe"] = "6";
     pmap["universe"] = "6";
     pmap["name"] = getLeaseFilePath("leasefile6_0.csv");
     pmap["name"] = getLeaseFilePath("leasefile6_0.csv");