2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-29 13:07:50 +00:00

[#3019] retry db open on startup

This commit is contained in:
Razvan Becheriu 2023-10-18 18:30:33 +03:00
parent 463ede2e5a
commit d781e915cd
84 changed files with 8851 additions and 7282 deletions

View File

@ -408,6 +408,10 @@
// serve-retry-continue // serve-retry-continue
"on-fail": "stop-retry-exit", "on-fail": "stop-retry-exit",
// Flag which indicates if the DB recovery should be attempted
// at server startup and on reconfiguration events.
"retry-on-startup": false,
// Connection connect timeout in seconds. // Connection connect timeout in seconds.
"connect-timeout": 100, "connect-timeout": 100,

View File

@ -42,6 +42,7 @@
// "reconnect-wait-time": 3000, // expressed in ms // "reconnect-wait-time": 3000, // expressed in ms
// "max-reconnect-tries": 3, // "max-reconnect-tries": 3,
// "on-fail": "stop-retry-exit", // "on-fail": "stop-retry-exit",
// "retry-on-startup": false,
// "connect-timeout": 3 // "connect-timeout": 3
// }, // },
@ -62,6 +63,7 @@
// "reconnect-wait-time": 3000, // expressed in ms // "reconnect-wait-time": 3000, // expressed in ms
// "max-reconnect-tries": 3, // "max-reconnect-tries": 3,
// "on-fail": "stop-retry-exit", // "on-fail": "stop-retry-exit",
// "retry-on-startup": false,
// "connect-timeout": 3 // "connect-timeout": 3
// }, // },

View File

@ -350,6 +350,10 @@
// serve-retry-continue // serve-retry-continue
"on-fail": "stop-retry-exit", "on-fail": "stop-retry-exit",
// Flag which indicates if the DB recovery should be attempted
// at server startup and on reconfiguration events.
"retry-on-startup": false,
// Connection connect timeout in seconds. // Connection connect timeout in seconds.
"connect-timeout": 100, "connect-timeout": 100,

View File

@ -42,6 +42,7 @@
// "reconnect-wait-time": 3000, // expressed in ms // "reconnect-wait-time": 3000, // expressed in ms
// "max-reconnect-tries": 3, // "max-reconnect-tries": 3,
// "on-fail": "stop-retry-exit", // "on-fail": "stop-retry-exit",
// "retry-on-startup": false,
// "connect-timeout": 3 // "connect-timeout": 3
// }, // },
@ -62,6 +63,7 @@
// "reconnect-wait-time": 3000, // expressed in ms // "reconnect-wait-time": 3000, // expressed in ms
// "max-reconnect-tries": 3, // "max-reconnect-tries": 3,
// "on-fail": "stop-retry-exit", // "on-fail": "stop-retry-exit",
// "retry-on-startup": false,
// "connect-timeout": 3 // "connect-timeout": 3
// }, // },

View File

@ -6,9 +6,9 @@ Database Connectivity
The Kea servers (:iscman:`kea-dhcp4` and :iscman:`kea-dhcp6`) can be configured to use a variety of The Kea servers (:iscman:`kea-dhcp4` and :iscman:`kea-dhcp6`) can be configured to use a variety of
database backends for leases, hosts, and configuration. They can be database backends for leases, hosts, and configuration. They can be
configured to support automatic recovery when connectivity is lost, via configured to support automatic recovery when connectivity is lost, via
the ``on-fail`` parameter. (The ``reconnect-wait-time`` and the ``on-fail`` and ``retry-on-startup`` parameters.
``max-reconnect-tries`` parameters are described (The ``reconnect-wait-time`` and ``max-reconnect-tries`` parameters are
in :ref:`database-configuration4` and :ref:`database-configuration6`.) described in :ref:`database-configuration4` and :ref:`database-configuration6`.)
It is important to understand how and when automatic recovery comes into play. It is important to understand how and when automatic recovery comes into play.
Automatic recovery, when configured, only operates after a successful startup Automatic recovery, when configured, only operates after a successful startup
@ -16,10 +16,13 @@ or reconfiguration during which connectivity to all backends has been
successfully established. successfully established.
During server startup, the inability to connect to any of the configured During server startup, the inability to connect to any of the configured
backends is always considered fatal. A fatal error is logged and the server backends is considered fatal only if ``retry-on-startup`` is set to ``false``.
exits, based on the idea that the configuration should be valid A fatal error is logged and the server exits, based on the idea that the
at startup. Exiting to the operating system allows nanny scripts to detect configuration should be valid at startup. Exiting to the operating system allows
the problem. nanny scripts to detect the problem.
If ``retry-on-startup`` is set to ``true``, the server will start reconnection
attempts even at server startup or on reconfigure events, and will honor the
action specified in ``on-fail`` parameter.
During dynamic reconfiguration, all backends are disconnected and then During dynamic reconfiguration, all backends are disconnected and then
reconnected using the new configuration. If connectivity to any of the reconnected using the new configuration. If connectivity to any of the

View File

@ -576,6 +576,19 @@ The possible values are:
active while processing DHCP traffic. Change this only if the server is used active while processing DHCP traffic. Change this only if the server is used
exclusively as a configuration tool. exclusively as a configuration tool.
::
"Dhcp4": { "lease-database": { "retry-on-startup" : true, ... }, ... }
During server startup, the inability to connect to any of the configured
backends is considered fatal only if ``retry-on-startup`` is set to ``false``.
A fatal error is logged and the server exits, based on the idea that the
configuration should be valid at startup. Exiting to the operating system allows
nanny scripts to detect the problem.
If ``retry-on-startup`` is set to ``true``, the server will start reconnection
attempts even at server startup or on reconfigure events, and will honor the
action specified in ``on-fail`` parameter.
The host parameter is used by the MySQL and PostgreSQL backends. The host parameter is used by the MySQL and PostgreSQL backends.
Finally, the credentials of the account under which the server will Finally, the credentials of the account under which the server will
@ -798,6 +811,19 @@ The possible values are:
the lease database backend and the hosts database backend are connected to the lease database backend and the hosts database backend are connected to
the same database instance. the same database instance.
::
"Dhcp4": { "hosts-database": { "retry-on-startup" : true, ... }, ... }
During server startup, the inability to connect to any of the configured
backends is considered fatal only if ``retry-on-startup`` is set to ``false``.
A fatal error is logged and the server exits, based on the idea that the
configuration should be valid at startup. Exiting to the operating system allows
nanny scripts to detect the problem.
If ``retry-on-startup`` is set to ``true``, the server will start reconnection
attempts even at server startup or on reconfigure events, and will honor the
action specified in ``on-fail`` parameter.
Finally, the credentials of the account under which the server will Finally, the credentials of the account under which the server will
access the database should be set: access the database should be set:

View File

@ -532,6 +532,19 @@ The possible values are:
active while processing DHCP traffic. Change this only if the server is used active while processing DHCP traffic. Change this only if the server is used
exclusively as a configuration tool. exclusively as a configuration tool.
::
"Dhcp6": { "lease-database": { "retry-on-startup" : true, ... }, ... }
During server startup, the inability to connect to any of the configured
backends is considered fatal only if ``retry-on-startup`` is set to ``false``.
A fatal error is logged and the server exits, based on the idea that the
configuration should be valid at startup. Exiting to the operating system allows
nanny scripts to detect the problem.
If ``retry-on-startup`` is set to ``true``, the server will start reconnection
attempts even at server startup or on reconfigure events, and will honor the
action specified in ``on-fail`` parameter.
The host parameter is used by the MySQL and PostgreSQL backends. The host parameter is used by the MySQL and PostgreSQL backends.
Finally, the credentials of the account under which the server will Finally, the credentials of the account under which the server will
@ -754,6 +767,19 @@ The possible values are:
the lease database backend and the hosts database backend are connected to the lease database backend and the hosts database backend are connected to
the same database instance. the same database instance.
::
"Dhcp6": { "hosts-database": { "retry-on-startup" : true, ... }, ... }
During server startup, the inability to connect to any of the configured
backends is considered fatal only if ``retry-on-startup`` is set to ``false``.
A fatal error is logged and the server exits, based on the idea that the
configuration should be valid at startup. Exiting to the operating system allows
nanny scripts to detect the problem.
If ``retry-on-startup`` is set to ``true``, the server will start reconnection
attempts even at server startup or on reconfigure events, and will honor the
action specified in ``on-fail`` parameter.
Finally, the credentials of the account under which the server will Finally, the credentials of the account under which the server will
access the database should be set: access the database should be set:

View File

@ -1083,3 +1083,12 @@ If ``on-fail`` is set to ``serve-retry-exit``, the server will shut down if
the connection to the database backend is not restored according to the the connection to the database backend is not restored according to the
``max-reconnect-tries`` and ``reconnect-wait-time`` parameters, but it ``max-reconnect-tries`` and ``reconnect-wait-time`` parameters, but it
continues serving clients while this mechanism is activated. continues serving clients while this mechanism is activated.
During server startup, the inability to connect to any of the configured
backends is considered fatal only if ``retry-on-startup`` is set to ``false``.
A fatal error is logged and the server exits, based on the idea that the
configuration should be valid at startup. Exiting to the operating system allows
nanny scripts to detect the problem.
If ``retry-on-startup`` is set to ``true``, the server will start reconnection
attempts even at server startup or on reconfigure events, and will honor the
action specified in ``on-fail`` parameter.

View File

@ -911,6 +911,10 @@ isc::data::ConstElementPtr
ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) { ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance(); ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
// Allow DB reconnect on startup. The database connection parameters specify
// respective details.
DbConnectionInitWithRetry retry;
// Single stream instance used in all error clauses // Single stream instance used in all error clauses
std::ostringstream err; std::ostringstream err;
@ -1155,11 +1159,8 @@ ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t server_port /*= DHCP4_SERVER_P
// CommandMgr uses IO service to run asynchronous socket operations. // CommandMgr uses IO service to run asynchronous socket operations.
CommandMgr::instance().setIOService(getIOService()); CommandMgr::instance().setIOService(getIOService());
// LeaseMgr uses IO service to run asynchronous timers. // DatabaseConnection uses IO service to run asynchronous timers.
LeaseMgr::setIOService(getIOService()); DatabaseConnection::setIOService(getIOService());
// HostMgr uses IO service to run asynchronous timers.
HostMgr::setIOService(getIOService());
// These are the commands always supported by the DHCPv4 server. // These are the commands always supported by the DHCPv4 server.
// Please keep the list in alphabetic order. // Please keep the list in alphabetic order.
@ -1295,11 +1296,8 @@ ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
CommandMgr::instance().deregisterCommand("status-get"); CommandMgr::instance().deregisterCommand("status-get");
CommandMgr::instance().deregisterCommand("version-get"); CommandMgr::instance().deregisterCommand("version-get");
// LeaseMgr uses IO service to run asynchronous timers. // Reset DatabaseConnection IO service.
LeaseMgr::setIOService(IOServicePtr()); DatabaseConnection::setIOService(IOServicePtr());
// HostMgr uses IO service to run asynchronous timers.
HostMgr::setIOService(IOServicePtr());
} catch (...) { } catch (...) {
// Don't want to throw exceptions from the destructor. The server // Don't want to throw exceptions from the destructor. The server
// is shutting down anyway. // is shutting down anyway.

View File

@ -593,6 +593,17 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
} }
} }
\"retry-on-startup\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::LEASE_DATABASE:
case isc::dhcp::Parser4Context::HOSTS_DATABASE:
case isc::dhcp::Parser4Context::CONFIG_DATABASE:
return isc::dhcp::Dhcp4Parser::make_RETRY_ON_STARTUP(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("retry-on-startup", driver.loc_);
}
}
\"max-reconnect-tries\" { \"max-reconnect-tries\" {
switch(driver.ctx_) { switch(driver.ctx_) {
case isc::dhcp::Parser4Context::LEASE_DATABASE: case isc::dhcp::Parser4Context::LEASE_DATABASE:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -109,6 +109,7 @@ using namespace std;
STOP_RETRY_EXIT "stop-retry-exit" STOP_RETRY_EXIT "stop-retry-exit"
SERVE_RETRY_EXIT "serve-retry-exit" SERVE_RETRY_EXIT "serve-retry-exit"
SERVE_RETRY_CONTINUE "serve-retry-continue" SERVE_RETRY_CONTINUE "serve-retry-continue"
RETRY_ON_STARTUP "retry-on-startup"
MAX_ROW_ERRORS "max-row-errors" MAX_ROW_ERRORS "max-row-errors"
TRUST_ANCHOR "trust-anchor" TRUST_ANCHOR "trust-anchor"
CERT_FILE "cert-file" CERT_FILE "cert-file"
@ -1093,6 +1094,7 @@ database_map_param: database_type
| max_reconnect_tries | max_reconnect_tries
| reconnect_wait_time | reconnect_wait_time
| on_fail | on_fail
| retry_on_startup
| max_row_errors | max_row_errors
| trust_anchor | trust_anchor
| cert_file | cert_file
@ -1223,6 +1225,12 @@ on_fail_mode: STOP_RETRY_EXIT { $$ = ElementPtr(new StringElement("stop-retry-ex
| SERVE_RETRY_CONTINUE { $$ = ElementPtr(new StringElement("serve-retry-continue", ctx.loc2pos(@1))); } | SERVE_RETRY_CONTINUE { $$ = ElementPtr(new StringElement("serve-retry-continue", ctx.loc2pos(@1))); }
; ;
retry_on_startup: RETRY_ON_STARTUP COLON BOOLEAN {
ctx.unique("retry-on-startup", ctx.loc2pos(@1));
ElementPtr n(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("retry-on-startup", n);
};
max_row_errors: MAX_ROW_ERRORS COLON INTEGER { max_row_errors: MAX_ROW_ERRORS COLON INTEGER {
ctx.unique("max-row-errors", ctx.loc2pos(@1)); ctx.unique("max-row-errors", ctx.loc2pos(@1));
ElementPtr n(new IntElement($3, ctx.loc2pos(@3))); ElementPtr n(new IntElement($3, ctx.loc2pos(@3)));

View File

@ -53,15 +53,16 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <dirent.h> #include <dirent.h>
using namespace std;
using namespace isc; using namespace isc;
using namespace isc::dhcp;
using namespace isc::data;
using namespace isc::asiolink; using namespace isc::asiolink;
using namespace isc::cb; using namespace isc::cb;
using namespace isc::config; using namespace isc::config;
using namespace isc::data;
using namespace isc::db;
using namespace isc::dhcp;
using namespace isc::dhcp::test; using namespace isc::dhcp::test;
using namespace isc::util; using namespace isc::util;
using namespace std;
namespace { namespace {
@ -2879,11 +2880,8 @@ Dhcpv4SrvTest::loadConfigFile(const string& path) {
// CommandMgr uses IO service to run asynchronous socket operations. // CommandMgr uses IO service to run asynchronous socket operations.
CommandMgr::instance().setIOService(srv.getIOService()); CommandMgr::instance().setIOService(srv.getIOService());
// LeaseMgr uses IO service to run asynchronous timers. // DatabaseConnection uses IO service to run asynchronous timers.
LeaseMgr::setIOService(srv.getIOService()); DatabaseConnection::setIOService(srv.getIOService());
// HostMgr uses IO service to run asynchronous timers.
HostMgr::setIOService(srv.getIOService());
Parser4Context parser; Parser4Context parser;
ConstElementPtr json; ConstElementPtr json;
@ -2917,11 +2915,8 @@ Dhcpv4SrvTest::loadConfigFile(const string& path) {
// Reset CommandMgr IO service. // Reset CommandMgr IO service.
CommandMgr::instance().setIOService(IOServicePtr()); CommandMgr::instance().setIOService(IOServicePtr());
// Reset LeaseMgr IO service. // Reset DatabaseConnection IO service.
LeaseMgr::setIOService(IOServicePtr()); DatabaseConnection::setIOService(IOServicePtr());
// Reset HostMgr IO service.
HostMgr::setIOService(IOServicePtr());
} }
/// @brief Class which handles initialization of database /// @brief Class which handles initialization of database

View File

@ -125,7 +125,7 @@ public:
// Create fixed server id. // Create fixed server id.
server_id_.reset(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER, server_id_.reset(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER,
asiolink::IOAddress("192.0.3.1"))); asiolink::IOAddress("192.0.3.1")));
LeaseMgr::setIOService(getIOService()); db::DatabaseConnection::setIOService(getIOService());
} }
/// @brief Returns fixed server identifier assigned to the naked server /// @brief Returns fixed server identifier assigned to the naked server

View File

@ -916,6 +916,10 @@ isc::data::ConstElementPtr
ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) { ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance(); ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance();
// Allow DB reconnect on startup. The database connection parameters specify
// respective details.
DbConnectionInitWithRetry retry;
// Single stream instance used in all error clauses // Single stream instance used in all error clauses
std::ostringstream err; std::ostringstream err;
@ -1174,11 +1178,8 @@ ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t server_port /*= DHCP6_SERVER_P
// CommandMgr uses IO service to run asynchronous socket operations. // CommandMgr uses IO service to run asynchronous socket operations.
CommandMgr::instance().setIOService(getIOService()); CommandMgr::instance().setIOService(getIOService());
// LeaseMgr uses IO service to run asynchronous timers. // DatabaseConnection uses IO service to run asynchronous timers.
LeaseMgr::setIOService(getIOService()); DatabaseConnection::setIOService(getIOService());
// HostMgr uses IO service to run asynchronous timers.
HostMgr::setIOService(getIOService());
// These are the commands always supported by the DHCPv6 server. // These are the commands always supported by the DHCPv6 server.
// Please keep the list in alphabetic order. // Please keep the list in alphabetic order.
@ -1314,11 +1315,8 @@ ControlledDhcpv6Srv::~ControlledDhcpv6Srv() {
CommandMgr::instance().deregisterCommand("status-get"); CommandMgr::instance().deregisterCommand("status-get");
CommandMgr::instance().deregisterCommand("version-get"); CommandMgr::instance().deregisterCommand("version-get");
// LeaseMgr uses IO service to run asynchronous timers. // Reset DatabaseConnection IO service.
LeaseMgr::setIOService(IOServicePtr()); DatabaseConnection::setIOService(IOServicePtr());
// HostMgr uses IO service to run asynchronous timers.
HostMgr::setIOService(IOServicePtr());
} catch (...) { } catch (...) {
// Don't want to throw exceptions from the destructor. The server // Don't want to throw exceptions from the destructor. The server
// is shutting down anyway. // is shutting down anyway.

File diff suppressed because it is too large Load Diff

View File

@ -791,6 +791,17 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
} }
} }
\"retry-on-startup\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::LEASE_DATABASE:
case isc::dhcp::Parser6Context::HOSTS_DATABASE:
case isc::dhcp::Parser6Context::CONFIG_DATABASE:
return isc::dhcp::Dhcp6Parser::make_RETRY_ON_STARTUP(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("retry-on-startup", driver.loc_);
}
}
\"max-reconnect-tries\" { \"max-reconnect-tries\" {
switch(driver.ctx_) { switch(driver.ctx_) {
case isc::dhcp::Parser6Context::LEASE_DATABASE: case isc::dhcp::Parser6Context::LEASE_DATABASE:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -92,6 +92,7 @@ using namespace std;
STOP_RETRY_EXIT "stop-retry-exit" STOP_RETRY_EXIT "stop-retry-exit"
SERVE_RETRY_EXIT "serve-retry-exit" SERVE_RETRY_EXIT "serve-retry-exit"
SERVE_RETRY_CONTINUE "serve-retry-continue" SERVE_RETRY_CONTINUE "serve-retry-continue"
RETRY_ON_STARTUP "retry-on-startup"
MAX_ROW_ERRORS "max-row-errors" MAX_ROW_ERRORS "max-row-errors"
TRUST_ANCHOR "trust-anchor" TRUST_ANCHOR "trust-anchor"
CERT_FILE "cert-file" CERT_FILE "cert-file"
@ -1024,6 +1025,7 @@ database_map_param: database_type
| max_reconnect_tries | max_reconnect_tries
| reconnect_wait_time | reconnect_wait_time
| on_fail | on_fail
| retry_on_startup
| max_row_errors | max_row_errors
| trust_anchor | trust_anchor
| cert_file | cert_file
@ -1149,6 +1151,12 @@ on_fail_mode: STOP_RETRY_EXIT { $$ = ElementPtr(new StringElement("stop-retry-ex
| SERVE_RETRY_CONTINUE { $$ = ElementPtr(new StringElement("serve-retry-continue", ctx.loc2pos(@1))); } | SERVE_RETRY_CONTINUE { $$ = ElementPtr(new StringElement("serve-retry-continue", ctx.loc2pos(@1))); }
; ;
retry_on_startup: RETRY_ON_STARTUP COLON BOOLEAN {
ctx.unique("retry-on-startup", ctx.loc2pos(@1));
ElementPtr n(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("retry-on-startup", n);
};
max_row_errors: MAX_ROW_ERRORS COLON INTEGER { max_row_errors: MAX_ROW_ERRORS COLON INTEGER {
ctx.unique("max-row-errors", ctx.loc2pos(@1)); ctx.unique("max-row-errors", ctx.loc2pos(@1));
ElementPtr n(new IntElement($3, ctx.loc2pos(@3))); ElementPtr n(new IntElement($3, ctx.loc2pos(@3)));

View File

@ -60,6 +60,7 @@ using namespace isc::asiolink;
using namespace isc::cb; using namespace isc::cb;
using namespace isc::config; using namespace isc::config;
using namespace isc::data; using namespace isc::data;
using namespace isc::db;
using namespace isc::dhcp; using namespace isc::dhcp;
using namespace isc::dhcp::test; using namespace isc::dhcp::test;
using namespace isc::util; using namespace isc::util;
@ -248,11 +249,8 @@ Dhcpv6SrvTest::loadConfigFile(const string& path) {
// CommandMgr uses IO service to run asynchronous socket operations. // CommandMgr uses IO service to run asynchronous socket operations.
CommandMgr::instance().setIOService(srv.getIOService()); CommandMgr::instance().setIOService(srv.getIOService());
// LeaseMgr uses IO service to run asynchronous timers. // DatabaseConnection uses IO service to run asynchronous timers.
LeaseMgr::setIOService(srv.getIOService()); DatabaseConnection::setIOService(srv.getIOService());
// HostMgr uses IO service to run asynchronous timers.
HostMgr::setIOService(srv.getIOService());
Parser6Context parser; Parser6Context parser;
ConstElementPtr json; ConstElementPtr json;
@ -286,11 +284,8 @@ Dhcpv6SrvTest::loadConfigFile(const string& path) {
// Reset CommandMgr IO service. // Reset CommandMgr IO service.
CommandMgr::instance().setIOService(IOServicePtr()); CommandMgr::instance().setIOService(IOServicePtr());
// Reset LeaseMgr IO service. // Reset DatabaseConnection IO service.
LeaseMgr::setIOService(IOServicePtr()); DatabaseConnection::setIOService(IOServicePtr());
// Reset HostMgr IO service.
HostMgr::setIOService(IOServicePtr());
} }
/// @brief Class which handles initialization of database /// @brief Class which handles initialization of database

View File

@ -135,7 +135,7 @@ public:
// Open the "memfile" database for leases // Open the "memfile" database for leases
std::string memfile = "type=memfile universe=6 persist=false"; std::string memfile = "type=memfile universe=6 persist=false";
isc::dhcp::LeaseMgrFactory::create(memfile); isc::dhcp::LeaseMgrFactory::create(memfile);
LeaseMgr::setIOService(getIOService()); db::DatabaseConnection::setIOService(getIOService());
} }
/// @brief fakes packet reception /// @brief fakes packet reception

View File

@ -27,6 +27,7 @@
#include <dhcpsrv/parsers/client_class_def_parser.h> #include <dhcpsrv/parsers/client_class_def_parser.h>
#include <util/buffer.h> #include <util/buffer.h>
#include <util/boost_time_utils.h> #include <util/boost_time_utils.h>
#include <util/dhcp_space.h>
#include <util/multi_threading_mgr.h> #include <util/multi_threading_mgr.h>
#include <mysql/mysql_connection.h> #include <mysql/mysql_connection.h>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
@ -3687,7 +3688,8 @@ TaggedStatementArray tagged_statements = { {
} // end anonymous namespace } // end anonymous namespace
MySqlConfigBackendDHCPv4Impl::MySqlConfigBackendDHCPv4Impl(const DatabaseConnection::ParameterMap& parameters) MySqlConfigBackendDHCPv4Impl::MySqlConfigBackendDHCPv4Impl(const DatabaseConnection::ParameterMap& parameters)
: MySqlConfigBackendImpl(parameters, &MySqlConfigBackendDHCPv4Impl::dbReconnect) { : MySqlConfigBackendImpl(std::string(cStringDhcpSpace<DHCPv4>()), parameters,
&MySqlConfigBackendDHCPv4Impl::dbReconnect) {
// Prepare query statements. Those are will be only used to retrieve // Prepare query statements. Those are will be only used to retrieve
// information from the database, so they can be used even if the // information from the database, so they can be used even if the
// database is read only for the current user. // database is read only for the current user.
@ -3696,14 +3698,6 @@ MySqlConfigBackendDHCPv4Impl::MySqlConfigBackendDHCPv4Impl(const DatabaseConnect
// @todo As part of enabling read-only CB access, statements need to // @todo As part of enabling read-only CB access, statements need to
// be limited: // be limited:
// tagged_statements.begin() + WRITE_STMTS_BEGIN); // tagged_statements.begin() + WRITE_STMTS_BEGIN);
// Create unique timer name per instance.
timer_name_ = "MySqlConfigBackend4[";
timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
timer_name_ += "]DbReconnectTimer";
// Create ReconnectCtl for this connection.
conn_.makeReconnectCtl(timer_name_);
} }
MySqlConfigBackendDHCPv4Impl::~MySqlConfigBackendDHCPv4Impl() { MySqlConfigBackendDHCPv4Impl::~MySqlConfigBackendDHCPv4Impl() {

View File

@ -28,6 +28,7 @@
#include <dhcpsrv/parsers/client_class_def_parser.h> #include <dhcpsrv/parsers/client_class_def_parser.h>
#include <util/buffer.h> #include <util/buffer.h>
#include <util/boost_time_utils.h> #include <util/boost_time_utils.h>
#include <util/dhcp_space.h>
#include <util/multi_threading_mgr.h> #include <util/multi_threading_mgr.h>
#include <util/triplet.h> #include <util/triplet.h>
#include <mysql/mysql_connection.h> #include <mysql/mysql_connection.h>
@ -4143,7 +4144,8 @@ TaggedStatementArray tagged_statements = { {
} // end anonymous namespace } // end anonymous namespace
MySqlConfigBackendDHCPv6Impl::MySqlConfigBackendDHCPv6Impl(const DatabaseConnection::ParameterMap& parameters) MySqlConfigBackendDHCPv6Impl::MySqlConfigBackendDHCPv6Impl(const DatabaseConnection::ParameterMap& parameters)
: MySqlConfigBackendImpl(parameters, &MySqlConfigBackendDHCPv6Impl::dbReconnect) { : MySqlConfigBackendImpl(std::string(cStringDhcpSpace<DHCPv6>()), parameters,
&MySqlConfigBackendDHCPv6Impl::dbReconnect) {
// Prepare query statements. Those are will be only used to retrieve // Prepare query statements. Those are will be only used to retrieve
// information from the database, so they can be used even if the // information from the database, so they can be used even if the
// database is read only for the current user. // database is read only for the current user.
@ -4152,14 +4154,6 @@ MySqlConfigBackendDHCPv6Impl::MySqlConfigBackendDHCPv6Impl(const DatabaseConnect
// @todo As part of enabling read-only CB access, statements need to // @todo As part of enabling read-only CB access, statements need to
// be limited: // be limited:
// tagged_statements.begin() + WRITE_STMTS_BEGIN); // tagged_statements.begin() + WRITE_STMTS_BEGIN);
// Create unique timer name per instance.
timer_name_ = "MySqlConfigBackend6[";
timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
timer_name_ += "]DbReconnectTimer";
// Create ReconnectCtl for this connection.
conn_.makeReconnectCtl(timer_name_);
} }
MySqlConfigBackendDHCPv6Impl::~MySqlConfigBackendDHCPv6Impl() { MySqlConfigBackendDHCPv6Impl::~MySqlConfigBackendDHCPv6Impl() {

View File

@ -5,11 +5,13 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h> #include <config.h>
#include <mysql_cb_impl.h> #include <mysql_cb_impl.h>
#include <mysql_cb_log.h> #include <mysql_cb_log.h>
#include <asiolink/io_address.h> #include <asiolink/io_address.h>
#include <config_backend/constants.h> #include <config_backend/constants.h>
#include <dhcp/option_space.h> #include <dhcp/option_space.h>
#include <dhcpsrv/timer_mgr.h>
#include <util/buffer.h> #include <util/buffer.h>
#include <mysql.h> #include <mysql.h>
@ -48,17 +50,43 @@ ScopedAuditRevision::~ScopedAuditRevision() {
} }
MySqlConfigBackendImpl:: MySqlConfigBackendImpl::
MySqlConfigBackendImpl(const DatabaseConnection::ParameterMap& parameters, MySqlConfigBackendImpl(const std::string& space,
const DatabaseConnection::ParameterMap& parameters,
const DbCallback db_reconnect_callback) const DbCallback db_reconnect_callback)
: conn_(parameters, : conn_(parameters,
IOServiceAccessorPtr(new IOServiceAccessor(MySqlConfigBackendImpl::getIOService)), IOServiceAccessorPtr(new IOServiceAccessor(&MySqlConfigBackendImpl::getIOService)),
db_reconnect_callback), timer_name_(""), db_reconnect_callback), timer_name_(""),
audit_revision_ref_count_(0), parameters_(parameters) { audit_revision_ref_count_(0), parameters_(parameters) {
// Create unique timer name per instance.
timer_name_ = "MySqlConfigBackend";
timer_name_ += space;
timer_name_ += "[";
timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
timer_name_ += "]DbReconnectTimer";
// Create ReconnectCtl for this connection.
conn_.makeReconnectCtl(timer_name_);
// Test schema version first. // Test schema version first.
std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR,
MYSQL_SCHEMA_VERSION_MINOR); MYSQL_SCHEMA_VERSION_MINOR);
std::string timer_name = "";
bool retry = false;
if (parameters.count("retry-on-startup")) {
if (parameters.at("retry-on-startup") == "true") {
retry = true;
}
}
if (retry) {
timer_name = timer_name_;
}
IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
std::pair<uint32_t, uint32_t> db_version = std::pair<uint32_t, uint32_t> db_version =
MySqlConnection::getVersion(parameters); MySqlConnection::getVersion(parameters, ac, db_reconnect_callback, timer_name);
if (code_version != db_version) { if (code_version != db_version) {
isc_throw(DbOpenError, "MySQL schema version mismatch: need version: " isc_throw(DbOpenError, "MySQL schema version mismatch: need version: "
<< code_version.first << "." << code_version.second << code_version.first << "." << code_version.second
@ -829,7 +857,6 @@ MySqlConfigBackendImpl::processOptionRow(const Option::Universe& universe,
code = (*(first_binding + 1))->getInteger<uint16_t>(); code = (*(first_binding + 1))->getInteger<uint16_t>();
} }
// Get formatted value if available. // Get formatted value if available.
std::string formatted_value = (*(first_binding + 3))->getStringOrDefault(""); std::string formatted_value = (*(first_binding + 3))->getStringOrDefault("");

View File

@ -106,10 +106,12 @@ public:
/// @brief Constructor. /// @brief Constructor.
/// ///
/// @param space The DHCP space (v4 or v6).
/// @param parameters A data structure relating keywords and values /// @param parameters A data structure relating keywords and values
/// concerned with the database. /// concerned with the database.
/// @param db_reconnect_callback The connection recovery callback. /// @param db_reconnect_callback The connection recovery callback.
explicit MySqlConfigBackendImpl(const db::DatabaseConnection::ParameterMap& parameters, explicit MySqlConfigBackendImpl(const std::string& space,
const db::DatabaseConnection::ParameterMap& parameters,
const db::DbCallback db_reconnect_callback); const db::DbCallback db_reconnect_callback);
/// @brief Destructor. /// @brief Destructor.

View File

@ -462,6 +462,46 @@ public:
} }
}; };
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredCallback();
}
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredCallback();
}
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndFailedCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedCallback();
}
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndFailedCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedCallback();
}
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testNoCallbackOnOpenFailure) { TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testNoCallbackOnOpenFailure) {
MultiThreadingTest mt(false); MultiThreadingTest mt(false);
testNoCallbackOnOpenFailure(); testNoCallbackOnOpenFailure();

View File

@ -466,6 +466,46 @@ public:
} }
}; };
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredCallback();
}
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredCallback();
}
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndFailedCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedCallback();
}
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndFailedCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedCallback();
}
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testNoCallbackOnOpenFailure) { TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testNoCallbackOnOpenFailure) {
MultiThreadingTest mt(false); MultiThreadingTest mt(false);
testNoCallbackOnOpenFailure(); testNoCallbackOnOpenFailure();

View File

@ -27,6 +27,7 @@
#include <dhcpsrv/parsers/client_class_def_parser.h> #include <dhcpsrv/parsers/client_class_def_parser.h>
#include <util/buffer.h> #include <util/buffer.h>
#include <util/boost_time_utils.h> #include <util/boost_time_utils.h>
#include <util/dhcp_space.h>
#include <util/multi_threading_mgr.h> #include <util/multi_threading_mgr.h>
#include <pgsql/pgsql_connection.h> #include <pgsql/pgsql_connection.h>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
@ -4555,7 +4556,8 @@ TaggedStatementArray tagged_statements = { {
} // end anonymous namespace } // end anonymous namespace
PgSqlConfigBackendDHCPv4Impl::PgSqlConfigBackendDHCPv4Impl(const DatabaseConnection::ParameterMap& parameters) PgSqlConfigBackendDHCPv4Impl::PgSqlConfigBackendDHCPv4Impl(const DatabaseConnection::ParameterMap& parameters)
: PgSqlConfigBackendImpl(parameters, &PgSqlConfigBackendDHCPv4Impl::dbReconnect, : PgSqlConfigBackendImpl(std::string(cStringDhcpSpace<DHCPv4>()), parameters,
&PgSqlConfigBackendDHCPv4Impl::dbReconnect,
PgSqlConfigBackendDHCPv4Impl::GET_LAST_INSERT_ID4) { PgSqlConfigBackendDHCPv4Impl::GET_LAST_INSERT_ID4) {
// Prepare query statements. Those are will be only used to retrieve // Prepare query statements. Those are will be only used to retrieve
// information from the database, so they can be used even if the // information from the database, so they can be used even if the
@ -4565,14 +4567,6 @@ PgSqlConfigBackendDHCPv4Impl::PgSqlConfigBackendDHCPv4Impl(const DatabaseConnect
// @todo As part of enabling read-only CB access, statements need to // @todo As part of enabling read-only CB access, statements need to
// be limited: // be limited:
// tagged_statements.begin() + WRITE_STMTS_BEGIN); // tagged_statements.begin() + WRITE_STMTS_BEGIN);
// Create unique timer name per instance.
timer_name_ = "PgSqlConfigBackend4[";
timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
timer_name_ += "]DbReconnectTimer";
// Create ReconnectCtl for this connection.
conn_.makeReconnectCtl(timer_name_);
} }
PgSqlConfigBackendDHCPv4Impl::~PgSqlConfigBackendDHCPv4Impl() { PgSqlConfigBackendDHCPv4Impl::~PgSqlConfigBackendDHCPv4Impl() {

View File

@ -28,6 +28,7 @@
#include <dhcpsrv/parsers/client_class_def_parser.h> #include <dhcpsrv/parsers/client_class_def_parser.h>
#include <util/buffer.h> #include <util/buffer.h>
#include <util/boost_time_utils.h> #include <util/boost_time_utils.h>
#include <util/dhcp_space.h>
#include <util/multi_threading_mgr.h> #include <util/multi_threading_mgr.h>
#include <util/triplet.h> #include <util/triplet.h>
#include <pgsql/pgsql_connection.h> #include <pgsql/pgsql_connection.h>
@ -5016,7 +5017,8 @@ TaggedStatementArray tagged_statements = { {
} // end anonymous namespace } // end anonymous namespace
PgSqlConfigBackendDHCPv6Impl::PgSqlConfigBackendDHCPv6Impl(const DatabaseConnection::ParameterMap& parameters) PgSqlConfigBackendDHCPv6Impl::PgSqlConfigBackendDHCPv6Impl(const DatabaseConnection::ParameterMap& parameters)
: PgSqlConfigBackendImpl(parameters, &PgSqlConfigBackendDHCPv6Impl::dbReconnect, : PgSqlConfigBackendImpl(std::string(cStringDhcpSpace<DHCPv6>()), parameters,
&PgSqlConfigBackendDHCPv6Impl::dbReconnect,
PgSqlConfigBackendDHCPv6Impl::GET_LAST_INSERT_ID6) { PgSqlConfigBackendDHCPv6Impl::GET_LAST_INSERT_ID6) {
// Prepare query statements. Those are will be only used to retrieve // Prepare query statements. Those are will be only used to retrieve
// information from the database, so they can be used even if the // information from the database, so they can be used even if the
@ -5026,14 +5028,6 @@ PgSqlConfigBackendDHCPv6Impl::PgSqlConfigBackendDHCPv6Impl(const DatabaseConnect
// @todo As part of enabling read-only CB access, statements need to // @todo As part of enabling read-only CB access, statements need to
// be limited: // be limited:
// tagged_statements.begin() + WRITE_STMTS_BEGIN); // tagged_statements.begin() + WRITE_STMTS_BEGIN);
// Create unique timer name per instance.
timer_name_ = "PgSqlConfigBackend6[";
timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
timer_name_ += "]DbReconnectTimer";
// Create ReconnectCtl for this connection.
conn_.makeReconnectCtl(timer_name_);
} }
PgSqlConfigBackendDHCPv6Impl::~PgSqlConfigBackendDHCPv6Impl() { PgSqlConfigBackendDHCPv6Impl::~PgSqlConfigBackendDHCPv6Impl() {

View File

@ -8,8 +8,9 @@
#include <asiolink/io_address.h> #include <asiolink/io_address.h>
#include <config_backend/constants.h> #include <config_backend/constants.h>
#include <dhcp/option_space.h>
#include <database/db_exceptions.h> #include <database/db_exceptions.h>
#include <dhcp/option_space.h>
#include <dhcpsrv/timer_mgr.h>
#include <pgsql/pgsql_exchange.h> #include <pgsql/pgsql_exchange.h>
#include <util/buffer.h> #include <util/buffer.h>
@ -70,15 +71,26 @@ PgSqlConfigBackendImpl::ScopedAuditRevision::~ScopedAuditRevision() {
impl_->clearAuditRevision(); impl_->clearAuditRevision();
} }
PgSqlConfigBackendImpl::PgSqlConfigBackendImpl(const DatabaseConnection::ParameterMap& parameters, PgSqlConfigBackendImpl::PgSqlConfigBackendImpl(const std::string& space,
const DatabaseConnection::ParameterMap& parameters,
const DbCallback db_reconnect_callback, const DbCallback db_reconnect_callback,
size_t last_insert_id_index) size_t last_insert_id_index)
: conn_(parameters, : conn_(parameters,
IOServiceAccessorPtr(new IOServiceAccessor(PgSqlConfigBackendImpl::getIOService)), IOServiceAccessorPtr(new IOServiceAccessor(&PgSqlConfigBackendImpl::getIOService)),
db_reconnect_callback), timer_name_(""), db_reconnect_callback), timer_name_(""),
audit_revision_ref_count_(0), parameters_(parameters), audit_revision_ref_count_(0), parameters_(parameters),
last_insert_id_index_(last_insert_id_index) { last_insert_id_index_(last_insert_id_index) {
// Create unique timer name per instance.
timer_name_ = "PgSqlConfigBackend";
timer_name_ += space;
timer_name_ += "[";
timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
timer_name_ += "]DbReconnectTimer";
// Create ReconnectCtl for this connection.
conn_.makeReconnectCtl(timer_name_);
// Check TLS support. // Check TLS support.
size_t tls(0); size_t tls(0);
tls += parameters.count("trust-anchor"); tls += parameters.count("trust-anchor");
@ -102,8 +114,24 @@ PgSqlConfigBackendImpl::PgSqlConfigBackendImpl(const DatabaseConnection::Paramet
#endif #endif
// Test schema version first. // Test schema version first.
std::pair<uint32_t, uint32_t> code_version(PGSQL_SCHEMA_VERSION_MAJOR, PGSQL_SCHEMA_VERSION_MINOR); std::pair<uint32_t, uint32_t> code_version(PGSQL_SCHEMA_VERSION_MAJOR,
std::pair<uint32_t, uint32_t> db_version = PgSqlConnection::getVersion(parameters); PGSQL_SCHEMA_VERSION_MINOR);
std::string timer_name = "";
bool retry = false;
if (parameters.count("retry-on-startup")) {
if (parameters.at("retry-on-startup") == "true") {
retry = true;
}
}
if (retry) {
timer_name = timer_name_;
}
IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
std::pair<uint32_t, uint32_t> db_version =
PgSqlConnection::getVersion(parameters, ac, db_reconnect_callback, timer_name);
if (code_version != db_version) { if (code_version != db_version) {
isc_throw(DbOpenError, "PostgreSQL schema version mismatch: need version: " isc_throw(DbOpenError, "PostgreSQL schema version mismatch: need version: "
<< code_version.first << "." << code_version.second << code_version.first << "." << code_version.second

View File

@ -106,12 +106,14 @@ public:
/// @brief Constructor. /// @brief Constructor.
/// ///
/// @param space The DHCP space (v4 or v6).
/// @param parameters A data structure relating keywords and values /// @param parameters A data structure relating keywords and values
/// concerned with the database. /// concerned with the database.
/// @param db_reconnect_callback The connection recovery callback. /// @param db_reconnect_callback The connection recovery callback.
/// @param last_insert_id_index statement index of the SQL statement to /// @param last_insert_id_index statement index of the SQL statement to
/// use when fetching the last insert id for a given table. /// use when fetching the last insert id for a given table.
explicit PgSqlConfigBackendImpl(const db::DatabaseConnection::ParameterMap& parameters, explicit PgSqlConfigBackendImpl(const std::string& space,
const db::DatabaseConnection::ParameterMap& parameters,
const db::DbCallback db_reconnect_callback, const db::DbCallback db_reconnect_callback,
const size_t last_insert_id_index); const size_t last_insert_id_index);

View File

@ -460,6 +460,46 @@ public:
} }
}; };
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredCallback();
}
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredCallback();
}
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndFailedCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedCallback();
}
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndFailedCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedCallback();
}
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testNoCallbackOnOpenFailure) { TEST_F(PgSqlConfigBackendDHCPv4DbLostCallbackTest, testNoCallbackOnOpenFailure) {
MultiThreadingTest mt(false); MultiThreadingTest mt(false);
testNoCallbackOnOpenFailure(); testNoCallbackOnOpenFailure();

View File

@ -464,6 +464,46 @@ public:
} }
}; };
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredCallback();
}
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredCallback();
}
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndFailedCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedCallback();
}
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndFailedCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedCallback();
}
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testNoCallbackOnOpenFailure) { TEST_F(PgSqlConfigBackendDHCPv6DbLostCallbackTest, testNoCallbackOnOpenFailure) {
MultiThreadingTest mt(false); MultiThreadingTest mt(false);
testNoCallbackOnOpenFailure(); testNoCallbackOnOpenFailure();

View File

@ -35,7 +35,7 @@ public:
params["name"] = "keatest"; params["name"] = "keatest";
params["password"] = "keatest"; params["password"] = "keatest";
params["user"] = "keatest"; params["user"] = "keatest";
ASSERT_NO_THROW_LOG(cbptr_.reset(new PgSqlConfigBackendImpl(params, 0, 0))); ASSERT_NO_THROW_LOG(cbptr_.reset(new PgSqlConfigBackendImpl("", params, 0, 0)));
} }
/// @brief Cleans up after each test. /// @brief Cleans up after each test.

View File

@ -18,6 +18,7 @@
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <vector> #include <vector>
using namespace isc::asiolink;
using namespace isc::util; using namespace isc::util;
using namespace std; using namespace std;
@ -257,6 +258,7 @@ DatabaseConnection::toElement(const ParameterMap& params) {
(keyword == "host") || (keyword == "host") ||
(keyword == "name") || (keyword == "name") ||
(keyword == "on-fail") || (keyword == "on-fail") ||
(keyword == "retry-on-startup") ||
(keyword == "trust-anchor") || (keyword == "trust-anchor") ||
(keyword == "cert-file") || (keyword == "cert-file") ||
(keyword == "key-file") || (keyword == "key-file") ||
@ -280,6 +282,8 @@ DatabaseConnection::toElementDbAccessString(const std::string& dbaccess) {
DbCallback DatabaseConnection::db_lost_callback_ = 0; DbCallback DatabaseConnection::db_lost_callback_ = 0;
DbCallback DatabaseConnection::db_recovered_callback_ = 0; DbCallback DatabaseConnection::db_recovered_callback_ = 0;
DbCallback DatabaseConnection::db_failed_callback_ = 0; DbCallback DatabaseConnection::db_failed_callback_ = 0;
bool DatabaseConnection::retry_ = false;
IOServicePtr DatabaseConnection::io_service_ = IOServicePtr();
} // namespace db } // namespace db
} // namespace isc } // namespace isc

View File

@ -34,6 +34,13 @@ public:
isc::Exception(file, line, what) {} isc::Exception(file, line, what) {}
}; };
/// @brief Exception thrown on failure to open database but permit retries
class DbOpenErrorWithRetry : public Exception {
public:
DbOpenErrorWithRetry(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Exception thrown on failure to execute a database function /// @brief Exception thrown on failure to execute a database function
class DbOperationError : public Exception { class DbOperationError : public Exception {
public: public:
@ -215,6 +222,18 @@ public:
/// @return a pointer to configuration /// @return a pointer to configuration
static isc::data::ElementPtr toElementDbAccessString(const std::string& dbaccess); static isc::data::ElementPtr toElementDbAccessString(const std::string& dbaccess);
/// @brief Sets IO service to be used by the Lease Manager.
///
/// @param io_service IOService object, used for all ASIO operations.
static void setIOService(const isc::asiolink::IOServicePtr& io_service) {
io_service_ = io_service;
}
/// @brief Returns pointer to the IO service.
static isc::asiolink::IOServicePtr& getIOService() {
return (io_service_);
}
/// @brief Optional callback function to invoke if an opened connection is /// @brief Optional callback function to invoke if an opened connection is
/// lost /// lost
static DbCallback db_lost_callback_; static DbCallback db_lost_callback_;
@ -227,6 +246,14 @@ public:
/// recovery failed /// recovery failed
static DbCallback db_failed_callback_; static DbCallback db_failed_callback_;
/// @brief Flag which indicated if retry database connection on fail should
/// be attempted.
///
/// Allow only the first database connection attempt to fail and start
/// recovery. Sequential tries invoked by the dbReconnect callback should
/// not start yet another database connection attempt.
static bool retry_;
/// @brief Throws an exception if the connection is not usable. /// @brief Throws an exception if the connection is not usable.
/// @throw DbConnectionUnusable /// @throw DbConnectionUnusable
void checkUnusable() { void checkUnusable() {
@ -243,6 +270,7 @@ public:
} }
protected: protected:
/// @brief Sets the unusable flag to true. /// @brief Sets the unusable flag to true.
void markUnusable() { unusable_ = true; } void markUnusable() { unusable_ = true; }
@ -272,6 +300,27 @@ private:
/// @brief Reconnect settings. /// @brief Reconnect settings.
util::ReconnectCtlPtr reconnect_ctl_; util::ReconnectCtlPtr reconnect_ctl_;
/// The IOService object, used for all ASIO operations.
static isc::asiolink::IOServicePtr io_service_;
};
/// @brief RAII class to enable DB reconnect retries on server startup.
class DbConnectionInitWithRetry {
public:
/// @brief Constructor.
///
/// Enable DB reconnect retries on server startup.
DbConnectionInitWithRetry() {
DatabaseConnection::retry_ = true;
}
/// @brief Destructor.
///
/// Disable DB reconnect retries.
~DbConnectionInitWithRetry() {
DatabaseConnection::retry_ = false;
}
}; };
} // namespace db } // namespace db

View File

@ -61,7 +61,8 @@ DbAccessParser::parse(std::string& access_string,
for (std::pair<std::string, ConstElementPtr> param : database_config->mapValue()) { for (std::pair<std::string, ConstElementPtr> param : database_config->mapValue()) {
try { try {
if ((param.first == "persist") || if ((param.first == "persist") ||
(param.first == "readonly")) { (param.first == "readonly") ||
(param.first == "retry-on-startup")) {
values_copy[param.first] = (param.second->boolValue() ? values_copy[param.first] = (param.second->boolValue() ?
"true" : "false"); "true" : "false");

View File

@ -5,8 +5,10 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h> #include <config.h>
#include <database/database_connection.h>
#include <dhcpsrv/cfg_db_access.h> #include <dhcpsrv/cfg_db_access.h>
#include <dhcpsrv/db_type.h> #include <dhcpsrv/db_type.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/host_data_source_factory.h> #include <dhcpsrv/host_data_source_factory.h>
#include <dhcpsrv/host_mgr.h> #include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/lease_mgr_factory.h> #include <dhcpsrv/lease_mgr_factory.h>
@ -17,6 +19,7 @@
#include <vector> #include <vector>
using namespace isc::data; using namespace isc::data;
using namespace isc::db;
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
@ -55,8 +58,19 @@ CfgDbAccess::getHostDbAccessStringList() const {
void void
CfgDbAccess::createManagers() const { CfgDbAccess::createManagers() const {
try {
// Recreate lease manager without preserving the registered callbacks. // Recreate lease manager without preserving the registered callbacks.
LeaseMgrFactory::recreate(getLeaseDbAccessString(), false); LeaseMgrFactory::recreate(getLeaseDbAccessString(), false);
} catch (const isc::db::DbOpenErrorWithRetry& err) {
std::string redacted;
try {
DatabaseConnection::ParameterMap parameters = DatabaseConnection::parse(getLeaseDbAccessString());
redacted = DatabaseConnection::redactedAccessString(parameters);
} catch (...) {
}
LOG_INFO(dhcpsrv_logger, DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED)
.arg(redacted).arg(err.what());
}
// Recreate host data source. // Recreate host data source.
HostMgr::create(); HostMgr::create();
@ -69,7 +83,18 @@ CfgDbAccess::createManagers() const {
// Add database backends. // Add database backends.
std::list<std::string> host_db_access_list = getHostDbAccessStringList(); std::list<std::string> host_db_access_list = getHostDbAccessStringList();
for (std::string& hds : host_db_access_list) { for (std::string& hds : host_db_access_list) {
try {
HostMgr::addBackend(hds); HostMgr::addBackend(hds);
} catch (const isc::db::DbOpenErrorWithRetry& err) {
std::string redacted;
try {
DatabaseConnection::ParameterMap parameters = DatabaseConnection::parse(hds);
redacted = DatabaseConnection::redactedAccessString(parameters);
} catch (...) {
}
LOG_INFO(dhcpsrv_logger, DHCPSRV_HOST_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED)
.arg(redacted).arg(err.what());
}
} }
// Check for a host cache. // Check for a host cache.

View File

@ -71,6 +71,7 @@ extern const isc::log::MessageID DHCPSRV_HOOK_LEASE4_SELECT_SKIP = "DHCPSRV_HOOK
extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP = "DHCPSRV_HOOK_LEASE6_EXTEND_SKIP"; extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP = "DHCPSRV_HOOK_LEASE6_EXTEND_SKIP";
extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP = "DHCPSRV_HOOK_LEASE6_RECOVER_SKIP"; extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP = "DHCPSRV_HOOK_LEASE6_RECOVER_SKIP";
extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP = "DHCPSRV_HOOK_LEASE6_SELECT_SKIP"; extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP = "DHCPSRV_HOOK_LEASE6_SELECT_SKIP";
extern const isc::log::MessageID DHCPSRV_HOST_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED = "DHCPSRV_HOST_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED";
extern const isc::log::MessageID DHCPSRV_INVALID_ACCESS = "DHCPSRV_INVALID_ACCESS"; extern const isc::log::MessageID DHCPSRV_INVALID_ACCESS = "DHCPSRV_INVALID_ACCESS";
extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL = "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL"; extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL = "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL";
extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED = "DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED"; extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED = "DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED";
@ -78,6 +79,7 @@ extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL = "DHC
extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED = "DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED"; extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED = "DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED";
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION = "DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION"; extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION = "DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION";
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION = "DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION"; extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION = "DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION";
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED = "DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED";
extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FAIL = "DHCPSRV_LEASE_SANITY_FAIL"; extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FAIL = "DHCPSRV_LEASE_SANITY_FAIL";
extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FAIL_DISCARD = "DHCPSRV_LEASE_SANITY_FAIL_DISCARD"; extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FAIL_DISCARD = "DHCPSRV_LEASE_SANITY_FAIL_DISCARD";
extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FIXED = "DHCPSRV_LEASE_SANITY_FIXED"; extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FIXED = "DHCPSRV_LEASE_SANITY_FIXED";
@ -355,6 +357,7 @@ const char* values[] = {
"DHCPSRV_HOOK_LEASE6_EXTEND_SKIP", "DHCPv6 lease lifetime was not extended because a callout set the skip flag for message %1", "DHCPSRV_HOOK_LEASE6_EXTEND_SKIP", "DHCPv6 lease lifetime was not extended because a callout set the skip flag for message %1",
"DHCPSRV_HOOK_LEASE6_RECOVER_SKIP", "DHCPv6 lease %1 was not recovered from declined state because a callout set the skip status.", "DHCPSRV_HOOK_LEASE6_RECOVER_SKIP", "DHCPv6 lease %1 was not recovered from declined state because a callout set the skip status.",
"DHCPSRV_HOOK_LEASE6_SELECT_SKIP", "Lease6 (non-temporary) creation was skipped, because of callout skip flag.", "DHCPSRV_HOOK_LEASE6_SELECT_SKIP", "Lease6 (non-temporary) creation was skipped, because of callout skip flag.",
"DHCPSRV_HOST_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED", "Failed to connect to database: %1 with error: %2",
"DHCPSRV_INVALID_ACCESS", "invalid database access string: %1", "DHCPSRV_INVALID_ACCESS", "invalid database access string: %1",
"DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL", "extended info for lease %1 failed checks (%2)", "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL", "extended info for lease %1 failed checks (%2)",
"DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED", "extended info for lease %1 was upgraded", "DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED", "extended info for lease %1 was upgraded",
@ -362,6 +365,7 @@ const char* values[] = {
"DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED", "extended info for lease %1 was upgraded", "DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED", "extended info for lease %1 was upgraded",
"DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION", "exception occurred in a lease manager callback for callback type %1, subnet id %2, and lease %3: %4", "DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION", "exception occurred in a lease manager callback for callback type %1, subnet id %2, and lease %3: %4",
"DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION", "unknown exception occurred in a lease manager callback for callback type %1, subnet id %2, and lease %3", "DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION", "unknown exception occurred in a lease manager callback for callback type %1, subnet id %2, and lease %3",
"DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED", "Failed to connect to database: %1 with error: %2",
"DHCPSRV_LEASE_SANITY_FAIL", "The lease %1 with subnet-id %2 failed subnet-id checks (%3).", "DHCPSRV_LEASE_SANITY_FAIL", "The lease %1 with subnet-id %2 failed subnet-id checks (%3).",
"DHCPSRV_LEASE_SANITY_FAIL_DISCARD", "The lease %1 with subnet-id %2 failed subnet-id checks (%3) and was dropped.", "DHCPSRV_LEASE_SANITY_FAIL_DISCARD", "The lease %1 with subnet-id %2 failed subnet-id checks (%3) and was dropped.",
"DHCPSRV_LEASE_SANITY_FIXED", "The lease %1 with subnet-id %2 failed subnet-id checks, but was corrected to subnet-id %3.", "DHCPSRV_LEASE_SANITY_FIXED", "The lease %1 with subnet-id %2 failed subnet-id checks, but was corrected to subnet-id %3.",

View File

@ -72,6 +72,7 @@ extern const isc::log::MessageID DHCPSRV_HOOK_LEASE4_SELECT_SKIP;
extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP; extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP;
extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP; extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP;
extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP; extern const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP;
extern const isc::log::MessageID DHCPSRV_HOST_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED;
extern const isc::log::MessageID DHCPSRV_INVALID_ACCESS; extern const isc::log::MessageID DHCPSRV_INVALID_ACCESS;
extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL; extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL;
extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED; extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED;
@ -79,6 +80,7 @@ extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL;
extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED; extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED;
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION; extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION;
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION; extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION;
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED;
extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FAIL; extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FAIL;
extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FAIL_DISCARD; extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FAIL_DISCARD;
extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FIXED; extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FIXED;

View File

@ -341,6 +341,12 @@ have been experienced. Any such errors should have preceding entries in the
log with details. No further attempts to communicate with kea-dhcp-ddns will log with details. No further attempts to communicate with kea-dhcp-ddns will
be made without intervention. be made without intervention.
% DHCPSRV_HOST_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED Failed to connect to database: %1 with error: %2
This is an informational message issued when the the server failed to connect to
the host database. The operation started a retry to connect procedure.
The database access string with password redacted is logged, along with the
error and details for the reconnect procedure.
% DHCPSRV_HOOK_LEASE4_RECOVER_SKIP DHCPv4 lease %1 was not recovered from the declined state because a callout set the skip status. % DHCPSRV_HOOK_LEASE4_RECOVER_SKIP DHCPv4 lease %1 was not recovered from the declined state because a callout set the skip status.
This debug message is printed when a callout installed on lease4_recover This debug message is printed when a callout installed on lease4_recover
hook point set the next step status to SKIP. For this particular hook point, this hook point set the next step status to SKIP. For this particular hook point, this
@ -424,6 +430,12 @@ The third argument prints the lease for which the error has occurred.
This log message variant contains no error text because it is triggered This log message variant contains no error text because it is triggered
by an unknown exception. by an unknown exception.
% DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED Failed to connect to database: %1 with error: %2
This is an informational message issued when the the server failed to connect to
the lease database. The operation started a retry to connect procedure.
The database access string with password redacted is logged, along with the
error and details for the reconnect procedure.
% DHCPSRV_LEASE_SANITY_FAIL The lease %1 with subnet-id %2 failed subnet-id checks (%3). % DHCPSRV_LEASE_SANITY_FAIL The lease %1 with subnet-id %2 failed subnet-id checks (%3).
This warning message is printed when the lease being loaded does not match the This warning message is printed when the lease being loaded does not match the
configuration. Due to lease-checks value, the lease will be loaded, but configuration. Due to lease-checks value, the lease will be loaded, but

View File

@ -42,8 +42,6 @@ namespace dhcp {
using namespace isc::asiolink; using namespace isc::asiolink;
using namespace isc::db; using namespace isc::db;
IOServicePtr HostMgr::io_service_ = IOServicePtr();
boost::scoped_ptr<HostMgr>& boost::scoped_ptr<HostMgr>&
HostMgr::getHostMgrPtr() { HostMgr::getHostMgrPtr() {
static boost::scoped_ptr<HostMgr> host_mgr_ptr; static boost::scoped_ptr<HostMgr> host_mgr_ptr;

View File

@ -832,18 +832,6 @@ public:
return (ip_reservations_unique_); return (ip_reservations_unique_);
} }
/// @brief Sets IO service to be used by the Host Manager.
///
/// @param io_service IOService object, used for all ASIO operations.
static void setIOService(const isc::asiolink::IOServicePtr& io_service) {
io_service_ = io_service;
}
/// @brief Returns pointer to the IO service.
static isc::asiolink::IOServicePtr& getIOService() {
return (io_service_);
}
protected: protected:
/// @brief The negative caching flag. /// @brief The negative caching flag.
@ -901,9 +889,6 @@ private:
/// @brief Returns a pointer to the currently used instance of the /// @brief Returns a pointer to the currently used instance of the
/// @c HostMgr. /// @c HostMgr.
static boost::scoped_ptr<HostMgr>& getHostMgrPtr(); static boost::scoped_ptr<HostMgr>& getHostMgrPtr();
/// The IOService object, used for all ASIO operations.
static isc::asiolink::IOServicePtr io_service_;
}; };
} // namespace dhcp } // namespace dhcp

View File

@ -38,8 +38,6 @@ using namespace std;
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
IOServicePtr LeaseMgr::io_service_ = IOServicePtr();
LeasePageSize::LeasePageSize(const size_t page_size) LeasePageSize::LeasePageSize(const size_t page_size)
: page_size_(page_size) { : page_size_(page_size) {

View File

@ -805,6 +805,7 @@ public:
/// @brief Returns backend version. /// @brief Returns backend version.
/// ///
/// @param timer_name The DB reconnect timer name.
/// @return Version number as a pair of unsigned integers. "first" is the /// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number. /// major version number, "second" the minor number.
/// ///
@ -817,7 +818,7 @@ public:
/// B>=A and B=C (it is ok to have newer backend, as it should be backward /// B>=A and B=C (it is ok to have newer backend, as it should be backward
/// compatible) /// compatible)
/// Also if B>C, some database upgrade procedure may be triggered /// Also if B>C, some database upgrade procedure may be triggered
virtual VersionPair getVersion() const = 0; virtual VersionPair getVersion(const std::string& timer_name = "") const = 0;
/// @brief Commit Transactions /// @brief Commit Transactions
/// ///
@ -831,18 +832,6 @@ public:
/// support transactions, this is a no-op. /// support transactions, this is a no-op.
virtual void rollback() = 0; virtual void rollback() = 0;
/// @brief Sets IO service to be used by the Lease Manager.
///
/// @param io_service IOService object, used for all ASIO operations.
static void setIOService(const isc::asiolink::IOServicePtr& io_service) {
io_service_ = io_service;
}
/// @brief Returns pointer to the IO service.
static isc::asiolink::IOServicePtr& getIOService() {
return (io_service_);
}
// -- The following are memfile only, but defined in the base LeaseMgr for convenience. -- // -- The following are memfile only, but defined in the base LeaseMgr for convenience. --
/// @brief Returns the class lease count for a given class and lease type. /// @brief Returns the class lease count for a given class and lease type.
@ -1101,8 +1090,6 @@ protected:
const std::vector<uint8_t>& remote_id) = 0; const std::vector<uint8_t>& remote_id) = 0;
private: private:
/// The IOService object, used for all ASIO operations.
static isc::asiolink::IOServicePtr io_service_;
/// @brief Holds the setting whether the lease extended info tables /// @brief Holds the setting whether the lease extended info tables
/// are enabled or disabled. The default is disabled. /// are enabled or disabled. The default is disabled.

View File

@ -209,7 +209,7 @@ LFCSetup::setup(const uint32_t lfc_interval,
args.push_back("ignored-path"); args.push_back("ignored-path");
// Create the process (do not start it yet). // Create the process (do not start it yet).
process_.reset(new ProcessSpawn(LeaseMgr::getIOService(), executable, args)); process_.reset(new ProcessSpawn(DatabaseConnection::getIOService(), executable, args));
// If we've been told to run it once now, invoke the callback directly. // If we've been told to run it once now, invoke the callback directly.
if (run_once_now) { if (run_once_now) {
@ -2113,7 +2113,7 @@ Memfile_LeaseMgr::getDescription() const {
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
Memfile_LeaseMgr::getVersion() const { Memfile_LeaseMgr::getVersion(const std::string& /* timer_name */) const {
std::string const& universe(conn_.getParameter("universe")); std::string const& universe(conn_.getParameter("universe"));
if (universe == "4") { if (universe == "4") {
return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4); return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);

View File

@ -898,9 +898,10 @@ public:
/// @brief Returns backend version. /// @brief Returns backend version.
/// ///
/// @param timer_name The DB reconnect timer name.
/// @return Version number as a pair of unsigned integers. "first" is the /// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number. /// major version number, "second" the minor number.
virtual std::pair<uint32_t, uint32_t> getVersion() const override; virtual std::pair<uint32_t, uint32_t> getVersion(const std::string& /* timer_name */ = "") const override;
/// @brief Commit Transactions /// @brief Commit Transactions
/// ///

View File

@ -2171,13 +2171,14 @@ public:
/// The method is called by the constructor before opening the database /// The method is called by the constructor before opening the database
/// to verify that the schema version is correct. /// to verify that the schema version is correct.
/// ///
/// @param timer_name The DB reconnect timer name.
/// @return Version number stored in the database, as a pair of unsigned /// @return Version number stored in the database, as a pair of unsigned
/// integers. "first" is the major version number, "second" the /// integers. "first" is the major version number, "second" the
/// minor number. /// minor number.
/// ///
/// @throw isc::dhcp::DbOperationError An operation on the open database /// @throw isc::dhcp::DbOperationError An operation on the open database
/// has failed. /// has failed.
std::pair<uint32_t, uint32_t> getVersion() const; std::pair<uint32_t, uint32_t> getVersion(const std::string& timer_name = "") const;
/// @brief Executes statements which inserts a row into one of the tables. /// @brief Executes statements which inserts a row into one of the tables.
/// ///
@ -2882,7 +2883,19 @@ MySqlHostDataSourceImpl::MySqlHostDataSourceImpl(const DatabaseConnection::Param
// Validate the schema version first. // Validate the schema version first.
std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR,
MYSQL_SCHEMA_VERSION_MINOR); MYSQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion();
std::string timer_name = "";
bool retry = false;
if (parameters.count("retry-on-startup")) {
if (parameters.at("retry-on-startup") == "true") {
retry = true;
}
}
if (retry) {
timer_name = timer_name_;
}
std::pair<uint32_t, uint32_t> db_version = getVersion(timer_name);
if (code_version != db_version) { if (code_version != db_version) {
isc_throw(DbOpenError, isc_throw(DbOpenError,
"MySQL schema version mismatch: need version: " "MySQL schema version mismatch: need version: "
@ -2901,7 +2914,7 @@ MySqlHostDataSourceImpl::MySqlHostDataSourceImpl(const DatabaseConnection::Param
MySqlHostContextPtr MySqlHostContextPtr
MySqlHostDataSourceImpl::createContext() const { MySqlHostDataSourceImpl::createContext() const {
MySqlHostContextPtr ctx(new MySqlHostContext(parameters_, MySqlHostContextPtr ctx(new MySqlHostContext(parameters_,
IOServiceAccessorPtr(new IOServiceAccessor(&HostMgr::getIOService)), IOServiceAccessorPtr(new IOServiceAccessor(&DatabaseConnection::getIOService)),
&MySqlHostDataSourceImpl::dbReconnect)); &MySqlHostDataSourceImpl::dbReconnect));
// Open the database. // Open the database.
@ -3030,11 +3043,14 @@ MySqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
MySqlHostDataSourceImpl::getVersion() const { MySqlHostDataSourceImpl::getVersion(const std::string& timer_name) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MYSQL_HOST_DB_GET_VERSION); DHCPSRV_MYSQL_HOST_DB_GET_VERSION);
return (MySqlConnection::getVersion(parameters_)); IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
DbCallback cb(&MySqlHostDataSourceImpl::dbReconnect);
return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name));
} }
void void
@ -4096,8 +4112,8 @@ MySqlHostDataSource::getDescription() const {
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
MySqlHostDataSource::getVersion() const { MySqlHostDataSource::getVersion(const std::string& timer_name) const {
return(impl_->getVersion()); return(impl_->getVersion(timer_name));
} }
void void

View File

@ -458,13 +458,14 @@ public:
/// @brief Returns backend version. /// @brief Returns backend version.
/// ///
/// @param timer_name The DB reconnect timer name.
/// @return Version number stored in the database, as a pair of unsigned /// @return Version number stored in the database, as a pair of unsigned
/// integers. "first" is the major version number, "second" the /// integers. "first" is the major version number, "second" the
/// minor number. /// minor number.
/// ///
/// @throw isc::db::DbOperationError An operation on the open database /// @throw isc::db::DbOperationError An operation on the open database
/// has failed. /// has failed.
virtual std::pair<uint32_t, uint32_t> getVersion() const; virtual std::pair<uint32_t, uint32_t> getVersion(const std::string& timer_name = "") const;
/// @brief Commit Transactions /// @brief Commit Transactions
/// ///

View File

@ -2198,7 +2198,19 @@ MySqlLeaseMgr::MySqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
// Validate schema version first. // Validate schema version first.
std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR,
MYSQL_SCHEMA_VERSION_MINOR); MYSQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion();
std::string timer_name = "";
bool retry = false;
if (parameters.count("retry-on-startup")) {
if (parameters.at("retry-on-startup") == "true") {
retry = true;
}
}
if (retry) {
timer_name = timer_name_;
}
std::pair<uint32_t, uint32_t> db_version = getVersion(timer_name);
if (code_version != db_version) { if (code_version != db_version) {
isc_throw(DbOpenError, isc_throw(DbOpenError,
"MySQL schema version mismatch: need version: " "MySQL schema version mismatch: need version: "
@ -2287,9 +2299,12 @@ MySqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
MySqlLeaseContextPtr MySqlLeaseContextPtr
MySqlLeaseMgr::createContext() const { MySqlLeaseMgr::createContext() const {
MySqlLeaseContextPtr ctx(new MySqlLeaseContext(parameters_, MySqlLeaseContextPtr ctx(new MySqlLeaseContext(parameters_,
IOServiceAccessorPtr(new IOServiceAccessor(&LeaseMgr::getIOService)), IOServiceAccessorPtr(new IOServiceAccessor(&DatabaseConnection::getIOService)),
&MySqlLeaseMgr::dbReconnect)); &MySqlLeaseMgr::dbReconnect));
// Create ReconnectCtl for this connection.
ctx->conn_.makeReconnectCtl(timer_name_);
// Open the database. // Open the database.
ctx->conn_.openDatabase(); ctx->conn_.openDatabase();
@ -2314,9 +2329,6 @@ MySqlLeaseMgr::createContext() const {
ctx->exchange4_.reset(new MySqlLease4Exchange()); ctx->exchange4_.reset(new MySqlLease4Exchange());
ctx->exchange6_.reset(new MySqlLease6Exchange()); ctx->exchange6_.reset(new MySqlLease6Exchange());
// Create ReconnectCtl for this connection.
ctx->conn_.makeReconnectCtl(timer_name_);
return (ctx); return (ctx);
} }
@ -3824,10 +3836,13 @@ MySqlLeaseMgr::getDescription() const {
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
MySqlLeaseMgr::getVersion() const { MySqlLeaseMgr::getVersion(const string& timer_name) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_GET_VERSION); LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_GET_VERSION);
return (MySqlConnection::getVersion(parameters_)); IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
DbCallback cb(&MySqlLeaseMgr::dbReconnect);
return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name));
} }
void void

View File

@ -689,12 +689,13 @@ public:
/// @brief Returns backend version. /// @brief Returns backend version.
/// ///
/// @param timer_name The DB reconnect timer name.
/// @return Version number as a pair of unsigned integers. "first" is the /// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number. /// major version number, "second" the minor number.
/// ///
/// @throw isc::db::DbOperationError An operation on the open database has /// @throw isc::db::DbOperationError An operation on the open database has
/// failed. /// failed.
virtual std::pair<uint32_t, uint32_t> getVersion() const override; virtual std::pair<uint32_t, uint32_t> getVersion(const std::string& timer_name = "") const override;
/// @brief Commit Transactions /// @brief Commit Transactions
/// ///

View File

@ -1613,13 +1613,14 @@ public:
/// @brief Returns PostgreSQL schema version of the open database /// @brief Returns PostgreSQL schema version of the open database
/// ///
/// @param timer_name The DB reconnect timer name.
/// @return Version number stored in the database, as a pair of unsigned /// @return Version number stored in the database, as a pair of unsigned
/// integers. "first" is the major version number, "second" the /// integers. "first" is the major version number, "second" the
/// minor number. /// minor number.
/// ///
/// @throw isc::db::DbOperationError An operation on the open database /// @throw isc::db::DbOperationError An operation on the open database
/// has failed. /// has failed.
std::pair<uint32_t, uint32_t> getVersion() const; std::pair<uint32_t, uint32_t> getVersion(const std::string& timer_name = "") const;
/// @brief The parameters /// @brief The parameters
DatabaseConnection::ParameterMap parameters_; DatabaseConnection::ParameterMap parameters_;
@ -2299,7 +2300,19 @@ PgSqlHostDataSourceImpl::PgSqlHostDataSourceImpl(const DatabaseConnection::Param
// Validate the schema version first. // Validate the schema version first.
std::pair<uint32_t, uint32_t> code_version(PGSQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(PGSQL_SCHEMA_VERSION_MAJOR,
PGSQL_SCHEMA_VERSION_MINOR); PGSQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion();
std::string timer_name = "";
bool retry = false;
if (parameters.count("retry-on-startup")) {
if (parameters.at("retry-on-startup") == "true") {
retry = true;
}
}
if (retry) {
timer_name = timer_name_;
}
std::pair<uint32_t, uint32_t> db_version = getVersion(timer_name);
if (code_version != db_version) { if (code_version != db_version) {
isc_throw(DbOpenError, isc_throw(DbOpenError,
"PostgreSQL schema version mismatch: need version: " "PostgreSQL schema version mismatch: need version: "
@ -2318,7 +2331,7 @@ PgSqlHostDataSourceImpl::PgSqlHostDataSourceImpl(const DatabaseConnection::Param
PgSqlHostContextPtr PgSqlHostContextPtr
PgSqlHostDataSourceImpl::createContext() const { PgSqlHostDataSourceImpl::createContext() const {
PgSqlHostContextPtr ctx(new PgSqlHostContext(parameters_, PgSqlHostContextPtr ctx(new PgSqlHostContext(parameters_,
IOServiceAccessorPtr(new IOServiceAccessor(&HostMgr::getIOService)), IOServiceAccessorPtr(new IOServiceAccessor(&DatabaseConnection::getIOService)),
&PgSqlHostDataSourceImpl::dbReconnect)); &PgSqlHostDataSourceImpl::dbReconnect));
// Open the database. // Open the database.
@ -2616,10 +2629,14 @@ PgSqlHostDataSourceImpl::getHost(PgSqlHostContextPtr& ctx,
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
PgSqlHostDataSourceImpl::getVersion() const { PgSqlHostDataSourceImpl::getVersion(const std::string& timer_name) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_HOST_DB_GET_VERSION); DHCPSRV_PGSQL_HOST_DB_GET_VERSION);
return (PgSqlConnection::getVersion(parameters_));
IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
DbCallback cb(&PgSqlHostDataSourceImpl::dbReconnect);
return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name));
} }
void void
@ -3298,8 +3315,8 @@ PgSqlHostDataSource::getDescription() const {
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
PgSqlHostDataSource::getVersion() const { PgSqlHostDataSource::getVersion(const std::string& timer_name) const {
return(impl_->getVersion()); return(impl_->getVersion(timer_name));
} }
void void

View File

@ -510,13 +510,14 @@ public:
/// is correct. Thus it must not rely on a pre-prepared statement or /// is correct. Thus it must not rely on a pre-prepared statement or
/// formal statement execution error checking. /// formal statement execution error checking.
/// ///
/// @param timer_name The DB reconnect timer name.
/// @return Version number stored in the database, as a pair of unsigned /// @return Version number stored in the database, as a pair of unsigned
/// integers. "first" is the major version number, "second" the /// integers. "first" is the major version number, "second" the
/// minor number. /// minor number.
/// ///
/// @throw isc::db::DbOperationError An operation on the open database /// @throw isc::db::DbOperationError An operation on the open database
/// has failed. /// has failed.
virtual std::pair<uint32_t, uint32_t> getVersion() const; virtual std::pair<uint32_t, uint32_t> getVersion(const std::string& timer_name = "") const;
/// @brief Commit Transactions /// @brief Commit Transactions
/// ///

View File

@ -1647,7 +1647,19 @@ PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
// Validate schema version first. // Validate schema version first.
std::pair<uint32_t, uint32_t> code_version(PGSQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(PGSQL_SCHEMA_VERSION_MAJOR,
PGSQL_SCHEMA_VERSION_MINOR); PGSQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion();
std::string timer_name = "";
bool retry = false;
if (parameters.count("retry-on-startup")) {
if (parameters.at("retry-on-startup") == "true") {
retry = true;
}
}
if (retry) {
timer_name = timer_name_;
}
std::pair<uint32_t, uint32_t> db_version = getVersion(timer_name);
if (code_version != db_version) { if (code_version != db_version) {
isc_throw(DbOpenError, isc_throw(DbOpenError,
"PostgreSQL schema version mismatch: need version: " "PostgreSQL schema version mismatch: need version: "
@ -1736,9 +1748,12 @@ PgSqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
PgSqlLeaseContextPtr PgSqlLeaseContextPtr
PgSqlLeaseMgr::createContext() const { PgSqlLeaseMgr::createContext() const {
PgSqlLeaseContextPtr ctx(new PgSqlLeaseContext(parameters_, PgSqlLeaseContextPtr ctx(new PgSqlLeaseContext(parameters_,
IOServiceAccessorPtr(new IOServiceAccessor(&LeaseMgr::getIOService)), IOServiceAccessorPtr(new IOServiceAccessor(&DatabaseConnection::getIOService)),
&PgSqlLeaseMgr::dbReconnect)); &PgSqlLeaseMgr::dbReconnect));
// Create ReconnectCtl for this connection.
ctx->conn_.makeReconnectCtl(timer_name_);
// Open the database. // Open the database.
ctx->conn_.openDatabase(); ctx->conn_.openDatabase();
@ -1759,9 +1774,6 @@ PgSqlLeaseMgr::createContext() const {
ctx->exchange4_.reset(new PgSqlLease4Exchange()); ctx->exchange4_.reset(new PgSqlLease4Exchange());
ctx->exchange6_.reset(new PgSqlLease6Exchange()); ctx->exchange6_.reset(new PgSqlLease6Exchange());
// Create ReconnectCtl for this connection.
ctx->conn_.makeReconnectCtl(timer_name_);
return (ctx); return (ctx);
} }
@ -2989,10 +3001,13 @@ PgSqlLeaseMgr::getDescription() const {
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
PgSqlLeaseMgr::getVersion() const { PgSqlLeaseMgr::getVersion(const string& timer_name) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_PGSQL_GET_VERSION); LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_PGSQL_GET_VERSION);
return (PgSqlConnection::getVersion(parameters_)); IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
DbCallback cb(&PgSqlLeaseMgr::dbReconnect);
return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name));
} }
void void

View File

@ -665,12 +665,13 @@ public:
/// @brief Returns backend version. /// @brief Returns backend version.
/// ///
/// @param timer_name The DB reconnect timer name.
/// @return Version number as a pair of unsigned integers. "first" is the /// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number. /// major version number, "second" the minor number.
/// ///
/// @throw isc::db::DbOperationError An operation on the open database has /// @throw isc::db::DbOperationError An operation on the open database has
/// failed. /// failed.
virtual std::pair<uint32_t, uint32_t> getVersion() const override; virtual std::pair<uint32_t, uint32_t> getVersion(const std::string& timer_name = "") const override;
/// @brief Commit Transactions /// @brief Commit Transactions
/// ///

View File

@ -107,7 +107,6 @@ libdhcpsrv_unittests_SOURCES += lease_file_loader_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_unittest.cc libdhcpsrv_unittests_SOURCES += lease_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += generic_lease_mgr_unittest.cc generic_lease_mgr_unittest.h
libdhcpsrv_unittests_SOURCES += memfile_lease_extended_info_unittest.cc libdhcpsrv_unittests_SOURCES += memfile_lease_extended_info_unittest.cc
libdhcpsrv_unittests_SOURCES += memfile_lease_limits_unittest.cc libdhcpsrv_unittests_SOURCES += memfile_lease_limits_unittest.cc
libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc

View File

@ -11,7 +11,7 @@
#include <dhcpsrv/memfile_lease_mgr.h> #include <dhcpsrv/memfile_lease_mgr.h>
#include <dhcpsrv/testutils/test_utils.h> #include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/testutils/concrete_lease_mgr.h> #include <dhcpsrv/testutils/concrete_lease_mgr.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h> #include <dhcpsrv/testutils/generic_lease_mgr_unittest.h>
#include <testutils/gtest_utils.h> #include <testutils/gtest_utils.h>
#include <iostream> #include <iostream>

View File

@ -20,7 +20,7 @@
#include <dhcpsrv/timer_mgr.h> #include <dhcpsrv/timer_mgr.h>
#include <dhcpsrv/testutils/lease_file_io.h> #include <dhcpsrv/testutils/lease_file_io.h>
#include <dhcpsrv/testutils/test_utils.h> #include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h> #include <dhcpsrv/testutils/generic_lease_mgr_unittest.h>
#include <testutils/gtest_utils.h> #include <testutils/gtest_utils.h>
#include <util/multi_threading_mgr.h> #include <util/multi_threading_mgr.h>
#include <util/pid_file.h> #include <util/pid_file.h>
@ -117,7 +117,7 @@ public:
extra_files_() { extra_files_() {
timer_mgr_->setIOService(io_service_); timer_mgr_->setIOService(io_service_);
LeaseMgr::setIOService(io_service_); DatabaseConnection::setIOService(io_service_);
std::ostringstream s; std::ostringstream s;
s << KEA_LFC_BUILD_DIR << "/kea-lfc"; s << KEA_LFC_BUILD_DIR << "/kea-lfc";

View File

@ -1690,6 +1690,54 @@ TEST_F(MySQLHostMgrTest, setIPReservationsUnique) {
EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(false)); EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
} }
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
/// @brief Verifies that db lost callback is not invoked on an open failure /// @brief Verifies that db lost callback is not invoked on an open failure
TEST_F(MySQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) { TEST_F(MySQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
MultiThreadingTest mt(false); MultiThreadingTest mt(false);

View File

@ -10,8 +10,8 @@
#include <dhcpsrv/lease_mgr_factory.h> #include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/mysql_lease_mgr.h> #include <dhcpsrv/mysql_lease_mgr.h>
#include <dhcpsrv/testutils/test_utils.h> #include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/testutils/generic_lease_mgr_unittest.h>
#include <dhcpsrv/testutils/mysql_generic_backend_unittest.h> #include <dhcpsrv/testutils/mysql_generic_backend_unittest.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
#include <mysql/mysql_connection.h> #include <mysql/mysql_connection.h>
#include <mysql/testutils/mysql_schema.h> #include <mysql/testutils/mysql_schema.h>
@ -976,6 +976,54 @@ public:
} }
}; };
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
/// @brief Verifies that db lost callback is not invoked on an open failure /// @brief Verifies that db lost callback is not invoked on an open failure
TEST_F(MySqlLeaseMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) { TEST_F(MySqlLeaseMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
MultiThreadingTest mt(false); MultiThreadingTest mt(false);

View File

@ -1658,6 +1658,54 @@ TEST_F(PgSQLHostMgrTest, setIPReservationsUnique) {
EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(false)); EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
} }
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSQLHostMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
/// @brief Verifies that db lost callback is not invoked on an open failure /// @brief Verifies that db lost callback is not invoked on an open failure
TEST_F(PgSQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) { TEST_F(PgSQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
MultiThreadingTest mt(false); MultiThreadingTest mt(false);

View File

@ -10,8 +10,8 @@
#include <dhcpsrv/lease_mgr_factory.h> #include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/pgsql_lease_mgr.h> #include <dhcpsrv/pgsql_lease_mgr.h>
#include <dhcpsrv/testutils/test_utils.h> #include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/testutils/generic_lease_mgr_unittest.h>
#include <dhcpsrv/testutils/pgsql_generic_backend_unittest.h> #include <dhcpsrv/testutils/pgsql_generic_backend_unittest.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
#include <pgsql/pgsql_connection.h> #include <pgsql/pgsql_connection.h>
#include <pgsql/testutils/pgsql_schema.h> #include <pgsql/testutils/pgsql_schema.h>
@ -943,6 +943,54 @@ public:
} }
}; };
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallback) {
MultiThreadingTest mt(false);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testRetryOpenDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
MultiThreadingTest mt(true);
testRetryOpenDbLostAndFailedAfterTimeoutCallback();
}
/// @brief Verifies that db lost callback is not invoked on an open failure /// @brief Verifies that db lost callback is not invoked on an open failure
TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) { TEST_F(PgSqlLeaseMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
MultiThreadingTest mt(false); MultiThreadingTest mt(false);

View File

@ -8,7 +8,7 @@
#include <dhcpsrv/subnet_id.h> #include <dhcpsrv/subnet_id.h>
#include <dhcpsrv/testutils/concrete_lease_mgr.h> #include <dhcpsrv/testutils/concrete_lease_mgr.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h> #include <dhcpsrv/testutils/generic_lease_mgr_unittest.h>
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
#include <functional> #include <functional>
#include <gtest/gtest.h> #include <gtest/gtest.h>

View File

@ -19,6 +19,7 @@ libdhcpsrvtest_la_SOURCES += host_data_source_utils.cc host_data_source_utils.h
libdhcpsrvtest_la_SOURCES += memory_host_data_source.cc memory_host_data_source.h libdhcpsrvtest_la_SOURCES += memory_host_data_source.cc memory_host_data_source.h
libdhcpsrvtest_la_SOURCES += test_utils.cc test_utils.h libdhcpsrvtest_la_SOURCES += test_utils.cc test_utils.h
libdhcpsrvtest_la_SOURCES += generic_backend_unittest.cc generic_backend_unittest.h libdhcpsrvtest_la_SOURCES += generic_backend_unittest.cc generic_backend_unittest.h
libdhcpsrvtest_la_SOURCES += generic_lease_mgr_unittest.cc generic_lease_mgr_unittest.h
libdhcpsrvtest_la_SOURCES += generic_host_data_source_unittest.cc generic_host_data_source_unittest.h libdhcpsrvtest_la_SOURCES += generic_host_data_source_unittest.cc generic_host_data_source_unittest.h
libdhcpsrvtest_la_SOURCES += generic_cb_dhcp4_unittest.h generic_cb_dhcp4_unittest.cc libdhcpsrvtest_la_SOURCES += generic_cb_dhcp4_unittest.h generic_cb_dhcp4_unittest.cc
libdhcpsrvtest_la_SOURCES += generic_cb_dhcp6_unittest.h generic_cb_dhcp6_unittest.cc libdhcpsrvtest_la_SOURCES += generic_cb_dhcp6_unittest.h generic_cb_dhcp6_unittest.cc

View File

@ -328,7 +328,7 @@ ConcreteLeaseMgr::getDescription() const {
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
ConcreteLeaseMgr::getVersion() const { ConcreteLeaseMgr::getVersion(const std::string& /* timer_name */) const {
return (make_pair(uint32_t(0), uint32_t(0))); return (make_pair(uint32_t(0), uint32_t(0)));
} }

View File

@ -414,7 +414,9 @@ public:
virtual std::string getDescription() const override; virtual std::string getDescription() const override;
/// @brief Returns backend version. /// @brief Returns backend version.
virtual std::pair<uint32_t, uint32_t> getVersion() const override; ///
/// @param timer_name The DB reconnect timer name.
virtual std::pair<uint32_t, uint32_t> getVersion(const std::string& /* timer_name */ = "") const override;
/// @brief Commit transactions /// @brief Commit transactions
virtual void commit() override; virtual void commit() override;

View File

@ -41,6 +41,7 @@ GenericConfigBackendDbLostCallbackTest::SetUp() {
DatabaseConnection::db_lost_callback_ = 0; DatabaseConnection::db_lost_callback_ = 0;
DatabaseConnection::db_recovered_callback_ = 0; DatabaseConnection::db_recovered_callback_ = 0;
DatabaseConnection::db_failed_callback_ = 0; DatabaseConnection::db_failed_callback_ = 0;
isc::db::DatabaseConnection::setIOService(io_service_);
setConfigBackendImplIOService(io_service_); setConfigBackendImplIOService(io_service_);
isc::dhcp::TimerMgr::instance()->setIOService(io_service_); isc::dhcp::TimerMgr::instance()->setIOService(io_service_);
isc::dhcp::CfgMgr::instance().clear(); isc::dhcp::CfgMgr::instance().clear();
@ -61,11 +62,256 @@ GenericConfigBackendDbLostCallbackTest::TearDown() {
DatabaseConnection::db_lost_callback_ = 0; DatabaseConnection::db_lost_callback_ = 0;
DatabaseConnection::db_recovered_callback_ = 0; DatabaseConnection::db_recovered_callback_ = 0;
DatabaseConnection::db_failed_callback_ = 0; DatabaseConnection::db_failed_callback_ = 0;
isc::db::DatabaseConnection::setIOService(IOServicePtr());
setConfigBackendImplIOService(IOServicePtr()); setConfigBackendImplIOService(IOServicePtr());
isc::dhcp::TimerMgr::instance()->unregisterTimers(); isc::dhcp::TimerMgr::instance()->unregisterTimers();
isc::dhcp::CfgMgr::instance().clear(); isc::dhcp::CfgMgr::instance().clear();
} }
void
GenericConfigBackendDbLostCallbackTest::testRetryOpenDbLostAndRecoveredCallback() {
// Set the connectivity lost callback.
DatabaseConnection::db_lost_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
DatabaseConnection::db_recovered_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
DatabaseConnection::db_failed_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectionString();
access += " retry-on-startup=true";
ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Connect to the CB backend.
ASSERT_THROW(addBackend(access), DbOpenErrorWithRetry);
dbr.reset();
// Verify we can execute a query. We don't care about the answer.
ServerCollection servers;
// A query should fail with NoSuchDatabase,.
ASSERT_THROW(servers = getAllServers(), NoSuchDatabase);
access = validConnectionString();
CfgMgr::instance().clear();
// by adding an invalid access will cause the manager factory to throw
// resulting in failure to recreate the manager
config_ctl_info.reset(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
const ConfigDbInfoList& cfg = CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases();
(const_cast<ConfigDbInfoList&>(cfg))[0].setAccessString(access, true);
io_service_->poll();
// Our lost and recovered connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
// Verify we can execute a query. We don't care about the answer.
ASSERT_NO_THROW_LOG(servers = getAllServers());
}
void
GenericConfigBackendDbLostCallbackTest::testRetryOpenDbLostAndFailedCallback() {
// Set the connectivity lost callback.
DatabaseConnection::db_lost_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
DatabaseConnection::db_recovered_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
DatabaseConnection::db_failed_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectionString();
access += " retry-on-startup=true";
ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Connect to the CB backend.
ASSERT_THROW(addBackend(access), DbOpenErrorWithRetry);
dbr.reset();
// Verify we can execute a query. We don't care about the answer.
ServerCollection servers;
// A query should fail with NoSuchDatabase,.
ASSERT_THROW(servers = getAllServers(), NoSuchDatabase);
io_service_->poll();
// Our lost and failed connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(1, db_failed_callback_called_);
// A query should fail with NoSuchDatabase,.
ASSERT_THROW(servers = getAllServers(), NoSuchDatabase);
}
void
GenericConfigBackendDbLostCallbackTest::testRetryOpenDbLostAndRecoveredAfterTimeoutCallback() {
// Set the connectivity lost callback.
DatabaseConnection::db_lost_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
DatabaseConnection::db_recovered_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
DatabaseConnection::db_failed_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectionString();
std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1 retry-on-startup=true";
access += extra;
ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Connect to the CB backend.
ASSERT_THROW(addBackend(access), DbOpenErrorWithRetry);
dbr.reset();
// Verify we can execute a query. We don't care about the answer.
ServerCollection servers;
// A query should fail with NoSuchDatabase,.
ASSERT_THROW(servers = getAllServers(), NoSuchDatabase);
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
access = validConnectionString();
access += extra;
CfgMgr::instance().clear();
config_ctl_info.reset(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
sleep(1);
io_service_->poll();
// Our lost and recovered connectivity callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
// Verify we can execute a query. We don't care about the answer.
ASSERT_NO_THROW_LOG(servers = getAllServers());
sleep(1);
io_service_->poll();
// No callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
// Verify we can execute a query. We don't care about the answer.
ASSERT_NO_THROW_LOG(servers = getAllServers());
}
void
GenericConfigBackendDbLostCallbackTest::testRetryOpenDbLostAndFailedAfterTimeoutCallback() {
// Set the connectivity lost callback.
DatabaseConnection::db_lost_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
DatabaseConnection::db_recovered_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
DatabaseConnection::db_failed_callback_ =
std::bind(&GenericConfigBackendDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectionString();
std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1 retry-on-startup=true";
access += extra;
ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Connect to the CB backend.
ASSERT_THROW(addBackend(access), DbOpenErrorWithRetry);
dbr.reset();
// Verify we can execute a query. We don't care about the answer.
ServerCollection servers;
// A query should fail with NoSuchDatabase,.
ASSERT_THROW(servers = getAllServers(), NoSuchDatabase);
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
// A query should fail with NoSuchDatabase,.
ASSERT_THROW(servers = getAllServers(), NoSuchDatabase);
sleep(1);
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
// A query should fail with NoSuchDatabase,.
ASSERT_THROW(servers = getAllServers(), NoSuchDatabase);
sleep(1);
io_service_->poll();
// Our lost and failed connectivity callback should have been invoked.
EXPECT_EQ(3, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(1, db_failed_callback_called_);
// A query should fail with NoSuchDatabase,.
ASSERT_THROW(servers = getAllServers(), NoSuchDatabase);
}
void void
GenericConfigBackendDbLostCallbackTest::testNoCallbackOnOpenFailure() { GenericConfigBackendDbLostCallbackTest::testNoCallbackOnOpenFailure() {
DatabaseConnection::db_lost_callback_ = DatabaseConnection::db_lost_callback_ =
@ -158,6 +404,7 @@ GenericConfigBackendDbLostCallbackTest::testDbLostAndFailedCallback() {
std::bind(&GenericConfigBackendDbLostCallbackTest::db_failed_callback, this, ph::_1); std::bind(&GenericConfigBackendDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = validConnectionString(); std::string access = validConnectionString();
ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo()); ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access); config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
@ -221,6 +468,7 @@ GenericConfigBackendDbLostCallbackTest::testDbLostAndRecoveredAfterTimeoutCallba
std::string access = validConnectionString(); std::string access = validConnectionString();
std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1"; std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1";
access += extra; access += extra;
ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo()); ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access); config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
@ -310,6 +558,7 @@ GenericConfigBackendDbLostCallbackTest::testDbLostAndFailedAfterTimeoutCallback(
std::string access = validConnectionString(); std::string access = validConnectionString();
std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1"; std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1";
access += extra; access += extra;
ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo()); ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
config_ctl_info->addConfigDatabase(access); config_ctl_info->addConfigDatabase(access);
CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info); CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);

View File

@ -72,6 +72,48 @@ public:
/// we created. /// we created.
virtual void TearDown(); virtual void TearDown();
/// @brief Verifies the CB manager's behavior if DB connection can not be
/// established but succeeds on retry
///
/// This function creates a CB manager with a back end that supports
/// connectivity lost callback. It verifies that connectivity is unavailable
/// and then recovered on retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbRecoveredCallback was invoked
void testRetryOpenDbLostAndRecoveredCallback();
/// @brief Verifies the CB manager's behavior if DB connection can not be
/// established but fails on retry
///
/// This function creates a CB manager with a back end that supports
/// connectivity lost callback. It verifies that connectivity is unavailable
/// and then fails again on retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbFailedCallback was invoked
void testRetryOpenDbLostAndFailedCallback();
/// @brief Verifies the CB manager's behavior if DB connection can not be
/// established but succeeds on retry
///
/// This function creates a CB manager with a back end that supports
/// connectivity lost callback. It verifies that connectivity is unavailable
/// and then recovered on retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbRecoveredCallback was invoked after two reconnect
/// attempts (once failing and second triggered by timer)
void testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
/// @brief Verifies the CB manager's behavior if DB connection can not be
/// established but fails on retry
///
/// This function creates a CB manager with a back end that supports
/// connectivity lost callback. It verifies that connectivity is unavailable
/// and then fails again on retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbFailedCallback was invoked after two reconnect
/// attempts (once failing and second triggered by timer)
void testRetryOpenDbLostAndFailedAfterTimeoutCallback();
/// @brief Verifies open failures do NOT invoke db lost callback /// @brief Verifies open failures do NOT invoke db lost callback
/// ///
/// The db lost callback should only be invoked after successfully /// The db lost callback should only be invoked after successfully

View File

@ -2674,6 +2674,216 @@ GenericHostDataSourceTest::testMultipleHosts6() {
ASSERT_NO_THROW(hdsptr_->add(host2)); ASSERT_NO_THROW(hdsptr_->add(host2));
} }
void
HostMgrDbLostCallbackTest::testRetryOpenDbLostAndRecoveredCallback() {
// Set the connectivity lost callback.
isc::db::DatabaseConnection::db_lost_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
isc::db::DatabaseConnection::db_recovered_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
isc::db::DatabaseConnection::db_failed_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectString();
access += " retry-on-startup=true";
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Create the HostMgr.
HostMgr::create();
ASSERT_THROW(HostMgr::addBackend(access), DbOpenErrorWithRetry);
dbr.reset();
ASSERT_FALSE(HostMgr::instance().getHostDataSource());
access = validConnectString();
access += " retry-on-startup=true";
CfgMgr::instance().clear();
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
io_service_->poll();
// Our lost and recovered connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_TRUE(HostMgr::instance().getHostDataSource());
}
void
HostMgrDbLostCallbackTest::testRetryOpenDbLostAndFailedCallback() {
// Set the connectivity lost callback.
isc::db::DatabaseConnection::db_lost_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
isc::db::DatabaseConnection::db_recovered_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
isc::db::DatabaseConnection::db_failed_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectString();
access += " retry-on-startup=true";
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Create the HostMgr.
HostMgr::create();
ASSERT_THROW(HostMgr::addBackend(access), DbOpenErrorWithRetry);
dbr.reset();
ASSERT_FALSE(HostMgr::instance().getHostDataSource());
io_service_->poll();
// Our lost and failed connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(1, db_failed_callback_called_);
ASSERT_FALSE(HostMgr::instance().getHostDataSource());
}
void
HostMgrDbLostCallbackTest::testRetryOpenDbLostAndRecoveredAfterTimeoutCallback() {
// Set the connectivity lost callback.
isc::db::DatabaseConnection::db_lost_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
isc::db::DatabaseConnection::db_recovered_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
isc::db::DatabaseConnection::db_failed_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectString();
std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1 retry-on-startup=true";
access += extra;
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Create the HostMgr.
HostMgr::create();
ASSERT_THROW(HostMgr::addBackend(access), DbOpenErrorWithRetry);
dbr.reset();
ASSERT_FALSE(HostMgr::instance().getHostDataSource());
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
access = validConnectString();
access += extra;
CfgMgr::instance().clear();
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
sleep(1);
io_service_->poll();
// Our lost and recovered connectivity callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_TRUE(HostMgr::instance().getHostDataSource());
sleep(1);
io_service_->poll();
// No callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_TRUE(HostMgr::instance().getHostDataSource());
}
void
HostMgrDbLostCallbackTest::testRetryOpenDbLostAndFailedAfterTimeoutCallback() {
// Set the connectivity lost callback.
isc::db::DatabaseConnection::db_lost_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
isc::db::DatabaseConnection::db_recovered_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
isc::db::DatabaseConnection::db_failed_callback_ =
std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectString();
std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1 retry-on-startup=true";
access += extra;
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Create the HostMgr.
HostMgr::create();
ASSERT_THROW(HostMgr::addBackend(access), DbOpenErrorWithRetry);
dbr.reset();
ASSERT_FALSE(HostMgr::instance().getHostDataSource());
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_FALSE(HostMgr::instance().getHostDataSource());
sleep(1);
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_FALSE(HostMgr::instance().getHostDataSource());
sleep(1);
io_service_->poll();
// Our lost and failed connectivity callback should have been invoked.
EXPECT_EQ(3, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(1, db_failed_callback_called_);
ASSERT_FALSE(HostMgr::instance().getHostDataSource());
}
void void
HostMgrDbLostCallbackTest::testNoCallbackOnOpenFailure() { HostMgrDbLostCallbackTest::testNoCallbackOnOpenFailure() {
isc::db::DatabaseConnection::db_lost_callback_ = isc::db::DatabaseConnection::db_lost_callback_ =

View File

@ -555,7 +555,7 @@ public:
isc::db::DatabaseConnection::db_lost_callback_ = 0; isc::db::DatabaseConnection::db_lost_callback_ = 0;
isc::db::DatabaseConnection::db_recovered_callback_ = 0; isc::db::DatabaseConnection::db_recovered_callback_ = 0;
isc::db::DatabaseConnection::db_failed_callback_ = 0; isc::db::DatabaseConnection::db_failed_callback_ = 0;
isc::dhcp::HostMgr::setIOService(io_service_); isc::db::DatabaseConnection::setIOService(io_service_);
isc::dhcp::TimerMgr::instance()->setIOService(io_service_); isc::dhcp::TimerMgr::instance()->setIOService(io_service_);
isc::dhcp::CfgMgr::instance().clear(); isc::dhcp::CfgMgr::instance().clear();
} }
@ -564,7 +564,7 @@ public:
isc::db::DatabaseConnection::db_lost_callback_ = 0; isc::db::DatabaseConnection::db_lost_callback_ = 0;
isc::db::DatabaseConnection::db_recovered_callback_ = 0; isc::db::DatabaseConnection::db_recovered_callback_ = 0;
isc::db::DatabaseConnection::db_failed_callback_ = 0; isc::db::DatabaseConnection::db_failed_callback_ = 0;
isc::dhcp::HostMgr::setIOService(isc::asiolink::IOServicePtr()); isc::db::DatabaseConnection::setIOService(isc::asiolink::IOServicePtr());
isc::dhcp::TimerMgr::instance()->unregisterTimers(); isc::dhcp::TimerMgr::instance()->unregisterTimers();
isc::dhcp::CfgMgr::instance().clear(); isc::dhcp::CfgMgr::instance().clear();
} }
@ -606,6 +606,50 @@ public:
/// string /// string
virtual std::string invalidConnectString() = 0; virtual std::string invalidConnectString() = 0;
/// @brief Verifies the host manager's behavior if DB connection can not be
/// established but succeeds on retry
///
/// This function creates a host manager with a back end that supports
/// connectivity lost callback (currently only MySQL and PostgreSQL). It
/// verifies that connectivity is unavailable and then recovered on retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbRecoveredCallback was invoked
void testRetryOpenDbLostAndRecoveredCallback();
/// @brief Verifies the host manager's behavior if DB connection can not be
/// established but fails on retry
///
/// This function creates a host manager with a back end that supports
/// connectivity lost callback (currently only MySQL and PostgreSQL). It
/// It verifies that connectivity is unavailable and then fails again on
/// retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbFailedCallback was invoked
void testRetryOpenDbLostAndFailedCallback();
/// @brief Verifies the host manager's behavior if DB connection can not be
/// established but succeeds on retry
///
/// This function creates a host manager with a back end that supports
/// connectivity lost callback (currently only MySQL and PostgreSQL). It
/// verifies that connectivity is unavailable and then recovered on retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbRecoveredCallback was invoked after two reconnect
/// attempts (once failing and second triggered by timer)
void testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
/// @brief Verifies the host manager's behavior if DB connection can not be
/// established but fails on retry
///
/// This function creates a host manager with a back end that supports
/// connectivity lost callback (currently only MySQL and PostgreSQL). It
/// It verifies that connectivity is unavailable and then fails again on
/// retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbFailedCallback was invoked after two reconnect
/// attempts (once failing and second triggered by timer)
void testRetryOpenDbLostAndFailedAfterTimeoutCallback();
/// @brief Verifies open failures do NOT invoke db lost callback /// @brief Verifies open failures do NOT invoke db lost callback
/// ///
/// The db lost callback should only be invoked after successfully /// The db lost callback should only be invoked after successfully

View File

@ -12,7 +12,7 @@
#include <dhcpsrv/cfgmgr.h> #include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/dhcpsrv_exceptions.h> #include <dhcpsrv/dhcpsrv_exceptions.h>
#include <dhcpsrv/lease_mgr_factory.h> #include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h> #include <dhcpsrv/testutils/generic_lease_mgr_unittest.h>
#include <dhcpsrv/testutils/test_utils.h> #include <dhcpsrv/testutils/test_utils.h>
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
#include <stats/stats_mgr.h> #include <stats/stats_mgr.h>
@ -3350,6 +3350,204 @@ LeaseMgrDbLostCallbackTest::TearDown() {
isc::dhcp::LeaseMgrFactory::destroy(); isc::dhcp::LeaseMgrFactory::destroy();
} }
void
LeaseMgrDbLostCallbackTest::testRetryOpenDbLostAndRecoveredCallback() {
// Set the connectivity lost callback.
DatabaseConnection::db_lost_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
DatabaseConnection::db_recovered_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
DatabaseConnection::db_failed_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectString();
access += " retry-on-startup=true";
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Connect to the lease backend.
ASSERT_THROW(LeaseMgrFactory::create(access), DbOpenErrorWithRetry);
dbr.reset();
ASSERT_FALSE(LeaseMgrFactory::haveInstance());
access = validConnectString();
access += " retry-on-startup=true";
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
io_service_->poll();
// Our lost and recovered connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_TRUE(LeaseMgrFactory::haveInstance());
}
void
LeaseMgrDbLostCallbackTest::testRetryOpenDbLostAndFailedCallback() {
// Set the connectivity lost callback.
DatabaseConnection::db_lost_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
DatabaseConnection::db_recovered_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
DatabaseConnection::db_failed_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectString();
access += " retry-on-startup=true";
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Connect to the lease backend.
ASSERT_THROW(LeaseMgrFactory::create(access), DbOpenErrorWithRetry);
dbr.reset();
ASSERT_FALSE(LeaseMgrFactory::haveInstance());
io_service_->poll();
// Our lost and failed connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(1, db_failed_callback_called_);
ASSERT_FALSE(LeaseMgrFactory::haveInstance());
}
void
LeaseMgrDbLostCallbackTest::testRetryOpenDbLostAndRecoveredAfterTimeoutCallback() {
// Set the connectivity lost callback.
DatabaseConnection::db_lost_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
DatabaseConnection::db_recovered_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
DatabaseConnection::db_failed_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectString();
std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1 retry-on-startup=true";
access += extra;
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Connect to the lease backend.
ASSERT_THROW(LeaseMgrFactory::create(access), DbOpenErrorWithRetry);
dbr.reset();
ASSERT_FALSE(LeaseMgrFactory::haveInstance());
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
access = validConnectString();
access += extra;
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
sleep(1);
io_service_->poll();
// Our lost and recovered connectivity callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_TRUE(LeaseMgrFactory::haveInstance());
sleep(1);
io_service_->poll();
// No callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(1, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_TRUE(LeaseMgrFactory::haveInstance());
}
void
LeaseMgrDbLostCallbackTest::testRetryOpenDbLostAndFailedAfterTimeoutCallback() {
// Set the connectivity lost callback.
DatabaseConnection::db_lost_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
// Set the connectivity recovered callback.
DatabaseConnection::db_recovered_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
// Set the connectivity failed callback.
DatabaseConnection::db_failed_callback_ =
std::bind(&LeaseMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
std::string access = invalidConnectString();
std::string extra = " max-reconnect-tries=3 reconnect-wait-time=1 retry-on-startup=true";
access += extra;
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
std::shared_ptr<DbConnectionInitWithRetry> dbr(new DbConnectionInitWithRetry);
// Connect to the lease backend.
ASSERT_THROW(LeaseMgrFactory::create(access), DbOpenErrorWithRetry);
dbr.reset();
ASSERT_FALSE(LeaseMgrFactory::haveInstance());
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(1, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
sleep(1);
io_service_->poll();
// Our lost connectivity callback should have been invoked.
EXPECT_EQ(2, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(0, db_failed_callback_called_);
ASSERT_FALSE(LeaseMgrFactory::haveInstance());
sleep(1);
io_service_->poll();
// Our lost and failed connectivity callback should have been invoked.
EXPECT_EQ(3, db_lost_callback_called_);
EXPECT_EQ(0, db_recovered_callback_called_);
EXPECT_EQ(1, db_failed_callback_called_);
ASSERT_FALSE(LeaseMgrFactory::haveInstance());
}
void void
LeaseMgrDbLostCallbackTest::testNoCallbackOnOpenFailure() { LeaseMgrDbLostCallbackTest::testNoCallbackOnOpenFailure() {
DatabaseConnection::db_lost_callback_ = DatabaseConnection::db_lost_callback_ =

View File

@ -8,6 +8,7 @@
#define GENERIC_LEASE_MGR_UNITTEST_H #define GENERIC_LEASE_MGR_UNITTEST_H
#include <asiolink/io_service.h> #include <asiolink/io_service.h>
#include <database/database_connection.h>
#include <dhcpsrv/tracking_lease_mgr.h> #include <dhcpsrv/tracking_lease_mgr.h>
#include <dhcpsrv/timer_mgr.h> #include <dhcpsrv/timer_mgr.h>
@ -682,7 +683,7 @@ public:
db::DatabaseConnection::db_lost_callback_ = 0; db::DatabaseConnection::db_lost_callback_ = 0;
db::DatabaseConnection::db_recovered_callback_ = 0; db::DatabaseConnection::db_recovered_callback_ = 0;
db::DatabaseConnection::db_failed_callback_ = 0; db::DatabaseConnection::db_failed_callback_ = 0;
LeaseMgr::setIOService(io_service_); db::DatabaseConnection::setIOService(io_service_);
TimerMgr::instance()->setIOService(io_service_); TimerMgr::instance()->setIOService(io_service_);
} }
@ -690,7 +691,7 @@ public:
db::DatabaseConnection::db_lost_callback_ = 0; db::DatabaseConnection::db_lost_callback_ = 0;
db::DatabaseConnection::db_recovered_callback_ = 0; db::DatabaseConnection::db_recovered_callback_ = 0;
db::DatabaseConnection::db_failed_callback_ = 0; db::DatabaseConnection::db_failed_callback_ = 0;
LeaseMgr::setIOService(isc::asiolink::IOServicePtr()); db::DatabaseConnection::setIOService(isc::asiolink::IOServicePtr());
TimerMgr::instance()->unregisterTimers(); TimerMgr::instance()->unregisterTimers();
} }
@ -720,6 +721,50 @@ public:
/// string /// string
virtual std::string invalidConnectString() = 0; virtual std::string invalidConnectString() = 0;
/// @brief Verifies the lease manager's behavior if DB connection can not be
/// established but succeeds on retry
///
/// This function creates a lease manager with a back end that supports
/// connectivity lost callback (currently only MySQL and PostgreSQL). It
/// verifies that connectivity is unavailable and then recovered on retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbRecoveredCallback was invoked
void testRetryOpenDbLostAndRecoveredCallback();
/// @brief Verifies the lease manager's behavior if DB connection can not be
/// established but fails on retry
///
/// This function creates a lease manager with a back end that supports
/// connectivity lost callback (currently only MySQL and PostgreSQL). It
/// It verifies that connectivity is unavailable and then fails again on
/// retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbFailedCallback was invoked
void testRetryOpenDbLostAndFailedCallback();
/// @brief Verifies the lease manager's behavior if DB connection can not be
/// established but succeeds on retry
///
/// This function creates a lease manager with a back end that supports
/// connectivity lost callback (currently only MySQL and PostgreSQL). It
/// verifies that connectivity is unavailable and then recovered on retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbRecoveredCallback was invoked after two reconnect
/// attempts (once failing and second triggered by timer)
void testRetryOpenDbLostAndRecoveredAfterTimeoutCallback();
/// @brief Verifies the lease manager's behavior if DB connection can not be
/// established but fails on retry
///
/// This function creates a lease manager with a back end that supports
/// connectivity lost callback (currently only MySQL and PostgreSQL). It
/// It verifies that connectivity is unavailable and then fails again on
/// retry:
/// -# The registered DbLostCallback was invoked
/// -# The registered DbFailedCallback was invoked after two reconnect
/// attempts (once failing and second triggered by timer)
void testRetryOpenDbLostAndFailedAfterTimeoutCallback();
/// @brief Verifies open failures do NOT invoke db lost callback /// @brief Verifies open failures do NOT invoke db lost callback
/// ///
/// The db lost callback should only be invoked after successfully /// The db lost callback should only be invoked after successfully

View File

@ -88,7 +88,7 @@ public:
/// @brief Sets IO service to be used by the Timer Manager. /// @brief Sets IO service to be used by the Timer Manager.
/// ///
/// @param io_service Pointer to the new IO service. /// @param io_service Pointer to the IO service.
void setIOService(const IOServicePtr& io_service); void setIOService(const IOServicePtr& io_service);
/// @brief Registers new timer in the @c TimerMgr. /// @brief Registers new timer in the @c TimerMgr.
@ -107,7 +107,6 @@ public:
const long interval, const long interval,
const asiolink::IntervalTimer::Mode& scheduling_mode); const asiolink::IntervalTimer::Mode& scheduling_mode);
/// @brief Unregisters specified timer. /// @brief Unregisters specified timer.
/// ///
/// This method cancels the timer if it is setup and removes the timer /// This method cancels the timer if it is setup and removes the timer
@ -176,7 +175,6 @@ private:
const long interval, const long interval,
const asiolink::IntervalTimer::Mode& scheduling_mode); const asiolink::IntervalTimer::Mode& scheduling_mode);
/// @brief Unregisters specified timer. /// @brief Unregisters specified timer.
/// ///
/// This method cancels the timer if it is setup and removes the timer /// This method cancels the timer if it is setup and removes the timer

View File

@ -73,7 +73,7 @@ public:
/// @brief Sets IO service to be used by the Timer Manager. /// @brief Sets IO service to be used by the Timer Manager.
/// ///
/// @param io_service Pointer to the new IO service. /// @param io_service Pointer to the IO service.
void setIOService(const asiolink::IOServicePtr& io_service); void setIOService(const asiolink::IOServicePtr& io_service);
/// @name Registering, unregistering and scheduling the timers. /// @name Registering, unregistering and scheduling the timers.

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <database/database_connection.h>
#include <database/db_log.h> #include <database/db_log.h>
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
#include <mysql/mysql_connection.h> #include <mysql/mysql_connection.h>
@ -243,7 +244,23 @@ MySqlConnection::openDatabase() {
MYSQL* status = mysql_real_connect(mysql_, host, user, password, name, MYSQL* status = mysql_real_connect(mysql_, host, user, password, name,
port, NULL, CLIENT_FOUND_ROWS); port, NULL, CLIENT_FOUND_ROWS);
if (status != mysql_) { if (status != mysql_) {
isc_throw(DbOpenError, mysql_error(mysql_)); std::string error_message = mysql_error(mysql_);
auto const& rec = reconnectCtl();
if (rec && DatabaseConnection::retry_) {
// Start the connection recovery.
startRecoverDbConnection();
std::ostringstream s;
s << " (scheduling retry " << rec->retriesLeft() << " in " << rec->retryInterval() << " milliseconds)";
error_message += s.str();
isc_throw(DbOpenErrorWithRetry, error_message);
}
isc_throw(DbOpenError, error_message);
} }
// Enable autocommit. In case transaction is explicitly used, this // Enable autocommit. In case transaction is explicitly used, this
@ -268,9 +285,16 @@ MySqlConnection::openDatabase() {
// Get schema version. // Get schema version.
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
MySqlConnection::getVersion(const ParameterMap& parameters) { MySqlConnection::getVersion(const ParameterMap& parameters,
const IOServiceAccessorPtr& ac,
const DbCallback& cb,
const string& timer_name) {
// Get a connection. // Get a connection.
MySqlConnection conn(parameters); MySqlConnection conn(parameters, ac, cb);
if (!timer_name.empty()) {
conn.makeReconnectCtl(timer_name);
}
// Open the database. // Open the database.
conn.openDatabase(); conn.openDatabase();

View File

@ -260,6 +260,9 @@ public:
/// ///
/// @param parameters A data structure relating keywords and values /// @param parameters A data structure relating keywords and values
/// concerned with the database. /// concerned with the database.
/// @param ac An IOServiceAccessor object.
/// @param cb The dbReconnect callback.
/// @param timer_name The DB reconnect timer name.
/// ///
/// @return Version number as a pair of unsigned integers. "first" is the /// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number. /// major version number, "second" the minor number.
@ -267,7 +270,10 @@ public:
/// @throw isc::db::DbOperationError An operation on the open database has /// @throw isc::db::DbOperationError An operation on the open database has
/// failed. /// failed.
static std::pair<uint32_t, uint32_t> static std::pair<uint32_t, uint32_t>
getVersion(const ParameterMap& parameters); getVersion(const ParameterMap& parameters,
const IOServiceAccessorPtr& ac = IOServiceAccessorPtr(),
const DbCallback& cb = DbCallback(),
const std::string& timer_name = "");
/// @brief Prepare Single Statement /// @brief Prepare Single Statement
/// ///

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <database/database_connection.h>
#include <database/db_exceptions.h> #include <database/db_exceptions.h>
#include <database/db_log.h> #include <database/db_log.h>
#include <pgsql/pgsql_connection.h> #include <pgsql/pgsql_connection.h>
@ -134,9 +135,16 @@ PgSqlConnection::~PgSqlConnection() {
} }
std::pair<uint32_t, uint32_t> std::pair<uint32_t, uint32_t>
PgSqlConnection::getVersion(const ParameterMap& parameters) { PgSqlConnection::getVersion(const ParameterMap& parameters,
const IOServiceAccessorPtr& ac,
const DbCallback& cb,
const string& timer_name) {
// Get a connection. // Get a connection.
PgSqlConnection conn(parameters); PgSqlConnection conn(parameters, ac, cb);
if (!timer_name.empty()) {
conn.makeReconnectCtl(timer_name);
}
// Open the database. // Open the database.
conn.openDatabaseInternal(false); conn.openDatabaseInternal(false);
@ -294,6 +302,21 @@ PgSqlConnection::openDatabaseInternal(bool logging) {
// to release it, but grab the error message first. // to release it, but grab the error message first.
std::string error_message = PQerrorMessage(new_conn); std::string error_message = PQerrorMessage(new_conn);
PQfinish(new_conn); PQfinish(new_conn);
auto const& rec = reconnectCtl();
if (rec && DatabaseConnection::retry_) {
// Start the connection recovery.
startRecoverDbConnection();
std::ostringstream s;
s << " (scheduling retry " << rec->retriesLeft() << " in " << rec->retryInterval() << " milliseconds)";
error_message += s.str();
isc_throw(DbOpenErrorWithRetry, error_message);
}
isc_throw(DbOpenError, error_message); isc_throw(DbOpenError, error_message);
} }

View File

@ -230,6 +230,9 @@ public:
/// ///
/// @param parameters A data structure relating keywords and values /// @param parameters A data structure relating keywords and values
/// concerned with the database. /// concerned with the database.
/// @param ac An IOServiceAccessor object.
/// @param cb The dbReconnect callback.
/// @param timer_name The DB reconnect timer name.
/// ///
/// @return Version number as a pair of unsigned integers. "first" is the /// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number. /// major version number, "second" the minor number.
@ -237,7 +240,10 @@ public:
/// @throw isc::db::DbOperationError An operation on the open database has /// @throw isc::db::DbOperationError An operation on the open database has
/// failed. /// failed.
static std::pair<uint32_t, uint32_t> static std::pair<uint32_t, uint32_t>
getVersion(const ParameterMap& parameters); getVersion(const ParameterMap& parameters,
const IOServiceAccessorPtr& ac = IOServiceAccessorPtr(),
const DbCallback& cb = DbCallback(),
const std::string& timer_name = "");
/// @brief Prepare Single Statement /// @brief Prepare Single Statement
/// ///

View File

@ -9,6 +9,7 @@
#include <database/audit_entry.h> #include <database/audit_entry.h>
#include <database/backend_selector.h> #include <database/backend_selector.h>
#include <database/database_connection.h>
#include <database/server_selector.h> #include <database/server_selector.h>
#include <process/config_base.h> #include <process/config_base.h>
#include <process/config_ctl_info.h> #include <process/config_ctl_info.h>
@ -142,9 +143,15 @@ public:
// Iterate over the configured DBs and instantiate them. // Iterate over the configured DBs and instantiate them.
for (auto db : config_ctl->getConfigDatabases()) { for (auto db : config_ctl->getConfigDatabases()) {
const std::string& redacted = db.redactedAccessString();
LOG_INFO(dctl_logger, DCTL_OPEN_CONFIG_DB) LOG_INFO(dctl_logger, DCTL_OPEN_CONFIG_DB)
.arg(db.redactedAccessString()); .arg(redacted);
try {
getMgr().addBackend(db.getAccessString()); getMgr().addBackend(db.getAccessString());
} catch (const isc::db::DbOpenErrorWithRetry& err) {
LOG_INFO(dctl_logger, DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED)
.arg(redacted).arg(err.what());
}
} }
// Let the caller know we have opened DBs. // Let the caller know we have opened DBs.

View File

@ -21,6 +21,7 @@ extern const isc::log::MessageID DCTL_CONFIG_LOAD_FAIL = "DCTL_CONFIG_LOAD_FAIL"
extern const isc::log::MessageID DCTL_CONFIG_START = "DCTL_CONFIG_START"; extern const isc::log::MessageID DCTL_CONFIG_START = "DCTL_CONFIG_START";
extern const isc::log::MessageID DCTL_CONFIG_STUB = "DCTL_CONFIG_STUB"; extern const isc::log::MessageID DCTL_CONFIG_STUB = "DCTL_CONFIG_STUB";
extern const isc::log::MessageID DCTL_CONFIG_UPDATE = "DCTL_CONFIG_UPDATE"; extern const isc::log::MessageID DCTL_CONFIG_UPDATE = "DCTL_CONFIG_UPDATE";
extern const isc::log::MessageID DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED = "DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED";
extern const isc::log::MessageID DCTL_DEVELOPMENT_VERSION = "DCTL_DEVELOPMENT_VERSION"; extern const isc::log::MessageID DCTL_DEVELOPMENT_VERSION = "DCTL_DEVELOPMENT_VERSION";
extern const isc::log::MessageID DCTL_INIT_PROCESS = "DCTL_INIT_PROCESS"; extern const isc::log::MessageID DCTL_INIT_PROCESS = "DCTL_INIT_PROCESS";
extern const isc::log::MessageID DCTL_INIT_PROCESS_FAIL = "DCTL_INIT_PROCESS_FAIL"; extern const isc::log::MessageID DCTL_INIT_PROCESS_FAIL = "DCTL_INIT_PROCESS_FAIL";
@ -58,12 +59,13 @@ const char* values[] = {
"DCTL_CONFIG_START", "parsing new configuration: %1", "DCTL_CONFIG_START", "parsing new configuration: %1",
"DCTL_CONFIG_STUB", "%1 configuration stub handler called", "DCTL_CONFIG_STUB", "%1 configuration stub handler called",
"DCTL_CONFIG_UPDATE", "%1 updated configuration received: %2", "DCTL_CONFIG_UPDATE", "%1 updated configuration received: %2",
"DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED", "Failed to connect to database: %1 with error: %2",
"DCTL_DEVELOPMENT_VERSION", "This software is a development branch of Kea. It is not recommended for production use.", "DCTL_DEVELOPMENT_VERSION", "This software is a development branch of Kea. It is not recommended for production use.",
"DCTL_INIT_PROCESS", "%1 initializing the application", "DCTL_INIT_PROCESS", "%1 initializing the application",
"DCTL_INIT_PROCESS_FAIL", "%1 application initialization failed: %2", "DCTL_INIT_PROCESS_FAIL", "%1 application initialization failed: %2",
"DCTL_NOT_RUNNING", "%1 application instance is not running", "DCTL_NOT_RUNNING", "%1 application instance is not running",
"DCTL_OPEN_CONFIG_DB", "Opening configuration database: %1", "DCTL_OPEN_CONFIG_DB", "Opening configuration database: %1",
"DCTL_PARSER_FAIL", ": %1", "DCTL_PARSER_FAIL", "Parser error: %1",
"DCTL_PID_FILE_ERROR", "%1 could not create a PID file: %2", "DCTL_PID_FILE_ERROR", "%1 could not create a PID file: %2",
"DCTL_PROCESS_FAILED", "%1 application execution failed: %2", "DCTL_PROCESS_FAILED", "%1 application execution failed: %2",
"DCTL_RUN_PROCESS", "%1 starting application event loop", "DCTL_RUN_PROCESS", "%1 starting application event loop",

View File

@ -22,6 +22,7 @@ extern const isc::log::MessageID DCTL_CONFIG_LOAD_FAIL;
extern const isc::log::MessageID DCTL_CONFIG_START; extern const isc::log::MessageID DCTL_CONFIG_START;
extern const isc::log::MessageID DCTL_CONFIG_STUB; extern const isc::log::MessageID DCTL_CONFIG_STUB;
extern const isc::log::MessageID DCTL_CONFIG_UPDATE; extern const isc::log::MessageID DCTL_CONFIG_UPDATE;
extern const isc::log::MessageID DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED;
extern const isc::log::MessageID DCTL_DEVELOPMENT_VERSION; extern const isc::log::MessageID DCTL_DEVELOPMENT_VERSION;
extern const isc::log::MessageID DCTL_INIT_PROCESS; extern const isc::log::MessageID DCTL_INIT_PROCESS;
extern const isc::log::MessageID DCTL_INIT_PROCESS_FAIL; extern const isc::log::MessageID DCTL_INIT_PROCESS_FAIL;

View File

@ -96,7 +96,13 @@ This message is printed when the Kea server is attempting to open a
configuration database. The database access string with password redacted configuration database. The database access string with password redacted
is logged. is logged.
% DCTL_PARSER_FAIL : %1 % DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED Failed to connect to database: %1 with error: %2
This is an informational message issued when the the server failed to connect to
the configuration database. The operation started a retry to connect procedure.
The database access string with password redacted is logged, along with the
error and details for the reconnect procedure.
% DCTL_PARSER_FAIL Parser error: %1
On receipt of a new configuration, the server failed to create a parser to On receipt of a new configuration, the server failed to create a parser to
decode the contents of the named configuration element, or the creation decode the contents of the named configuration element, or the creation
succeeded but the parsing actions and committal of changes failed. succeeded but the parsing actions and committal of changes failed.