]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#92,!13] New libkea-database library created.
authorMarcin Siodelski <marcin@isc.org>
Tue, 28 Aug 2018 09:56:19 +0000 (11:56 +0200)
committerMarcin Siodelski <marcin@isc.org>
Mon, 3 Sep 2018 07:31:33 +0000 (03:31 -0400)
20 files changed:
configure.ac
src/lib/Makefile.am
src/lib/database/Makefile.am [new file with mode: 0644]
src/lib/database/database_connection.cc [new file with mode: 0644]
src/lib/database/database_connection.h [new file with mode: 0644]
src/lib/database/db_exceptions.h [moved from src/lib/dhcpsrv/db_exceptions.h with 98% similarity]
src/lib/database/db_log.cc [moved from src/lib/dhcpsrv/db_log.cc with 88% similarity]
src/lib/database/db_log.h [moved from src/lib/dhcpsrv/db_log.h with 99% similarity]
src/lib/database/tests/Makefile.am [new file with mode: 0644]
src/lib/database/tests/database_connection_unittest.cc [new file with mode: 0644]
src/lib/database/tests/libdatabase_unittests [new file with mode: 0755]
src/lib/database/tests/run_unittests.cc [new file with mode: 0644]
src/lib/dhcpsrv/Makefile.am
src/lib/dhcpsrv/dhcpsrv_db_log.cc
src/lib/dhcpsrv/dhcpsrv_db_log.h
src/lib/dhcpsrv/lease_mgr.h
src/lib/dhcpsrv/mysql_connection.cc
src/lib/dhcpsrv/mysql_connection.h
src/lib/dhcpsrv/mysql_host_data_source.h
src/lib/dhcpsrv/pgsql_connection.h

index 25323f8baff0b3364e9874530ac969a5e95eb639..bb8dc7f0f202163f249296a15ebcc9b81a43315a 100644 (file)
@@ -1534,6 +1534,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/config/tests/testdata/Makefile
                  src/lib/cryptolink/Makefile
                  src/lib/cryptolink/tests/Makefile
+                 src/lib/database/Makefile
+                 src/lib/database/tests/Makefile
                  src/lib/dhcp/Makefile
                  src/lib/dhcp/tests/Makefile
                  src/lib/dhcp_ddns/Makefile
index 9de3269c323b393724c0278d18e75430836dbdc4..50ad1ec787f5ad4c3314b884feb4c109a13953d4 100644 (file)
@@ -1,3 +1,4 @@
 # The following build order must be maintained.
