]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3727] fixed db recovery
authorRazvan Becheriu <razvan@isc.org>
Fri, 24 Jan 2025 18:11:12 +0000 (20:11 +0200)
committerRazvan Becheriu <razvan@isc.org>
Mon, 27 Jan 2025 07:26:50 +0000 (09:26 +0200)
23 files changed:
src/bin/dhcp4/ctrl_dhcp4_srv.cc
src/bin/dhcp6/ctrl_dhcp6_srv.cc
src/hooks/dhcp/mysql/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql/mysql_cb_dhcp6.cc
src/hooks/dhcp/mysql/mysql_cb_impl.cc
src/hooks/dhcp/mysql/mysql_host_data_source.cc
src/hooks/dhcp/mysql/mysql_lease_mgr.cc
src/hooks/dhcp/pgsql/pgsql_cb_dhcp4.cc
src/hooks/dhcp/pgsql/pgsql_cb_dhcp6.cc
src/hooks/dhcp/pgsql/pgsql_cb_impl.cc
src/hooks/dhcp/pgsql/pgsql_host_data_source.cc
src/hooks/dhcp/pgsql/pgsql_lease_mgr.cc
src/lib/database/database_connection.cc
src/lib/database/database_connection.h
src/lib/database/tests/database_connection_unittest.cc
src/lib/dhcpsrv/cfg_iface.cc
src/lib/dhcpsrv/network_state.cc
src/lib/dhcpsrv/network_state.h
src/lib/mysql/mysql_connection.cc
src/lib/mysql/mysql_connection.h
src/lib/pgsql/pgsql_connection.cc
src/lib/pgsql/pgsql_connection.h
src/lib/util/reconnect_ctl.h

index 1ae29a37028e38eccad15cabbb99565bdb1283e2..b8ef7da76f06ad5d211595401759f9a1b067dcd8 100644 (file)
@@ -1639,7 +1639,7 @@ ControlledDhcpv4Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
     // Disable service until the connection is recovered.
     if (db_reconnect_ctl->retriesLeft() == db_reconnect_ctl->maxRetries() &&
         db_reconnect_ctl->alterServiceState()) {
-        network_state_->disableService(NetworkState::DB_CONNECTION);
+        network_state_->disableService(NetworkState::DB_CONNECTION + db_reconnect_ctl->id());
     }
 
     LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_LOST_CONNECTION);
@@ -1669,8 +1669,9 @@ ControlledDhcpv4Srv::dbRecoveredCallback(ReconnectCtlPtr db_reconnect_ctl) {
     }
 
     // Enable service after the connection is recovered.
-    if (db_reconnect_ctl->alterServiceState()) {
-        network_state_->enableService(NetworkState::DB_CONNECTION);
+    if (db_reconnect_ctl->retriesLeft() != db_reconnect_ctl->maxRetries() &&
+        db_reconnect_ctl->alterServiceState()) {
+        network_state_->enableService(NetworkState::DB_CONNECTION + db_reconnect_ctl->id());
     }
 
     LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_SUCCEEDED);
index ebac21c1d7e8b24e37bf06de9a6f2ca226ae4f0e..3cd3e249c1b2bf77ac94c02ce4d626412369f728 100644 (file)
@@ -1425,7 +1425,7 @@ ControlledDhcpv6Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
     // Disable service until the connection is recovered.
     if (db_reconnect_ctl->retriesLeft() == db_reconnect_ctl->maxRetries() &&
         db_reconnect_ctl->alterServiceState()) {
-        network_state_->disableService(NetworkState::DB_CONNECTION);
+        network_state_->disableService(NetworkState::DB_CONNECTION + db_reconnect_ctl->id());
     }
 
     LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_LOST_CONNECTION);
@@ -1455,8 +1455,9 @@ ControlledDhcpv6Srv::dbRecoveredCallback(ReconnectCtlPtr db_reconnect_ctl) {
     }
 
     // Enable service after the connection is recovered.