-SUBDIRS = exceptions util log cryptolink dns asiolink cc testutils hooks dhcp \
-          config stats asiodns dhcp_ddns eval dhcpsrv cfgrpt process http
+SUBDIRS = exceptions util log cryptolink dns asiolink cc database testutils \
+               hooks dhcp config stats asiodns dhcp_ddns eval dhcpsrv cfgrpt \
+               process http
diff --git a/src/lib/database/Makefile.am b/src/lib/database/Makefile.am
new file mode 100644 (file)
index 0000000..fac6488
--- /dev/null
@@ -0,0 +1,30 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(KEA_CXXFLAGS)
+
+lib_LTLIBRARIES = libkea-database.la
+libkea_database_la_SOURCES  = database_connection.cc database_connection.h
+libkea_database_la_SOURCES += db_exceptions.h
+libkea_database_la_SOURCES += db_log.cc db_log.h
+
+libkea_database_la_LIBADD  = $(top_builddir)/src/lib/log/libkea-log.la
+libkea_database_la_LIBADD += $(top_builddir)/src/lib/log/interprocess/libkea-log_interprocess.la
+libkea_database_la_LIBADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
+libkea_database_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la
+libkea_database_la_LIBADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+libkea_database_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+libkea_database_la_LIBADD += $(LOG4CPLUS_LIBS) $(BOOST_LIBS)
+
+libkea_database_la_LDFLAGS = -no-undefined -version-info 0:0:0
+
+# The message file should be in the distribution.
+#EXTRA_DIST = config_backend.dox
+
+CLEANFILES = *.gcno *.gcda
+
+# Specify the headers for copying into the installation directory tree.
+#libkea_cb_includedir = $(pkgincludedir)/config
+#libkea_cb_include_HEADERS = 
diff --git a/src/lib/database/database_connection.cc b/src/lib/database/database_connection.cc
new file mode 100644 (file)
index 0000000..2f736e2
--- /dev/null
@@ -0,0 +1,159 @@
+// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <database/database_connection.h>
+#include <database/db_exceptions.h>
+#include <database/db_log.h>
+#include <exceptions/exceptions.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
+#include <vector>
+
+using namespace std;
+
+namespace isc {
+namespace db {
+
+const time_t DatabaseConnection::MAX_DB_TIME = 2147483647;
+
+std::string
+DatabaseConnection::getParameter(const std::string& name) const {
+    ParameterMap::const_iterator param = parameters_.find(name);
+    if (param == parameters_.end()) {
+        isc_throw(BadValue, "Parameter " << name << " not found");
+    }
+    return (param->second);
+}
+
+DatabaseConnection::ParameterMap
+DatabaseConnection::parse(const std::string& dbaccess) {
+    DatabaseConnection::ParameterMap mapped_tokens;
+
+    if (!dbaccess.empty()) {
+        vector<string> tokens;
+
+        // We need to pass a string to is_any_of, not just char*. Otherwise
+        // there are cryptic warnings on Debian6 running g++ 4.4 in
+        // /usr/include/c++/4.4/bits/stl_algo.h:2178 "array subscript is above
+        // array bounds"
+        boost::split(tokens, dbaccess, boost::is_any_of(string("\t ")));
+        BOOST_FOREACH(std::string token, tokens) {
+            size_t pos = token.find("=");
+            if (pos != string::npos) {
+                string name = token.substr(0, pos);
+                string value = token.substr(pos + 1);
+                mapped_tokens.insert(make_pair(name, value));
+            } else {
+                DB_LOG_ERROR(DB_INVALID_ACCESS).arg(dbaccess);
+                isc_throw(InvalidParameter, "Cannot parse " << token
+                          << ", expected format is name=value");
+            }
+        }
+    }
+
+    return (mapped_tokens);
+}
+
+std::string
+DatabaseConnection::redactedAccessString(const ParameterMap& parameters) {
+    // Reconstruct the access string: start of with an empty string, then
+    // work through all the parameters in the original string and add them.
+    std::string access;
+    for (DatabaseConnection::ParameterMap::const_iterator i = parameters.begin();
+         i != parameters.end(); ++i) {
+
+        // Separate second and subsequent tokens are preceded by a space.
+        if (!access.empty()) {
+            access += " ";
+        }
+
+        // Append name of parameter...
+        access += i->first;
+        access += "=";
+
+        // ... and the value, except in the case of the password, where a
+        // redacted value is appended.
+        if (i->first == std::string("password")) {
+            access += "*****";
+        } else {
+            access += i->second;
+        }
+    }
+
+    return (access);
+}
+
+bool
+DatabaseConnection::configuredReadOnly() const {
+    std::string readonly_value = "false";
+    try {
+        readonly_value = getParameter("readonly");
+        boost::algorithm::to_lower(readonly_value);
+    } catch (...) {
+        // Parameter "readonly" hasn't been specified so we simply use
+        // the default value of "false".
+    }
+
+    if ((readonly_value != "false") && (readonly_value != "true")) {
+        isc_throw(DbInvalidReadOnly, "invalid value '" << readonly_value
+                  << "' specified for boolean parameter 'readonly'");
+    }
+
+    return (readonly_value == "true");
+}
+
+ReconnectCtlPtr
+DatabaseConnection::makeReconnectCtl() const {
+    ReconnectCtlPtr retry;
+    string type = "unknown";
+    unsigned int retries = 0;
+    unsigned int interval = 0;
+
+    // Assumes that parsing ensurse only valid values are present
+    try {
+        type = getParameter("type");
+    } catch (...) {
+        // Wasn't specified so we'll use default of "unknown".
+    }
+
+    std::string parm_str;
+    try {
+        parm_str = getParameter("max-reconnect-tries");
+        retries = boost::lexical_cast<unsigned int>(parm_str);
+    } catch (...) {
+        // Wasn't specified so we'll use default of 0;
+    }
+
+    try {
+        parm_str = getParameter("reconnect-wait-time");
+        interval = boost::lexical_cast<unsigned int>(parm_str);
+    } catch (...) {
+        // Wasn't specified so we'll use default of 0;
+    }
+
+    retry.reset(new ReconnectCtl(type, retries, interval));
+    return (retry);
+}
+
+bool
+DatabaseConnection::invokeDbLostCallback() const {
+    if (DatabaseConnection::db_lost_callback) {
+        // Invoke the callback, passing in a new instance of ReconnectCtl
+        return (DatabaseConnection::db_lost_callback)(makeReconnectCtl());
+    }
+
+    return (false);
+}
+
+
+DatabaseConnection::DbLostCallback
+DatabaseConnection::db_lost_callback = 0;
+
+};
+};
diff --git a/src/lib/database/database_connection.h b/src/lib/database/database_connection.h
new file mode 100644 (file)
index 0000000..515e20c
--- /dev/null
@@ -0,0 +1,236 @@
+// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef DATABASE_CONNECTION_H
+#define DATABASE_CONNECTION_H
+
+#include <boost/noncopyable.hpp>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <exceptions/exceptions.h>
+#include <map>
+#include <string>
+
+namespace isc {
+namespace db {
+
+/// @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 Invalid type exception
+///
+/// Thrown when the factory doesn't recognize the type of the backend.
+class InvalidType : public Exception {
+public:
+    InvalidType(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Invalid Timeout
+///
+/// Thrown when the timeout specified for the database connection is invalid.
+class DbInvalidTimeout : public Exception {
+public:
+    DbInvalidTimeout(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Invalid 'readonly' value specification.
+///
+/// Thrown when the value of the 'readonly' boolean parameter is invalid.
+class DbInvalidReadOnly : public Exception {
+public:
+    DbInvalidReadOnly(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Warehouses DB reconnect control values
+///
+/// When a DatabaseConnection loses connectivity to its backend, it
+/// creates an instance of this class based on its configuration parameters and
+/// passes the instance into connection's DB lost callback.  This allows
+/// the layer(s) above the connection to know how to proceed.
+///
+class ReconnectCtl {
+public:
+    /// @brief Constructor
+    /// @param backend_type type of the caller backend.
+    /// @param max_retries maximum number of reconnect attempts to make
+    /// @param retry_interval amount of time to between reconnect attempts
+    ReconnectCtl(const std::string& backend_type, unsigned int max_retries,
+                 unsigned int retry_interval)
+        : backend_type_(backend_type), max_retries_(max_retries),
+          retries_left_(max_retries), retry_interval_(retry_interval) {}
+
+    /// @brief Returns the type of the caller backend.
+    std::string backendType() const {
+        return (backend_type_);
+    }
+
+    /// @brief Decrements the number of retries remaining
+    ///
+    /// Each call decrements the number of retries by one until zero is reached.
+    /// @return true the number of retries remaining is greater than zero.
+    bool checkRetries() {
+        return (retries_left_ ? --retries_left_ : false);
+    }
+
+    /// @brief Returns the maximum number for retries allowed 
+    unsigned int maxRetries() {
+        return (max_retries_);
+    }
+
+    /// @brief Returns the number for retries remaining
+    unsigned int retriesLeft() {
+        return (retries_left_);
+    }
+
+    /// @brief Returns the amount of time to wait between reconnect attempts
+    unsigned int retryInterval() {
+        return (retry_interval_);
+    }
+
+private:
+    /// @brief Caller backend type.
+    const std::string backend_type_;
+
+    /// @brief Maximum number of retry attempts to make
+    unsigned int max_retries_;
+
+    /// @brief Number of attempts remaining
+    unsigned int retries_left_;
+
+    /// @brief The amount of time to wait between reconnect attempts
+    unsigned int retry_interval_;
+};
+
+/// @brief Pointer to an instance of ReconnectCtl
+typedef boost::shared_ptr<ReconnectCtl> ReconnectCtlPtr;
+
+/// @brief Common database connection class.
+///
+/// This class provides functions that are common for establishing
+/// connection with different types of databases; enables operations
+/// on access parameters strings. In particular, it provides a way
+/// to parse parameters in key=value format. This class is expected
+/// to be a base class for all @ref LeaseMgr and possibly
+/// @ref BaseHostDataSource derived classes.
+class DatabaseConnection : public boost::noncopyable {
+public:
+
+    /// @brief Defines maximum value for time that can be reliably stored.
+    ///
+    /// @todo: Is this common for MySQL and Postgres? Maybe we should have
+    /// specific values for each backend?
+    ///
+    /// If I'm still alive I'll be too old to care. You fix it.
+    static const time_t MAX_DB_TIME;
+
+    /// @brief Database configuration parameter map
+    typedef std::map<std::string, std::string> ParameterMap;
+
+    /// @brief Constructor
+    ///
+    /// @param parameters A data structure relating keywords and values
+    ///        concerned with the database.
+    DatabaseConnection(const ParameterMap& parameters)
+        :parameters_(parameters) {
+    }
+
+    /// @brief Destructor
+    virtual ~DatabaseConnection(){};
+
+    /// @brief Instantiates a ReconnectCtl based on the connection's
+    /// reconnect parameters
+    /// @return pointer to the new ReconnectCtl object
+    virtual ReconnectCtlPtr makeReconnectCtl() const;
+
+    /// @brief Returns value of a connection parameter.
+    ///
+    /// @param name Name of the parameter which value should be returned.
+    /// @return Value of one of the connection parameters.
+    /// @throw BadValue if parameter is not found
+    std::string getParameter(const std::string& name) const;
+
+    /// @brief Parse database access string
+    ///
+    /// Parses the string of "keyword=value" pairs and separates them
+    /// out into the map.
+    ///
+    /// @param dbaccess Database access string.
+    ///
+    /// @return @ref ParameterMap of keyword/value pairs.
+    static ParameterMap parse(const std::string& dbaccess);
+
+    /// @brief Redact database access string
+    ///
+    /// Takes the database parameters and returns a database access string
+    /// passwords replaced by asterisks. This string is used in log messages.
+    ///
+    /// @param parameters Database access parameters (output of "parse").
+    ///
+    /// @return Redacted database access string.
+    static std::string redactedAccessString(const ParameterMap& parameters);
+
+    /// @brief Convenience method checking if database should be opened with
+    /// read only access.
+    ///
+    /// @return true if "readonly" parameter is specified and set to true;
+    /// false if "readonly" parameter is not specified or it is specified
+    /// and set to false.
+    bool configuredReadOnly() const;
+
+    /// @brief Defines a callback prototype for propogating events upward
+    typedef boost::function<bool (ReconnectCtlPtr db_retry)> DbLostCallback;
+
+    /// @brief Invokes the connection's lost connectivity callback
+    ///
+    /// This function may be called by derivations when the connectivity
+    /// to their data server is lost.  If connectivity callback was specified,
+    /// this function will instantiate a ReconnectCtl and pass it to the
+    /// callback.
+    ///
+    /// @return Returns the result of the callback or false if there is no
+    /// callback.
+    bool invokeDbLostCallback() const;
+
+    /// @brief Optional call back function to invoke if a successfully
+    /// open connection subsequently fails
+    static DbLostCallback db_lost_callback;
+
+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_;
+
+};
+
+}; // end of isc::db namespace
+}; // end of isc namespace
+
+#endif // DATABASE_CONNECTION_H
similarity index 98%
rename from src/lib/dhcpsrv/db_exceptions.h
rename to src/lib/database/db_exceptions.h
index 1bf92a38bfb564f05c8b1334b8ff8fed5135d440..04b216bfc1745b59666d90d145ed26a4eaa1f99a 100644 (file)
@@ -10,7 +10,7 @@
 #include <exceptions/exceptions.h>
 
 namespace isc {
-namespace dhcp {
+namespace db {
 
 /// @brief Database statement not applied
 ///
@@ -75,6 +75,6 @@ public:
 };
 
 }  // namespace isc
-}  // namespace dhcp
+}  // namespace db
 
 #endif
similarity index 88%
rename from src/lib/dhcpsrv/db_log.cc
rename to src/lib/database/db_log.cc
index f2e3cd0a42a8ad2fdf82f4195606d9c980059461..75ee637d2a9fc3c90e626455e85d49371959d5ab 100644 (file)
@@ -9,13 +9,14 @@
 #include <config.h>
 
 #include <exceptions/exceptions.h>
-#include <dhcpsrv/db_log.h>
-#include <dhcpsrv/dhcpsrv_db_log.h>
+#include <database/db_log.h>
 
 using namespace isc::log;
 
 namespace isc {
-namespace dhcp {
+namespace db {
+
+DbLoggerStack db_logger_stack;
 
 const MessageID&
 DbLogger::translateMessage(const DbMessageID& id) const {
@@ -32,5 +33,5 @@ void checkDbLoggerStack() {
     }
 }
 
-} // namespace dhcp
+} // namespace db
 } // namespace isc
similarity index 99%
rename from src/lib/dhcpsrv/db_log.h
rename to src/lib/database/db_log.h
index 4eb76d6a0a1ceb2c93d7db30351f10a944997841..de7bd9f93fdf85f4d34a31746a5c0f6f24ada888 100644 (file)
@@ -24,7 +24,7 @@
 /// logger with mapped messages.
 
 namespace isc {
-namespace dhcp {
+namespace db {
 
 ///@{
 /// @brief Database logging levels
@@ -146,7 +146,7 @@ void checkDbLoggerStack();
 
 ///@}
 
-} // namespace dhcp
+} // namespace db
 } // namespace isc
 
 #endif // DB_LOG_H
diff --git a/src/lib/database/tests/Makefile.am b/src/lib/database/tests/Makefile.am
new file mode 100644 (file)
index 0000000..f38929b
--- /dev/null
@@ -0,0 +1,39 @@
+SUBDIRS = .
+
+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/config/tests\"
+
+AM_CXXFLAGS = $(KEA_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS_ENVIRONMENT = \
+       $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
+
+TESTS =
+if HAVE_GTEST
+TESTS += libdatabase_unittests
+
+libdatabase_unittests_SOURCES  = database_connection_unittest.cc
+libdatabase_unittests_SOURCES += run_unittests.cc
+
+libdatabase_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+libdatabase_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+
+libdatabase_unittests_LDADD  = $(top_builddir)/src/lib/database/libkea-database.la
+libdatabase_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
+libdatabase_unittests_LDADD += $(top_builddir)/src/lib/log/interprocess/libkea-log_interprocess.la
+libdatabase_unittests_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
+libdatabase_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
+libdatabase_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+libdatabase_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+libdatabase_unittests_LDADD += $(LOG4CPLUS_LIBS) $(BOOST_LIBS) $(GTEST_LDADD)
+
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/database/tests/database_connection_unittest.cc b/src/lib/database/tests/database_connection_unittest.cc
new file mode 100644 (file)
index 0000000..a564697
--- /dev/null
@@ -0,0 +1,249 @@
+// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+#include <exceptions/exceptions.h>
+#include <database/database_connection.h>
+#include <gtest/gtest.h>
+
+#include <boost/bind.hpp>
+
+using namespace isc::db;
+
+/// @brief Test fixture for exercising DbLostCallback invocation
+class DatabaseConnectionCallbackTest : public ::testing::Test {
+public:
+    /// Constructor
+    DatabaseConnectionCallbackTest()
+        : db_reconnect_ctl_(0) {
+    }
+
+    /// @brief Callback to register with a DatabaseConnection
+    ///
+    /// @param db_reconnect_ctl ReconnectCtl containing reconnect
+    /// parameters
+    bool dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
+        if (!db_reconnect_ctl) {
+            isc_throw(isc::BadValue, "db_reconnect_ctl should not be null");
+        }
+
+        db_reconnect_ctl_ = db_reconnect_ctl;
+        return (true);
+    }
+
+    /// @brief Retainer for the control passed into the callback
+    ReconnectCtlPtr db_reconnect_ctl_;
+};
+
+/// @brief getParameter test
+///
+/// This test checks if the LeaseMgr can be instantiated and that it
+/// parses parameters string properly.
+TEST(DatabaseConnectionTest, getParameter) {
+
+    DatabaseConnection::ParameterMap pmap;
+    pmap[std::string("param1")] = std::string("value1");
+    pmap[std::string("param2")] = std::string("value2");
+    DatabaseConnection datasrc(pmap);
+
+    EXPECT_EQ("value1", datasrc.getParameter("param1"));
+    EXPECT_EQ("value2", datasrc.getParameter("param2"));
+    EXPECT_THROW(datasrc.getParameter("param3"), isc::BadValue);
+}
+
+/// @brief NoDbLostCallback
+///
+/// This test verifies that DatabaseConnection::invokeDbLostCallback
+/// returns a false if there is connection has no registered
+/// DbLostCallback.
+TEST_F(DatabaseConnectionCallbackTest, NoDbLostCallback) {
+    DatabaseConnection::ParameterMap pmap;
+    pmap[std::string("type")] = std::string("test");
+    pmap[std::string("max-reconnect-tries")] = std::string("3");
+    pmap[std::string("reconnect-wait-time")] = std::string("60");
+    DatabaseConnection datasrc(pmap);
+
+    bool ret = false;
+    ASSERT_NO_THROW(ret = datasrc.invokeDbLostCallback());
+    EXPECT_FALSE(ret);
+    EXPECT_FALSE(db_reconnect_ctl_);
+}
+
+/// @brief dbLostCallback
+///
+/// This test verifies that DatabaseConnection::invokeDbLostCallback
+/// safely invokes the registered DbLostCallback.  It also tests
+/// operation of DbReconnectCtl retry accounting methods.
+TEST_F(DatabaseConnectionCallbackTest, dbLostCallback) {
+    /// Create a Database configuration that includes the reconnect
+    /// control parameters.
+    DatabaseConnection::ParameterMap pmap;
+    pmap[std::string("type")] = std::string("test");
+    pmap[std::string("max-reconnect-tries")] = std::string("3");
+    pmap[std::string("reconnect-wait-time")] = std::string("60");
+
+    /// Install the callback.
+    DatabaseConnection::db_lost_callback =
+        boost::bind(&DatabaseConnectionCallbackTest::dbLostCallback, this, _1);
+    /// Create the connection..
+    DatabaseConnection datasrc(pmap);
+
+    /// We should be able to invoke the callback and glean
+    /// the correct reconnect contorl parameters from it.
+    bool ret = false;
+    ASSERT_NO_THROW(ret = datasrc.invokeDbLostCallback());
+    EXPECT_TRUE(ret);
+    ASSERT_TRUE(db_reconnect_ctl_);
+    ASSERT_EQ("test", db_reconnect_ctl_->backendType());
+    ASSERT_EQ(3, db_reconnect_ctl_->maxRetries());
+    ASSERT_EQ(3, db_reconnect_ctl_->retriesLeft());
+    EXPECT_EQ(60, db_reconnect_ctl_->retryInterval());
+
+    /// Verify that checkRetries() correctly decrements
+    /// down to zero, and that retriesLeft() returns
+    /// the correct value.
+    for (int i = 3; i > 1 ; --i) {
+        ASSERT_EQ(i, db_reconnect_ctl_->retriesLeft());
+        ASSERT_TRUE(db_reconnect_ctl_->checkRetries());
+    }
+
+    /// Retries are exhausted, verify that's reflected.
+    EXPECT_FALSE(db_reconnect_ctl_->checkRetries());
+    EXPECT_EQ(0, db_reconnect_ctl_->retriesLeft());
+    EXPECT_EQ(3, db_reconnect_ctl_->maxRetries());
+}
+
+// This test checks that a database access string can be parsed correctly.
+TEST(DatabaseConnectionTest, parse) {
+
+    DatabaseConnection::ParameterMap parameters = DatabaseConnection::parse(
+        "user=me password=forbidden name=kea somethingelse= type=mysql");
+
+    EXPECT_EQ(5, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("forbidden", parameters["password"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+    EXPECT_EQ("", parameters["somethingelse"]);
+}
+
+// This test checks that an invalid database access string behaves as expected.
+TEST(DatabaseConnectionTest, parseInvalid) {
+
+    // No tokens in the string, so we expect no parameters
+    std::string invalid = "";
+    DatabaseConnection::ParameterMap parameters = DatabaseConnection::parse(invalid);
+    EXPECT_EQ(0, parameters.size());
+
+    // With spaces, there are some tokens so we expect invalid parameter
+    // as there are no equals signs.
+    invalid = "   \t  ";
+    EXPECT_THROW(DatabaseConnection::parse(invalid), isc::InvalidParameter);
+
+    invalid = "   noequalshere  ";
+    EXPECT_THROW(DatabaseConnection::parse(invalid), isc::InvalidParameter);
+
+    // A single "=" is valid string, but is placed here as the result is
+    // expected to be nothing.
+    invalid = "=";
+    parameters = DatabaseConnection::parse(invalid);
+    EXPECT_EQ(1, parameters.size());
+    EXPECT_EQ("", parameters[""]);
+}
+
+/// @brief redactConfigString test
+///
+/// Checks that the redacted configuration string includes the password only
+/// as a set of asterisks.
+TEST(DatabaseConnectionTest, redactAccessString) {
+
+    DatabaseConnection::ParameterMap parameters =
+        DatabaseConnection::parse("user=me password=forbidden name=kea type=mysql");
+    EXPECT_EQ(4, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("forbidden", parameters["password"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+
+    // Redact the result.  To check, break the redacted string down into its
+    // components.
+    std::string redacted = DatabaseConnection::redactedAccessString(parameters);
+    parameters = DatabaseConnection::parse(redacted);
+
+    EXPECT_EQ(4, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("*****", parameters["password"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+}
+
+/// @brief redactConfigString test - empty password
+///
+/// Checks that the redacted configuration string includes the password only
+/// as a set of asterisks, even if the password is null.
+TEST(DatabaseConnectionTest, redactAccessStringEmptyPassword) {
+
+    DatabaseConnection::ParameterMap parameters =
+        DatabaseConnection::parse("user=me name=kea type=mysql password=");
+    EXPECT_EQ(4, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("", parameters["password"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+
+    // Redact the result.  To check, break the redacted string down into its
+    // components.
+    std::string redacted = DatabaseConnection::redactedAccessString(parameters);
+    parameters = DatabaseConnection::parse(redacted);
+
+    EXPECT_EQ(4, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("*****", parameters["password"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+
+    // ... and again to check that the position of the empty password in the
+    // string does not matter.
+    parameters = DatabaseConnection::parse("user=me password= name=kea type=mysql");
+    EXPECT_EQ(4, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("", parameters["password"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+
+    redacted = DatabaseConnection::redactedAccessString(parameters);
+    parameters = DatabaseConnection::parse(redacted);
+
+    EXPECT_EQ(4, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("*****", parameters["password"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+}
+
+/// @brief redactConfigString test - no password
+///
+/// Checks that the redacted configuration string excludes the password if there
+/// was no password to begin with.
+TEST(DatabaseConnectionTest, redactAccessStringNoPassword) {
+
+    DatabaseConnection::ParameterMap parameters =
+        DatabaseConnection::parse("user=me name=kea type=mysql");
+    EXPECT_EQ(3, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+
+    // Redact the result.  To check, break the redacted string down into its
+    // components.
+    std::string redacted = DatabaseConnection::redactedAccessString(parameters);
+    parameters = DatabaseConnection::parse(redacted);
+
+    EXPECT_EQ(3, parameters.size());
+    EXPECT_EQ("me", parameters["user"]);
+    EXPECT_EQ("kea", parameters["name"]);
+    EXPECT_EQ("mysql", parameters["type"]);
+}
diff --git a/src/lib/database/tests/libdatabase_unittests b/src/lib/database/tests/libdatabase_unittests
new file mode 100755 (executable)
index 0000000..aaba95c
--- /dev/null
@@ -0,0 +1,210 @@
+#! /bin/sh
+
+# libdatabase_unittests - temporary wrapper script for .libs/libdatabase_unittests
+# Generated by libtool (GNU libtool) 2.4.6
+#
+# The libdatabase_unittests program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=""
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='2.4.6'
+  notinst_deplibs=' ../../../../src/lib/database/libkea-database.la /Users/marcin/devel/kea/src/lib/log/libkea-log.la /Users/marcin/devel/kea/src/lib/asiolink/libkea-asiolink.la ../../../../src/lib/log/libkea-log.la /Users/marcin/devel/kea/src/lib/util/threads/libkea-threads.la /Users/marcin/devel/kea/src/lib/util/libkea-util.la ../../../../src/lib/util/threads/libkea-threads.la ../../../../src/lib/util/libkea-util.la ../../../../src/lib/asiolink/libkea-asiolink.la /Users/marcin/devel/kea/src/lib/exceptions/libkea-exceptions.la ../../../../src/lib/exceptions/libkea-exceptions.la'
+else
+  # When we are sourced in execute mode, $file and $ECHO are already set.
+  if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+    file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+    ECHO="printf %s\\n"
+  fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ that is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options that match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../../../../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+  lt_script_arg0=$0
+  shift
+  for lt_opt
+  do
+    case "$lt_opt" in
+    --lt-debug) lt_option_debug=1 ;;
+    --lt-dump-script)
+        lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+        test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+        lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'`
+        cat "$lt_dump_D/$lt_dump_F"
+        exit 0
+      ;;
+    --lt-*)
+        $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+        exit 1
+      ;;
+    esac
+  done
+
+  # Print the debug banner immediately:
+  if test -n "$lt_option_debug"; then
+    echo "libdatabase_unittests:libdatabase_unittests:$LINENO: libtool wrapper (GNU libtool) 2.4.6" 1>&2
+  fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+  lt_dump_args_N=1;
+  for lt_arg
+  do
+    $ECHO "libdatabase_unittests:libdatabase_unittests:$LINENO: newargv[$lt_dump_args_N]: $lt_arg"
+    lt_dump_args_N=`expr $lt_dump_args_N + 1`
+  done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+      if test -n "$lt_option_debug"; then
+        $ECHO "libdatabase_unittests:libdatabase_unittests:$LINENO: newargv[0]: $progdir/$program" 1>&2
+        func_lt_dump_args ${1+"$@"} 1>&2
+      fi
+      exec "$progdir/$program" ${1+"$@"}
+
+      $ECHO "$0: cannot exec $program $*" 1>&2
+      exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+  case " $* " in
+  *\ --lt-*)
+    for lt_wr_arg
+    do
+      case $lt_wr_arg in
+      --lt-*) ;;
+      *) set x "$@" "$lt_wr_arg"; shift;;
+      esac
+      shift
+    done ;;
+  esac
+  func_exec_program_core ${1+"$@"}
+}
+
+  # Parse options
+  func_parse_lt_options "$0" ${1+"$@"}
+
+  # Find the directory that this script lives in.
+  thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
+  test "x$thisdir" = "x$file" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'`
+  while test -n "$file"; do
+    destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
+
+    # If there was a directory component, then change thisdir.
+    if test "x$destdir" != "x$file"; then
+      case "$destdir" in
+      [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+      *) thisdir="$thisdir/$destdir" ;;
+      esac
+    fi
+
+    file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'`
+    file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+  if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+    # special case for '.'
+    if test "$thisdir" = "."; then
+      thisdir=`pwd`
+    fi
+    # remove .libs from thisdir
+    case "$thisdir" in
+    *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;;
+    .libs )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=`cd "$thisdir" && pwd`
+  test -n "$absdir" && thisdir="$absdir"
+
+  program='libdatabase_unittests'
+  progdir="$thisdir/.libs"
+
+
+  if test -f "$progdir/$program"; then
+    # Add our own library path to DYLD_LIBRARY_PATH
+    DYLD_LIBRARY_PATH="/Users/marcin/devel/kea/src/lib/database/.libs:/Users/marcin/devel/kea/src/lib/log/.libs:/Users/marcin/devel/kea/src/lib/asiolink/.libs:/Users/marcin/devel/kea/src/lib/util/threads/.libs:/Users/marcin/devel/kea/src/lib/util/.libs:/Users/marcin/devel/kea/src/lib/exceptions/.libs:$DYLD_LIBRARY_PATH"
+
+    # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'`
+
+    export DYLD_LIBRARY_PATH
+
+    if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+      # Run the actual program with our arguments.
+      func_exec_program ${1+"$@"}
+    fi
+  else
+    # The program doesn't exist.
+    $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2
+    $ECHO "This script is just a wrapper for $program." 1>&2
+    $ECHO "See the libtool documentation for more information." 1>&2
+    exit 1
+  fi
+fi
diff --git a/src/lib/database/tests/run_unittests.cc b/src/lib/database/tests/run_unittests.cc
new file mode 100644 (file)
index 0000000..4e83d4b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <log/logger_support.h>
+#include <gtest/gtest.h>
+
+int
+main(int argc, char* argv[]) {
+    ::testing::InitGoogleTest(&argc, argv);
+    isc::log::initLogger();
+
+    int result = RUN_ALL_TESTS();
+
+    return (result);
+}
index 8432c7265ac85eaf18e1fab1f6c87bcdba718e95..77817aef12a49b49883352401aeccfb68ad0b7b2 100644 (file)
@@ -115,9 +115,6 @@ 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_mgr.cc d2_client_mgr.h
 libkea_dhcpsrv_la_SOURCES += daemon.cc daemon.h
-libkea_dhcpsrv_la_SOURCES += database_connection.cc database_connection.h
-libkea_dhcpsrv_la_SOURCES += db_exceptions.h
-libkea_dhcpsrv_la_SOURCES += db_log.cc db_log.h
 libkea_dhcpsrv_la_SOURCES += db_type.h
 libkea_dhcpsrv_la_SOURCES += dhcp4o6_ipc.cc dhcp4o6_ipc.h
 libkea_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h
@@ -220,6 +217,7 @@ libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/cc/libkea-cc.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/dns/libkea-dns++.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/hooks/libkea-hooks.la
+libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/database/libkea-database.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/log/libkea-log.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/util/threads/libkea-threads.la
 libkea_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/util/libkea-util.la
index 013d8c469dc9b4ed357f37a886c58e8bd67d77cd..4afff06545134e37f99765af668b44012db6e9dc 100644 (file)
@@ -11,6 +11,8 @@
 #include <dhcpsrv/dhcpsrv_db_log.h>
 #include <dhcpsrv/dhcpsrv_log.h>
 
+using namespace isc::db;
+
 namespace isc {
 namespace dhcp {
 
@@ -38,7 +40,7 @@ const DbLogger::MessageMap dhcpsrv_db_message_map = {
 DbLogger dhcpsrv_db_logger(dhcpsrv_logger, dhcpsrv_db_message_map);
 
 // Do this initialization here!
-DbLoggerStack db_logger_stack = { dhcpsrv_db_logger };
+//DbLoggerStack db_logger_stack = { dhcpsrv_db_logger };
 
 
 } // namespace dhcp
index 5965350cfe2e65c601ed5a9bead2d6ee4edd193c..d5056243fdf117b44a8ae7020efe4940c2263200 100644 (file)
@@ -7,18 +7,18 @@
 #ifndef DHCPSRV_DB_LOG_H
 #define DHCPSRV_DB_LOG_H
 
-#include <dhcpsrv/db_log.h>
+#include <database/db_log.h>
 
 namespace isc {
 namespace dhcp {
 
 /// @brief DHCP server database message map
-extern const DbLogger::MessageMap dhcpsrv_db_message_map;
+extern const db::DbLogger::MessageMap dhcpsrv_db_message_map;
 
 /// @brief DHCP server database Logger
 ///
 /// It is the default database logger.
-extern DbLogger dhcpsrv_db_logger;
+extern db::DbLogger dhcpsrv_db_logger;
 
 } // namespace dhcp
 } // namespace isc
index e5759973fddf837395700619fbb421d5918a2093..167645ee320549f50a1404d031123baf2399b5f1 100644 (file)
@@ -9,12 +9,12 @@
 
 #include <asiolink/io_address.h>
 #include <asiolink/io_service.h>
+#include <database/db_exceptions.h>
 #include <dhcp/duid.h>
 #include <dhcp/option.h>
 #include <dhcp/hwaddr.h>
 #include <dhcpsrv/lease.h>
 #include <dhcpsrv/subnet.h>
-#include <dhcpsrv/db_exceptions.h>
 #include <dhcpsrv/sql_common.h>
 
 #include <boost/noncopyable.hpp>
index a4de082a5f6aa93ac8b471a62a36a190e71c45d2..7929aa3924f946f70d742427d56226da3b28c2ff 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <config.h>
 
-#include <dhcpsrv/db_log.h>
+#include <database/db_log.h>
 #include <dhcpsrv/mysql_connection.h>
 #include <exceptions/exceptions.h>
 
index 88716d26cd7132eec14c1da4e827655b5c577867..5ad549d61d3c87853cfbaa0b01ea2ba8a00538d0 100644 (file)
@@ -7,8 +7,8 @@
 #ifndef MYSQL_CONNECTION_H
 #define MYSQL_CONNECTION_H
 
-#include <dhcpsrv/database_connection.h>
-#include <dhcpsrv/db_log.h>
+#include <database/database_connection.h>
+#include <database/db_log.h>
 #include <exceptions/exceptions.h>
 #include <boost/scoped_ptr.hpp>
 #include <mysql.h>
@@ -117,7 +117,7 @@ public:
     /// @throw DbOpenError Unable to initialize MySql handle.
     MySqlHolder() : mysql_(mysql_init(NULL)) {
         if (mysql_ == NULL) {
-            isc_throw(DbOpenError, "unable to initialize MySQL");
+            isc_throw(db::DbOpenError, "unable to initialize MySQL");
         }
     }
 
@@ -208,7 +208,7 @@ private:
 /// to the database and preparing compiled statements. Its fields are
 /// public, because they are used (both set and retrieved) in classes
 /// that use instances of MySqlConnection.
-class MySqlConnection : public DatabaseConnection {
+class MySqlConnection : public db::DatabaseConnection {
 public:
 
     /// @brief Constructor
index fb6e8274a403115fd846070fed2ca09ead60f09d..5e47c1dc1277720151d6ccef703617fd541164ce 100644 (file)
@@ -7,8 +7,8 @@
 #ifndef MYSQL_HOST_DATA_SOURCE_H
 #define MYSQL_HOST_DATA_SOURCE_H
 
+#include <database/db_exceptions.h>
 #include <dhcpsrv/base_host_data_source.h>
-#include <dhcpsrv/db_exceptions.h>
 #include <dhcpsrv/mysql_connection.h>
 
 #include <stdint.h>
index 49fda1444e91b767533a94df30eedb0d83e702ab..081aeedd4975e49f73bc96ca0ea2d53722aa740c 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef PGSQL_CONNECTION_H
 #define PGSQL_CONNECTION_H
 
-#include <dhcpsrv/database_connection.h>
+#include <database/database_connection.h>
 
 #include <libpq-fe.h>
 #include <boost/scoped_ptr.hpp>