-    if (db_reconnect_ctl->alterServiceState()) {
-        network_state_->enableService(NetworkState::DB_CONNECTION);
+    if (db_reconnect_ctl->retriesLeft() != db_reconnect_ctl->maxRetries() &&
+        db_reconnect_ctl->alterServiceState()) {
+        network_state_->enableService(NetworkState::DB_CONNECTION + db_reconnect_ctl->id());
     }
 
     LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_SUCCEEDED);
index 78dd421a9fcb61a955526ddbf87cdeac8f50c670..544de16915e8fab3d5ec7f95a612da132e1ddee0 100644 (file)
@@ -2917,6 +2917,7 @@ public:
         bool do_exit = false;
 
         const std::string timer_name = db_reconnect_ctl->timerName();
+        bool check = db_reconnect_ctl->checkRetries();
 
         // At least one connection was lost.
         try {
@@ -2959,7 +2960,7 @@ public:
                 return (false);
             }
         } else {
-            if (!db_reconnect_ctl->checkRetries()) {
+            if (!check) {
                 // We're out of retries, log it and initiate shutdown.
                 LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_FAILED4)
                         .arg(db_reconnect_ctl->maxRetries());
index 3d2bd8bb697f9c654988440023604c91a9f68cc5..0ec3fde9738fa93d9154a30f84f134ab4bf00453 100644 (file)
@@ -3309,6 +3309,7 @@ public:
         bool do_exit = false;
 
         const std::string timer_name = db_reconnect_ctl->timerName();
+        bool check = db_reconnect_ctl->checkRetries();
 
         // At least one connection was lost.
         try {
@@ -3351,7 +3352,7 @@ public:
                 return (false);
             }
         } else {
-            if (!db_reconnect_ctl->checkRetries()) {
+            if (!check) {
                 // We're out of retries, log it and initiate shutdown.
                 LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_FAILED6)
                         .arg(db_reconnect_ctl->maxRetries());
index 9c7dd8ad1ce262bb3c0de70def9b35946fa5a4cc..62747c29acb33093e6ca7eeb19524d71417a6c75 100644 (file)
@@ -11,6 +11,7 @@
 #include <asiolink/io_address.h>
 #include <config_backend/constants.h>
 #include <dhcp/option_space.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <util/buffer.h>
 
@@ -68,7 +69,7 @@ MySqlConfigBackendImpl(const std::string& space,
     MySqlConnection::ensureSchemaVersion(parameters, db_reconnect_callback, timer_name_);
 
     // Create ReconnectCtl for this connection.
-    conn_.makeReconnectCtl(timer_name_);
+    conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 21);
 
     // Open the database.
     conn_.openDatabase();
index 7dcc08d3a91e24ae86ef7089c6ecdc2ab0880287..2ef0fcb0aed16e657cc2ef3daf5edaf95c8e3014 100644 (file)
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/host_mgr.h>
+#include <dhcpsrv/network_state.h>
+#include <dhcpsrv/timer_mgr.h>
 #include <mysql_hb_log.h>
 #include <mysql_host_data_source.h>
-#include <dhcpsrv/timer_mgr.h>
 #include <util/buffer.h>
 #include <util/multi_threading_mgr.h>
 #include <util/optional.h>
@@ -3020,7 +3021,7 @@ MySqlHostDataSourceImpl::createContext() const {
     ctx->host_option_exchange_.reset(new MySqlOptionExchange());
 
     // Create ReconnectCtl for this connection.
-    ctx->conn_.makeReconnectCtl(timer_name_);
+    ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 11);
 
     return (ctx);
 }
@@ -3040,6 +3041,7 @@ MySqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
     bool reopened = false;
 
     const std::string timer_name = db_reconnect_ctl->timerName();
+    bool check = db_reconnect_ctl->checkRetries();
 
     // At least one connection was lost.
     try {
@@ -3068,7 +3070,7 @@ MySqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
             return (false);
         }
     } else {
-        if (!db_reconnect_ctl->checkRetries()) {
+        if (!check) {
             // We're out of retries, log it and initiate shutdown.
             LOG_ERROR(mysql_hb_logger, MYSQL_HB_DB_RECONNECT_FAILED)
                     .arg(db_reconnect_ctl->maxRetries());
@@ -3108,7 +3110,7 @@ MySqlHostDataSourceImpl::getVersion(const std::string& timer_name) const {
     IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
     DbCallback cb(&MySqlHostDataSourceImpl::dbReconnect);
 
-    return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name));
+    return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name, NetworkState::DB_CONNECTION + 11));
 }
 
 void
@@ -4170,7 +4172,7 @@ MySqlHostDataSource::getDescription() const {
 
 std::pair<uint32_t, uint32_t>
 MySqlHostDataSource::getVersion(const std::string& timer_name) const {
-    return(impl_->getVersion(timer_name));
+    return (impl_->getVersion(timer_name));
 }
 
 void
index 2603e076441f5890501ad636af715f4a76d59ac8..a6290558cd74154bea9a3777e90581e3e858c00e 100644 (file)
@@ -13,6 +13,7 @@
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <mysql_lb_log.h>
 #include <mysql_lease_mgr.h>
@@ -2205,6 +2206,7 @@ MySqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
     bool reopened = false;
 
     const std::string timer_name = db_reconnect_ctl->timerName();
+    bool check = db_reconnect_ctl->checkRetries();
 
     // At least one connection was lost.
     try {
@@ -2227,7 +2229,7 @@ MySqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
             return (false);
         }
     } else {
-        if (!db_reconnect_ctl->checkRetries()) {
+        if (!check) {
             // We're out of retries, log it and initiate shutdown.
             LOG_ERROR(mysql_lb_logger, MYSQL_LB_DB_RECONNECT_FAILED)
                     .arg(db_reconnect_ctl->maxRetries());
@@ -2269,7 +2271,7 @@ MySqlLeaseMgr::createContext() const {
         &MySqlLeaseMgr::dbReconnect));
 
     // Create ReconnectCtl for this connection.
-    ctx->conn_.makeReconnectCtl(timer_name_);
+    ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 1);
 
     // Open the database.
     ctx->conn_.openDatabase();
@@ -3863,7 +3865,7 @@ MySqlLeaseMgr::getVersion(const string& timer_name) const {
     IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
     DbCallback cb(&MySqlLeaseMgr::dbReconnect);
 
-    return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name));
+    return (MySqlConnection::getVersion(parameters_, ac, cb, timer_name, NetworkState::DB_CONNECTION + 1));
 }
 
 void
index 365477f2be5e1b9e154290f2bc3a98e0ca0997b2..8b88b4a59283b1e1bc90ec08e5e8a26f23133d3c 100644 (file)
@@ -2755,6 +2755,7 @@ public:
         bool do_exit = false;
 
         const std::string timer_name = db_reconnect_ctl->timerName();
+        bool check = db_reconnect_ctl->checkRetries();
 
         // At least one connection was lost.
         try {
@@ -2797,7 +2798,7 @@ public:
                 return (false);
             }
         } else {
-            if (!db_reconnect_ctl->checkRetries()) {
+            if (!check) {
                 // We're out of retries, log it and initiate shutdown.
                 LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_FAILED4)
                         .arg(db_reconnect_ctl->maxRetries());
index fe5d519a91af5b73b9737acc07e55eb4a3a6dd4b..b668d0fa835fed731509b9538a66f19fa5ed7bd4 100644 (file)
@@ -3073,6 +3073,7 @@ public:
         bool do_exit = false;
 
         const std::string timer_name = db_reconnect_ctl->timerName();
+        bool check = db_reconnect_ctl->checkRetries();
 
         // At least one connection was lost.
         try {
@@ -3115,7 +3116,7 @@ public:
                 return (false);
             }
         } else {
-            if (!db_reconnect_ctl->checkRetries()) {
+            if (!check) {
                 // We're out of retries, log it and initiate shutdown.
                 LOG_ERROR(pgsql_cb_logger, PGSQL_CB_RECONNECT_FAILED6)
                         .arg(db_reconnect_ctl->maxRetries());
index 1194236a9e2d0deb27e6fd1d0539341318c540bf..12e3575824e9a8bfb654d2a6230e7eadd1dbaf3f 100644 (file)
@@ -10,6 +10,7 @@
 #include <config_backend/constants.h>
 #include <database/db_exceptions.h>
 #include <dhcp/option_space.h>
+#include <dhcpsrv/network_state.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <pgsql/pgsql_exchange.h>
 #include <util/buffer.h>
@@ -113,7 +114,7 @@ PgSqlConfigBackendImpl::PgSqlConfigBackendImpl(const std::string& space,
     PgSqlConnection::ensureSchemaVersion(parameters, db_reconnect_callback, timer_name_);
 
     // Create ReconnectCtl for this connection.
-    conn_.makeReconnectCtl(timer_name_);
+    conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 22);
 
     // Open the database.
     conn_.openDatabase();
index 4201241151742694146009fa096cdd528b7ca7ce..c947279cb675f40cc83c395432b705d56fb177b0 100644 (file)
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/host_mgr.h>
+#include <dhcpsrv/network_state.h>
+#include <dhcpsrv/timer_mgr.h>
 #include <pgsql_hb_log.h>
 #include <pgsql_host_data_source.h>
-#include <dhcpsrv/timer_mgr.h>
 #include <util/buffer.h>
 #include <util/multi_threading_mgr.h>
 #include <util/optional.h>
@@ -2386,7 +2387,7 @@ PgSqlHostDataSourceImpl::createContext() const {
     ctx->host_option_exchange_.reset(new PgSqlOptionExchange());
 
     // Create ReconnectCtl for this connection.
-    ctx->conn_.makeReconnectCtl(timer_name_);
+    ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 12);
 
     return (ctx);
 }
@@ -2406,6 +2407,7 @@ PgSqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
     bool reopened = false;
 
     const std::string timer_name = db_reconnect_ctl->timerName();
+    bool check = db_reconnect_ctl->checkRetries();
 
     // At least one connection was lost.
     try {
@@ -2434,7 +2436,7 @@ PgSqlHostDataSourceImpl::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
             return (false);
         }
     } else {
-        if (!db_reconnect_ctl->checkRetries()) {
+        if (!check) {
             // We're out of retries, log it and initiate shutdown.
             LOG_ERROR(pgsql_hb_logger, PGSQL_HB_DB_RECONNECT_FAILED)
                     .arg(db_reconnect_ctl->maxRetries());
@@ -2660,7 +2662,7 @@ PgSqlHostDataSourceImpl::getVersion(const std::string& timer_name) const {
     IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
     DbCallback cb(&PgSqlHostDataSourceImpl::dbReconnect);
 
-    return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name));
+    return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name, NetworkState::DB_CONNECTION + 12));
 }
 
 void
@@ -3339,7 +3341,7 @@ PgSqlHostDataSource::getDescription() const {
 
 std::pair<uint32_t, uint32_t>
 PgSqlHostDataSource::getVersion(const std::string& timer_name) const {
-    return(impl_->getVersion(timer_name));
+    return (impl_->getVersion(timer_name));
 }
 
 void
index f0be9d0b7c8e02ab1dc0be64ac0a2aec855b535f..1f7a603d82ff7e60c2f53d3a21d4b7123837e4a2 100644 (file)
@@ -14,6 +14,7 @@
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/dhcpsrv_exceptions.h>
 #include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/network_state.h>
 #include <pgsql_lb_log.h>
 #include <pgsql_lease_mgr.h>
 #include <dhcpsrv/timer_mgr.h>
@@ -1668,6 +1669,7 @@ PgSqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
     bool reopened = false;
 
     const std::string timer_name = db_reconnect_ctl->timerName();
+    bool check = db_reconnect_ctl->checkRetries();
 
     // At least one connection was lost.
     try {
@@ -1690,7 +1692,7 @@ PgSqlLeaseMgr::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
             return (false);
         }
     } else {
-        if (!db_reconnect_ctl->checkRetries()) {
+        if (!check) {
             // We're out of retries, log it and initiate shutdown.
             LOG_ERROR(pgsql_lb_logger, PGSQL_LB_DB_RECONNECT_FAILED)
                     .arg(db_reconnect_ctl->maxRetries());
@@ -1732,7 +1734,7 @@ PgSqlLeaseMgr::createContext() const {
         &PgSqlLeaseMgr::dbReconnect));
 
     // Create ReconnectCtl for this connection.
-    ctx->conn_.makeReconnectCtl(timer_name_);
+    ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 2);
 
     // Open the database.
     ctx->conn_.openDatabase();
@@ -3032,7 +3034,7 @@ PgSqlLeaseMgr::getVersion(const string& timer_name) const {
     IOServiceAccessorPtr ac(new IOServiceAccessor(&DatabaseConnection::getIOService));
     DbCallback cb(&PgSqlLeaseMgr::dbReconnect);
 
-    return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name));
+    return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name, NetworkState::DB_CONNECTION + 2));
 }
 
 void
index 99a0bdf7b071c9f18744a97774af6235c85542ad..4b1ff0d288bf224f45d7f4f1affaa44c6792afdb 100644 (file)
@@ -148,7 +148,7 @@ DatabaseConnection::configuredReadOnly() const {
 }
 
 void
-DatabaseConnection::makeReconnectCtl(const std::string& timer_name) {
+DatabaseConnection::makeReconnectCtl(const std::string& timer_name, unsigned int id) {
     string type = "unknown";
     unsigned int retries = 0;
     unsigned int interval = 0;
@@ -184,7 +184,7 @@ DatabaseConnection::makeReconnectCtl(const std::string& timer_name) {
     }
 
     reconnect_ctl_ = boost::make_shared<ReconnectCtl>(type, timer_name, retries,
-                                                      interval, action);
+                                                      interval, action, id);
 }
 
 bool
index 80ed1ac4ff91d0231f452eddc6983100c2366aaa..1c84c3adf2dd37bd042447b35eab4332e873b07b 100644 (file)
@@ -153,7 +153,7 @@ public:
     /// reconnect parameters
     ///
     /// @param timer_name of the timer used for the ReconnectCtl object.
-    virtual void makeReconnectCtl(const std::string& timer_name);
+    virtual void makeReconnectCtl(const std::string& timer_name, unsigned int id);
 
     /// @brief The reconnect settings.
     ///
index de1ae2d72d5ec2eb2c96b4db37dddb70c0aa01f5..419200af8856490470084b2ac12639357a2a0101 100644 (file)
@@ -108,7 +108,7 @@ TEST_F(DatabaseConnectionCallbackTest, NoDbLostCallback) {
     pmap[std::string("max-reconnect-tries")] = std::string("3");
     pmap[std::string("reconnect-wait-time")] = std::string("60000");
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
 
     bool ret = false;
     ASSERT_NO_THROW(ret = DatabaseConnection::invokeDbLostCallback(datasrc.reconnectCtl()));
@@ -126,7 +126,7 @@ TEST_F(DatabaseConnectionCallbackTest, NoDbRecoveredCallback) {
     pmap[std::string("max-reconnect-tries")] = std::string("3");
     pmap[std::string("reconnect-wait-time")] = std::string("60000");
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
 
     bool ret = false;
     ASSERT_NO_THROW(ret = DatabaseConnection::invokeDbRecoveredCallback(datasrc.reconnectCtl()));
@@ -144,7 +144,7 @@ TEST_F(DatabaseConnectionCallbackTest, NoDbFailedCallback) {
     pmap[std::string("max-reconnect-tries")] = std::string("3");
     pmap[std::string("reconnect-wait-time")] = std::string("60000");
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
 
     bool ret = false;
     ASSERT_NO_THROW(ret = DatabaseConnection::invokeDbFailedCallback(datasrc.reconnectCtl()));
@@ -170,7 +170,7 @@ TEST_F(DatabaseConnectionCallbackTest, dbLostCallback) {
         std::bind(&DatabaseConnectionCallbackTest::dbLostCallback, this, ph::_1);
     /// Create the connection..
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
     bool ret = false;
 
     /// We should be able to invoke the callback and get
@@ -218,7 +218,7 @@ TEST_F(DatabaseConnectionCallbackTest, dbRecoveredCallback) {
         std::bind(&DatabaseConnectionCallbackTest::dbRecoveredCallback, this, ph::_1);
     /// Create the connection..
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
     bool ret = false;
 
     /// We should be able to invoke the callback and get
@@ -281,7 +281,7 @@ TEST_F(DatabaseConnectionCallbackTest, dbFailedCallback) {
         std::bind(&DatabaseConnectionCallbackTest::dbFailedCallback, this, ph::_1);
     /// Create the connection..
     DatabaseConnection datasrc(pmap);
-    datasrc.makeReconnectCtl("timer");
+    datasrc.makeReconnectCtl("timer", 0);
     bool ret = false;
 
     /// We should be able to invoke the callback and get
index 3991e223962158a96e91391061f46fba9cb38439..cbe572792b6f685b80fbeb5b41fe6ad46083eaad 100644 (file)
@@ -215,7 +215,7 @@ ReconnectCtlPtr CfgIface::makeReconnectCtl() const {
     auto reconnect_ctl = boost::make_shared<ReconnectCtl>("Socket", timer_name,
                                                           CfgIface::getServiceSocketsMaxRetries(),
                                                           CfgIface::getServiceSocketsRetryWaitTime(),
-                                                          on_fail_action);
+                                                          on_fail_action, 0);
 
     return (reconnect_ctl);
 }
index 0ba3f5f939c4f1af7be3595d44c1462b025e7a51..e6ce7690b458d76ab7cbf3bd825950d5ce24281f 100644 (file)
@@ -30,7 +30,7 @@ public:
     /// @brief Constructor.
     NetworkStateImpl() : globally_disabled_(false), disabled_subnets_(),
           disabled_networks_(), timer_mgr_(TimerMgr::instance()),
-          disabled_by_origin_(), disabled_by_db_connection_(0) {
+          disabled_by_origin_() {
     }
 
     /// @brief Destructor.
@@ -56,23 +56,11 @@ public:
         if (disable) {
             // Disable the service for any flag.
             globally_disabled_ = true;
-            if (origin == NetworkState::DB_CONNECTION) {
-                ++disabled_by_db_connection_;
-            } else {
-                disabled_by_origin_.insert(origin);
-            }
+            disabled_by_origin_.insert(origin);
         } else {
-            if (origin == NetworkState::DB_CONNECTION) {
-                // Never go below 0 (using unsigned type).
-                // This should never happen anyway.
-                if (disabled_by_db_connection_) {
-                    --disabled_by_db_connection_;
-                }
-            } else {
-                disabled_by_origin_.erase(origin);
-            }
+            disabled_by_origin_.erase(origin);
             // Enable the service only if all flags have been cleared.
-            if (disabled_by_origin_.empty() && disabled_by_db_connection_ == 0) {
+            if (disabled_by_origin_.empty()) {
                 globally_disabled_ = false;
             }
         }
@@ -82,7 +70,12 @@ public:
     ///
     /// @note The dhcp service will remain disabled until all flags are cleared.
     void resetForDbConnection() {
-        disabled_by_db_connection_ = 0;
+        auto disabled_by_origin = disabled_by_origin_;
+        for (auto const& origin : disabled_by_origin) {
+            if (origin >= NetworkState::DB_CONNECTION) {
+                disabled_by_origin_.erase(origin);
+            }
+        }
         if (disabled_by_origin_.empty()) {
             globally_disabled_ = false;
         }
@@ -99,7 +92,7 @@ public:
                 disabled_by_origin_.erase(origin);
             }
         }
-        if (disabled_by_origin_.empty() && disabled_by_db_connection_ == 0) {
+        if (disabled_by_origin_.empty()) {
             globally_disabled_ = false;
         }
     }
@@ -115,7 +108,7 @@ public:
                 disabled_by_origin_.erase(origin);
             }
         }
-        if (disabled_by_origin_.empty() && disabled_by_db_connection_ == 0) {
+        if (disabled_by_origin_.empty()) {
             globally_disabled_ = false;
         }
     }
@@ -141,7 +134,7 @@ public:
     /// @param origin The origin of the state transition.
     void createTimer(const unsigned int seconds, unsigned int origin) {
         destroyTimer(origin);
-        if (origin == NetworkState::DB_CONNECTION) {
+        if (origin >= NetworkState::DB_CONNECTION) {
             isc_throw(BadValue, "DB connection does not support delayed enable");
         }
         auto timer_name = getTimerName(origin);
@@ -157,7 +150,7 @@ public:
     ///
     /// @param origin The origin of the state transition.
     void destroyTimer(unsigned int origin) {
-        if (origin == NetworkState::DB_CONNECTION) {
+        if (origin >= NetworkState::DB_CONNECTION) {
             return;
         }
         auto timer_name = getTimerName(origin);
@@ -182,10 +175,10 @@ public:
     virtual ElementPtr toElement() const {
         ElementPtr result = Element::createMap();
         result->set("globally-disabled", Element::create(globally_disabled_));
-        result->set("disabled-by-db-connection", Element::create(disabled_by_db_connection_ != 0));
         bool disabled_by_user = false;
         ElementPtr local_origin = Element::createList();
         ElementPtr remote_origin = Element::createList();
+        ElementPtr db_origin = Element::createList();
         std::set<unsigned int> ordered(disabled_by_origin_.begin(), disabled_by_origin_.end());
         for (auto const& origin : ordered) {
             if (origin == NetworkState::USER_COMMAND) {
@@ -197,10 +190,14 @@ public:
             if (origin >= NetworkState::HA_REMOTE_COMMAND && origin < NetworkState::DB_CONNECTION) {
                 remote_origin->add(Element::create(origin));
             }
+            if (origin >= NetworkState::DB_CONNECTION) {
+                db_origin->add(Element::create(origin));
+            }
         }
         result->set("disabled-by-user", Element::create(disabled_by_user));
         result->set("disabled-by-local-command", local_origin);
         result->set("disabled-by-remote-command", remote_origin);
+        result->set("disabled-by-db-connection", db_origin);
 
         return (result);
     }
@@ -222,10 +219,6 @@ public:
 
     /// @brief A set of requests to disable the service by origin.
     std::unordered_set<unsigned int> disabled_by_origin_;
-
-    /// @brief Flag which indicates the state has been disabled by a DB
-    /// connection loss.
-    uint32_t disabled_by_db_connection_;
 };
 
 NetworkState::NetworkState()
index 76ea59de8a7d8d41aaa358cd20573f73be0801fd..105e7e2dc12eef74d297672d95b2853cad8f7146 100644 (file)
@@ -58,10 +58,7 @@ class NetworkStateImpl;
 ///
 /// The DHCP state can also be altered by the database recovery mechanism, which
 /// disables the service on connection loss and re-enables it after the connection
-/// is restored. Unlike in HA, this is implemented using an internal counter. In
-/// this case, there is one origin for all database connections. The requests for
-/// the @c NetworkState::DB_CONNECTION are counted, and the DHCP service is
-/// re-enabled when the counter reaches 0.
+/// is restored.
 ///
 /// @todo We should consider migrating the database recovery to the same mechanism
 ///  we use for the HA. The reference counting works because the database connection
index 97a303029b59d5863a93e48c0efd9e426fcf90e8..6e30bfbe10f150741fb44c558dcbc15d58064677 100644 (file)
@@ -320,12 +320,13 @@ std::pair<uint32_t, uint32_t>
 MySqlConnection::getVersion(const ParameterMap& parameters,
                             const IOServiceAccessorPtr& ac,
                             const DbCallback& cb,
-                            const string& timer_name) {
+                            const string& timer_name,
+                            unsigned int id) {
     // Get a connection.
     MySqlConnection conn(parameters, ac, cb);
 
     if (!timer_name.empty()) {
-        conn.makeReconnectCtl(timer_name);
+        conn.makeReconnectCtl(timer_name, id);
     }
 
     // Open the database.
index 10dc1dc1f4bdb5bec1e1a0f79f2d65fec7a8fe01..dfccf705f57591feb0c62f8b98f984b02810465d 100644 (file)
@@ -281,7 +281,8 @@ public:
     getVersion(const ParameterMap& parameters,
                const IOServiceAccessorPtr& ac = IOServiceAccessorPtr(),
                const DbCallback& cb = DbCallback(),
-               const std::string& timer_name = std::string());
+               const std::string& timer_name = std::string(),
+               unsigned int id = 0);
 
     /// @brief Retrieve schema version, validate it against the hardcoded
     ///     version, and attempt to initialize the schema if there is an
index f64d4dcb68d956c74bc7f96408d80c4583bef06c..7a808b98966c3f63a83feac64710044282b7ac76 100644 (file)
@@ -147,12 +147,13 @@ std::pair<uint32_t, uint32_t>
 PgSqlConnection::getVersion(const ParameterMap& parameters,
                             const IOServiceAccessorPtr& ac,
                             const DbCallback& cb,
-                            const string& timer_name) {
+                            const string& timer_name,
+                            unsigned int id) {
     // Get a connection.
     PgSqlConnection conn(parameters, ac, cb);
 
     if (!timer_name.empty()) {
-        conn.makeReconnectCtl(timer_name);
+        conn.makeReconnectCtl(timer_name, id);
     }
 
     // Open the database.
index aeae99f503618f669809489cbbfdf5cf1753e061..d433b88fd3de0e1f5f6a382c2a209fb160826937 100644 (file)
@@ -252,7 +252,8 @@ public:
     getVersion(const ParameterMap& parameters,
                const IOServiceAccessorPtr& ac = IOServiceAccessorPtr(),
                const DbCallback& cb = DbCallback(),
-               const std::string& timer_name = std::string());
+               const std::string& timer_name = std::string(),
+               unsigned int id = 0);
 
     /// @brief Retrieve schema version, validate it against the hardcoded
     ///     version, and attempt to initialize the schema if there is an
index b9f4a328ea5511a7f7ded2555a1230533f243699..63691f0d76c5e1343338ccf71504b2daa9e7c322 100644 (file)
@@ -38,16 +38,22 @@ public:
     /// @param action which should be taken on connection loss.
     ReconnectCtl(const std::string& backend_type, const std::string& timer_name,
                  unsigned int max_retries, unsigned int retry_interval,
-                 OnFailAction action) :
+                 OnFailAction action, unsigned int id) :
           backend_type_(backend_type), timer_name_(timer_name),
           max_retries_(max_retries), retries_left_(max_retries),
-          retry_interval_(retry_interval), action_(action) {}
+          retry_interval_(retry_interval), action_(action), id_(id) {
+    }
 
     /// @brief Returns the type of the caller backend.
     std::string backendType() const {
         return (backend_type_);
     }
 
+    /// @brief Returns the ID of the manager.
+    unsigned int id() const {
+        return (id_);
+    }
+
     /// @brief Returns the associated timer name.
     ///
     /// @return the associated timer.
@@ -132,6 +138,9 @@ private:
 
     /// @brief Action to take on connection loss.
     OnFailAction action_;
+
+    /// @brief The ID of the backend.
+    unsigned int id_;
 };
 
 /// @brief Pointer to an instance of ReconnectCtl