]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3315] addressed review comments
authorRazvan Becheriu <razvan@isc.org>
Fri, 19 Apr 2024 14:53:32 +0000 (17:53 +0300)
committerRazvan Becheriu <razvan@isc.org>
Mon, 22 Apr 2024 19:59:07 +0000 (22:59 +0300)
42 files changed:
src/bin/agent/ca_process.cc
src/bin/agent/simple_parser.cc
src/bin/d2/d2_hooks.dox
src/bin/d2/d2_process.cc
src/bin/dhcp4/ctrl_dhcp4_srv.cc
src/bin/dhcp4/dhcp4_hooks.dox
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/json_config_parser.cc
src/bin/dhcp4/tests/callout_library_4.cc
src/bin/dhcp4/tests/dhcp4_process_tests.sh.in
src/bin/dhcp6/ctrl_dhcp6_srv.cc
src/bin/dhcp6/dhcp6_hooks.dox
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/json_config_parser.cc
src/bin/dhcp6/tests/callout_library_4.cc
src/bin/dhcp6/tests/dhcp6_process_tests.sh.in
src/bin/netconf/netconf_process.cc
src/bin/netconf/simple_parser.cc
src/hooks/dhcp/high_availability/ha.dox
src/hooks/dhcp/high_availability/ha_callouts.cc
src/hooks/dhcp/high_availability/ha_impl.h
src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc
src/hooks/dhcp/high_availability/tests/ha_test.cc
src/hooks/dhcp/mysql_cb/mysql_cb_callouts.cc
src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc
src/hooks/dhcp/mysql_cb/mysql_cb_impl.h
src/hooks/dhcp/pgsql_cb/pgsql_cb_callouts.cc
src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc
src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.h
src/hooks/dhcp/run_script/run_script.cc
src/hooks/dhcp/run_script/run_script.h
src/hooks/dhcp/run_script/run_script_callouts.cc
src/lib/asiolink/Makefile.am
src/lib/asiolink/io_service.cc
src/lib/asiolink/io_service.h
src/lib/asiolink/io_service_mgr.cc [new file with mode: 0644]
src/lib/asiolink/io_service_mgr.h [new file with mode: 0644]
src/lib/asiolink/tests/Makefile.am
src/lib/asiolink/tests/io_service_mgr_unittest.cc [new file with mode: 0644]
src/lib/asiolink/tests/io_service_unittest.cc
src/lib/d2srv/d2_simple_parser.cc
src/lib/process/d_controller.cc

index 536c1fe29f9b8285171dd9edeab75f5124755aeb..2bfa6a77b644827dcb09a5ea0304277afb7f1f13 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 #include <asiolink/asio_wrapper.h>
+#include <asiolink/io_service_mgr.h>
 #include <agent/ca_process.h>
 #include <agent/ca_controller.h>
 #include <agent/ca_response_creator_factory.h>
@@ -89,7 +90,7 @@ CtrlAgentProcess::run() {
 
 size_t
 CtrlAgentProcess::runIO() {
-    getIOService()->pollExternalIOServices();
+    IOServiceMgr::instance().pollIOServices();
     size_t cnt = getIOService()->poll();
     if (!cnt) {
         cnt = getIOService()->runOne();
@@ -196,7 +197,7 @@ CtrlAgentProcess::configure(isc::data::ConstElementPtr config_set,
 
     /// Let postponed hook initializations to run.
     try {
-        getIOService()->pollExternalIOServices();
+        IOServiceMgr::instance().pollIOServices();
     } catch (const std::exception& ex) {
         std::ostringstream err;
         err << "Error initializing hooks: "
index 6c6eb5d06679c1bf39e1d44cde44212319647a3b..7a6a76372cd9d8e14439ab45e8c2625c02f9610c 100644 (file)
@@ -7,6 +7,7 @@
 #include <config.h>
 
 #include <agent/simple_parser.h>
+#include <asiolink/io_service_mgr.h>
 #include <cc/data.h>
 #include <cc/dhcp_config_error.h>
 #include <hooks/hooks_manager.h>
@@ -14,6 +15,7 @@
 #include <http/basic_auth_config.h>
 
 using namespace isc::data;
+using namespace isc::asiolink;
 
 namespace isc {
 namespace agent {
@@ -182,6 +184,7 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx,
         // change causes problems when trying to roll back.
         HooksManager::prepareUnloadLibraries();
         static_cast<void>(HooksManager::unloadLibraries());
+        IOServiceMgr::instance().clearIOServices();
         libraries.loadLibraries(false);
     }
 }
index 55410809b7d169c784584001a13c3b6e2ff786a3..a01525b5d4cb84b10394291e829693f53000aff5 100644 (file)
@@ -57,12 +57,15 @@ to the end of this list.
    its (re)configuration. The server provides received and parsed configuration
    structures to the hook library.
    If the library uses any IO operations, it should create a local IOService
-   object and register it to the main IOService which is also provided. This way
-   the local IOService is used by the server to run asynchronous operations. The
-   hooks library can use the local IOService object to schedule asynchronous
-   tasks which are triggered by the D2 server's main loop. The hook library
-   should hold the provided pointer until the library is unloaded at which stage
-   it must unregister the local IOService.
+   object and register it to the IOServiceMgr. This way the local IOService is
+   used by the server to run asynchronous operations. The hooks library can use
+   the local IOService object to schedule asynchronous tasks which are triggered
+   by the D2 server's main loop. The hook library can use the local IOService
+   until the library is unloaded at which stage it must unregister it.
+   The "io_context" parameter gives access to the main IOService, but it's use
+   has been deprecated in favor of a local IOService to avoid issues when
+   unloading the library. The parameter has been deprecated and will be removed
+   in future versions.
    The D2CfgContext object provides access to the D2 running configuration.
 
  - <b>Next step status</b>: If any callout sets the status to DROP, the server
index c77430cd8237202805c0eb9a4074f47d8ff34cf5..1e741697e9be6e614dea309f9d7ac5c043c1c3cb 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 #include <asiolink/asio_wrapper.h>
+#include <asiolink/io_service_mgr.h>
 #include <cc/command_interpreter.h>
 #include <config/command_mgr.h>
 #include <d2/d2_controller.h>
@@ -17,6 +18,7 @@
 #include <hooks/hooks.h>
 #include <hooks/hooks_manager.h>
 
+using namespace isc::asiolink;
 using namespace isc::config;
 using namespace isc::hooks;
 using namespace isc::process;
@@ -129,7 +131,7 @@ D2Process::run() {
 
 size_t
 D2Process::runIO() {
-    getIOService()->pollExternalIOServices();
+    IOServiceMgr::instance().pollIOServices();
     // We want to block until at least one handler is called.  We'll use
     // boost::asio::io_service directly for two reasons. First off
     // asiolink::IOService::runOne is a void and boost::asio::io_service::stopped
@@ -303,7 +305,7 @@ D2Process::configure(isc::data::ConstElementPtr config_set, bool check_only) {
 
     /// Let postponed hook initializations to run.
     try {
-        getIOService()->pollExternalIOServices();
+        IOServiceMgr::instance().pollIOServices();
     } catch (const std::exception& ex) {
         std::ostringstream err;
         err << "Error initializing hooks: "
index a3cc72087d9d99068301fbf0b76bc0df1466df36..3145be6a0ad05465baf09d208ee8c04ea2037fcd 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <cc/command_interpreter.h>
 #include <cc/data.h>
 #include <config/command_mgr.h>
@@ -241,7 +242,7 @@ ControlledDhcpv4Srv::commandLibReloadHandler(const string&, ConstElementPtr) {
         HookLibsCollection loaded = HooksManager::getLibraryInfo();
         HooksManager::prepareUnloadLibraries();
         static_cast<void>(HooksManager::unloadLibraries());
-        getIOService()->clearExternalIOServices();
+        IOServiceMgr::instance().clearIOServices();
         bool multi_threading_enabled = true;
         uint32_t thread_count = 0;
         uint32_t queue_size = 0;
@@ -453,7 +454,7 @@ ControlledDhcpv4Srv::commandConfigSetHandler(const string&,
 
     /// Let postponed hook initializations to run.
     try {
-        getIOService()->pollExternalIOServices();
+        IOServiceMgr::instance().pollIOServices();
     } catch (const std::exception& ex) {
         std::ostringstream err;
         err << "Error initializing hooks: "
index 177e5600ba8b771c17b3e400860b639428bac1bc..cb8c699a2070a1568a2b23f944550c6174bce414 100644 (file)
@@ -57,12 +57,15 @@ to the end of this list.
    its (re)configuration. The server provides received and parsed configuration
    structures to the hook library.
    If the library uses any IO operations, it should create a local IOService
-   object and register it to the main IOService which is also provided. This way
-   the local IOService is used by the server to run asynchronous operations. The
-   hooks library can use the local IOService object to schedule asynchronous
-   tasks which are triggered by the DHCP server's main loop. The hook library
-   should hold the provided pointer until the library is unloaded at which stage
-   it must unregister the local IOService.
+   object and register it to the IOServiceMgr. This way the local IOService is
+   used by the server to run asynchronous operations. The hooks library can use
+   the local IOService object to schedule asynchronous tasks which are triggered
+   by the DHCP server's main loop. The hook library can use the local IOService
+   until the library is unloaded at which stage it must unregister it.
+   The "io_context" parameter gives access to the main IOService, but it's use
+   has been deprecated in favor of a local IOService to avoid issues when
+   unloading the library. The parameter has been deprecated and will be removed
+   in future versions.
    The NetworkState object provides access to the DHCP service state of the
    server and allows for enabling and disabling the DHCP service from the hooks
    libraries.
index dd242cd0a525ea6ae88ed3896f0dccaddc8f4ce3..14ab46a1dfa5f6cf32e321719328d42eef940741 100644 (file)
@@ -7,6 +7,7 @@
 #include <config.h>
 #include <kea_version.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <dhcp/dhcp4.h>
 #include <dhcp/duid.h>
 #include <dhcp/hwaddr.h>
@@ -706,7 +707,7 @@ Dhcpv4Srv::~Dhcpv4Srv() {
         }
         LOG_ERROR(dhcp4_logger, DHCP4_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
     }
-    getIOService()->clearExternalIOServices();
+    IOServiceMgr::instance().clearIOServices();
     io_service_->stop();
     io_service_->restart();
     try {
@@ -1133,7 +1134,7 @@ Dhcpv4Srv::run() {
 #endif // ENABLE_AFL
         try {
             runOne();
-            getIOService()->pollExternalIOServices();
+            IOServiceMgr::instance().pollIOServices();
             getIOService()->poll();
         } catch (const std::exception& e) {
             // General catch-all exception that are not caught by more specific
index 0cfa5de2b7156d998bb831a9c2731bff1b566d01..9ab0c886c5214c5dd5743bd1761f001faa9ccfb9 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <cc/command_interpreter.h>
 #include <config/command_mgr.h>
 #include <database/dbaccess_parser.h>
@@ -879,6 +880,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
             // change causes problems when trying to roll back.
             HooksManager::prepareUnloadLibraries();
             static_cast<void>(HooksManager::unloadLibraries());
+            IOServiceMgr::instance().clearIOServices();
             const HooksConfig& libraries =
                 CfgMgr::instance().getStagingCfg()->getHooksConfig();
             bool multi_threading_enabled = true;
@@ -934,6 +936,16 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
             if (notify_libraries) {
                 return (notify_libraries);
             }
+
+            /// Let postponed hook initializations to run.
+            try {
+                IOServiceMgr::instance().pollIOServices();
+            } catch (const std::exception& ex) {
+                std::ostringstream err;
+                err << "Error initializing hooks: "
+                    << ex.what();
+                return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
+            }
         }
 
         return (answer);
index e9b55d85ad7e018a2453417c67d5a418f537a929..0166e5f0ee5ab7ce51cf625a51362b39b5ff1266 100644 (file)
@@ -15,6 +15,7 @@ static const int LIBRARY_NUMBER = 4;
 #include <config.h>
 
 #include <asiolink/io_service.h>
+#include <asiolink/io_service_mgr.h>
 #include <dhcp4/tests/callout_library_common.h>
 #include <dhcpsrv/srv_config.h>
 
@@ -32,7 +33,6 @@ void start_service(void) {
 };
 
 IOServicePtr io_service;
-IOServicePtr main_io_service;
 
 } // end anonymous
 
@@ -57,9 +57,7 @@ do_load_impl(LibraryHandle& handle) {
 
 int
 do_unload_impl() {
-    if (main_io_service) {
-        main_io_service->unregisterExternalIOService(io_service);
-    }
+    IOServiceMgr::instance().unregisterIOService(io_service);
     return (0);
 }
 
@@ -92,14 +90,10 @@ dhcp4_srv_configured(CalloutHandle& handle) {
     // Get the IO context to post start_service on it.
     std::string error("");
     try {
-        handle.getArgument("io_context", main_io_service);
-        if (!main_io_service) {
-            error = "null io_context";
-        }
-        main_io_service->registerExternalIOService(io_service);
+        IOServiceMgr::instance().registerIOService(io_service);
         io_service->post(start_service);
     } catch (const std::exception& ex) {
-        error = "no io_context in arguments";
+        error = "unknown error";
     }
     if (!error.empty()) {
         handle.setArgument("error", error);
index 2ab573b2a5264d176450202977b17ff745de5669..8ea55c1767d78a0a41735a6fd36e61689a7be3dd 100644 (file)
@@ -19,7 +19,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test_leases.csv"
 # Path to the Kea LFC application
 export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
 # Path to test hooks library
-HOOK_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/.libs/libco3.so"
+HOOK_FAIL_LOAD_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/.libs/libco3.so"
+# Path to test hooks library
+HOOK_FAIL_POLL_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/.libs/libco4.so"
 # Kea configuration to be stored in the configuration file.
 CONFIG="{
     \"Dhcp4\":
@@ -202,7 +204,7 @@ INVALID_CONFIG_HOOKS_LOAD="{
         },
         \"hooks-libraries\": [
         {
-            \"library\": \"$HOOK_PATH\",
+            \"library\": \"$HOOK_FAIL_LOAD_PATH\",
                 \"parameters\": {
                     \"mode\": \"fail-on-load\"
             }
@@ -223,14 +225,66 @@ INVALID_CONFIG_HOOKS_LOAD="{
 
 # Invalid configuration (hook point returns error) to check that performing
 # extra configuration checks detects the error.
-INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
+INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD="{
     \"Dhcp4\":
     {
         \"interfaces-config\": {
             \"interfaces\": [ ]
         },
         \"multi-threading\": {
-          \"enable-multi-threading\": false
+            \"enable-multi-threading\": false
+        },
+        \"valid-lifetime\": 4000,
+        \"renew-timer\": 1000,
+        \"rebind-timer\": 2000,
+        \"lease-database\":
+        {
+            \"type\": \"memfile\",
+            \"name\": \"$LEASE_FILE\",
+            \"persist\": false,
+            \"lfc-interval\": 0
+        },
+        \"subnet4\": [
+        {
+            \"id\": 1,
+            \"subnet\": \"10.0.0.0/8\",
+            \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
+        } ],
+        \"dhcp-ddns\": {
+            \"enable-updates\": true,
+            \"qualifying-suffix\": \"\"
+        },
+        \"hooks-libraries\": [
+        {
+            \"library\": \"$HOOK_FAIL_LOAD_PATH\",
+                \"parameters\": {
+                    \"mode\": \"fail-without-error\"
+            }
+        } ],
+        \"loggers\": [
+        {
+            \"name\": \"kea-dhcp4\",
+            \"output-options\": [
+                {
+                    \"output\": \"$LOG_FILE\"
+                }
+            ],
+            \"severity\": \"INFO\"
+        }
+        ]
+    }
+}"
+
+# Invalid configuration (poll after load throws exception) to check that performing
+# extra configuration checks detects the error.
+INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_POLL="{
+    \"Dhcp4\":
+    {
+        \"interfaces-config\": {
+            \"interfaces\": [ ]
+        },
+        \"multi-threading\": {
+            \"enable-multi-threading\": false
         },
         \"valid-lifetime\": 4000,
         \"renew-timer\": 1000,
@@ -254,7 +308,7 @@ INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
         },
         \"hooks-libraries\": [
         {
-            \"library\": \"$HOOK_PATH\",
+            \"library\": \"$HOOK_FAIL_POLL_PATH\",
                 \"parameters\": {
                     \"mode\": \"fail-without-error\"
             }
@@ -582,5 +636,6 @@ syntax_check_test "dhcpv4.syntax_check_success" "${CONFIG}" 0 -t
 syntax_check_test "dhcpv4.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1 -t
 syntax_check_test "dhcpv4.syntax_check_bad_values" "${CONFIG_BAD_VALUES}" 1 -t
 syntax_check_test "dhcpv4.syntax_check_hooks_load_fail" "${INVALID_CONFIG_HOOKS_LOAD}" 1 -T
-syntax_check_test "dhcpv4.syntax_check_hooks_callout_fail" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL}" 1 -T
+syntax_check_test "dhcpv4.syntax_check_hooks_callout_fail_on_load" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD}" 1 -T
+syntax_check_test "dhcpv4.syntax_check_hooks_callout_fail_on_poll" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_POLL}" 1 -T
 password_redact_test "dhcpv4.password_redact_test" "$(kea_dhcp_config 4)" 0
index bfea49d256ae7f928ea6ef276e2a5464b83efcbc..1e4af158d1481c76fb1a286ba4a37a159b0a6056 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <cc/command_interpreter.h>
 #include <cc/data.h>
 #include <config/command_mgr.h>
@@ -244,7 +245,7 @@ ControlledDhcpv6Srv::commandLibReloadHandler(const string&, ConstElementPtr) {
         HookLibsCollection loaded = HooksManager::getLibraryInfo();
         HooksManager::prepareUnloadLibraries();
         static_cast<void>(HooksManager::unloadLibraries());
-        getIOService()->clearExternalIOServices();
+        IOServiceMgr::instance().clearIOServices();
         bool multi_threading_enabled = true;
         uint32_t thread_count = 0;
         uint32_t queue_size = 0;
@@ -455,7 +456,7 @@ ControlledDhcpv6Srv::commandConfigSetHandler(const string&,
 
     /// Let postponed hook initializations to run.
     try {
-        getIOService()->pollExternalIOServices();
+        IOServiceMgr::instance().pollIOServices();
     } catch (const std::exception& ex) {
         std::ostringstream err;
         err << "Error initializing hooks: "
index 7c7e5dfa53c075c5014f4c4f672a56f851262f59..d2b30879508ce6cb64b4c396f40122c872c1f783 100644 (file)
@@ -57,12 +57,15 @@ to the end of this list.
    its (re)configuration. The server provides received and parsed configuration
    structures to the hook library.
    If the library uses any IO operations, it should create a local IOService
-   object and register it to the main IOService which is also provided. This way
-   the local IOService is used by the server to run asynchronous operations. The
-   hooks library can use the local IOService object to schedule asynchronous
-   tasks which are triggered by the DHCP server's main loop. The hook library
-   should hold the provided pointer until the library is unloaded at which stage
-   it must unregister the local IOService.
+   object and register it to the IOServiceMgr. This way the local IOService is
+   used by the server to run asynchronous operations. The hooks library can use
+   the local IOService object to schedule asynchronous tasks which are triggered
+   by the DHCP server's main loop. The hook library can use the local IOService
+   until the library is unloaded at which stage it must unregister it.
+   The "io_context" parameter gives access to the main IOService, but it's use
+   has been deprecated in favor of a local IOService to avoid issues when
+   unloading the library. The parameter has been deprecated and will be removed
+   in future versions.
    The NetworkState object provides access to the DHCP service state of the
    server and allows for enabling and disabling the DHCP service from the hooks
    libraries.
index 0f59bc4481f58876634361455f6585720bc89926..205bf5d23dc1aeac03b4ef06bdf672c938e77c76 100644 (file)
@@ -8,6 +8,7 @@
 #include <kea_version.h>
 
 #include <asiolink/io_address.h>
+#include <asiolink/io_service_mgr.h>
 #include <dhcp_ddns/ncr_msg.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/docsis3_option_defs.h>
@@ -302,7 +303,7 @@ Dhcpv6Srv::~Dhcpv6Srv() {
         }
         LOG_ERROR(dhcp6_logger, DHCP6_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
     }
-    getIOService()->clearExternalIOServices();
+    IOServiceMgr::instance().clearIOServices();
     io_service_->stop();
     io_service_->restart();
     try {
@@ -614,7 +615,7 @@ Dhcpv6Srv::run() {
 #endif // ENABLE_AFL
         try {
             runOne();
-            getIOService()->pollExternalIOServices();
+            IOServiceMgr::instance().pollIOServices();
             getIOService()->poll();
         } catch (const std::exception& e) {
             // General catch-all standard exceptions that are not caught by more
index 207dde7b0b837d076637b4677a4ff56a1cdbb2ce..8de39074383127965ca0193c80fe826437bd7f39 100644 (file)
@@ -7,6 +7,7 @@
 #include <config.h>
 
 #include <asiolink/io_address.h>
+#include <asiolink/io_service_mgr.h>
 #include <cc/data.h>
 #include <cc/command_interpreter.h>
 #include <config/command_mgr.h>
@@ -1012,6 +1013,7 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
             // change causes problems when trying to roll back.
             HooksManager::prepareUnloadLibraries();
             static_cast<void>(HooksManager::unloadLibraries());
+            IOServiceMgr::instance().clearIOServices();
             const HooksConfig& libraries =
                 CfgMgr::instance().getStagingCfg()->getHooksConfig();
             bool multi_threading_enabled = true;
@@ -1067,6 +1069,16 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
             if (notify_libraries) {
                 return (notify_libraries);
             }
+
+            /// Let postponed hook initializations to run.
+            try {
+                IOServiceMgr::instance().pollIOServices();
+            } catch (const std::exception& ex) {
+                std::ostringstream err;
+                err << "Error initializing hooks: "
+                    << ex.what();
+                return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
+            }
         }
 
         return (answer);
index 0739268fc19804afed00460f3a60dc9a8d083f7b..537315c4c556a5f6c3ceb7aff6fb00c7dd4ca536 100644 (file)
@@ -15,6 +15,7 @@ static const int LIBRARY_NUMBER = 4;
 #include <config.h>
 
 #include <asiolink/io_service.h>
+#include <asiolink/io_service_mgr.h>
 #include <dhcp6/tests/callout_library_common.h>
 #include <dhcpsrv/srv_config.h>
 
@@ -32,7 +33,6 @@ void start_service(void) {
 };
 
 IOServicePtr io_service;
-IOServicePtr main_io_service;
 
 } // end anonymous
 
@@ -57,9 +57,7 @@ do_load_impl(LibraryHandle& handle) {
 
 int
 do_unload_impl() {
-    if (main_io_service) {
-        main_io_service->unregisterExternalIOService(io_service);
-    }
+    IOServiceMgr::instance().unregisterIOService(io_service);
     return (0);
 }
 
@@ -92,14 +90,10 @@ dhcp6_srv_configured(CalloutHandle& handle) {
     // Get the IO context to post start_service on it.
     std::string error("");
     try {
-        handle.getArgument("io_context", main_io_service);
-        if (!main_io_service) {
-            error = "null io_context";
-        }
-        main_io_service->registerExternalIOService(io_service);
+        IOServiceMgr::instance().registerIOService(io_service);
         io_service->post(start_service);
     } catch (const std::exception& ex) {
-        error = "no io_context in arguments";
+        error = "unknown error";
     }
     if (!error.empty()) {
         handle.setArgument("error", error);
index 3bcab77cb35d593b72becb19dd18650e9288e80c..ad747214b96cccfed18c1794c1c6702a8fa8db86 100644 (file)
@@ -19,7 +19,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test_leases.csv"
 # Path to the Kea LFC application
 export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
 # Path to test hooks library
-HOOK_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/.libs/libco3.so"
+HOOK_FAIL_LOAD_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/.libs/libco3.so"
+# Path to test hooks library
+HOOK_FAIL_POLL_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/.libs/libco3.so"
 # Kea configuration to be stored in the configuration file.
 CONFIG="{
     \"Dhcp6\":
@@ -214,7 +216,7 @@ INVALID_CONFIG_HOOKS_LOAD="{
         },
         \"hooks-libraries\": [
         {
-            \"library\": \"$HOOK_PATH\",
+            \"library\": \"$HOOK_FAIL_LOAD_PATH\",
                 \"parameters\": {
                     \"mode\": \"fail-on-load\"
             }
@@ -235,18 +237,75 @@ INVALID_CONFIG_HOOKS_LOAD="{
 
 # Invalid configuration (hook point returns error) to check that performing
 # extra configuration checks detects the error.
-INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
+INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD="{
     \"Dhcp6\":
     {
         \"interfaces-config\": {
-          \"interfaces\": [ ]
+            \"interfaces\": [ ]
         },
         \"multi-threading\": {
-          \"enable-multi-threading\": false
+            \"enable-multi-threading\": false
         },
         \"server-id\": {
-          \"type\": \"LLT\",
-          \"persist\": false
+            \"type\": \"LLT\",
+            \"persist\": false
+        },
+        \"preferred-lifetime\": 3000,
+        \"valid-lifetime\": 4000,
+        \"renew-timer\": 1000,
+        \"rebind-timer\": 2000,
+        \"lease-database\":
+        {
+            \"type\": \"memfile\",
+            \"name\": \"$LEASE_FILE\",
+            \"persist\": false,
+            \"lfc-interval\": 0
+        },
+        \"subnet6\": [
+        {
+            \"subnet\": \"2001:db8:1::/64\",
+            \"id\": 1,
+            \"pools\": [ { \"pool\": \"2001:db8:1::10-2001:db8:1::100\" } ]
+        } ],
+        \"dhcp-ddns\": {
+            \"enable-updates\": true,
+            \"qualifying-suffix\": \"\"
+        },
+        \"hooks-libraries\": [
+        {
+            \"library\": \"$HOOK_FAIL_LOAD_PATH\",
+                \"parameters\": {
+                    \"mode\": \"fail-without-error\"
+            }
+        } ],
+        \"loggers\": [
+        {
+            \"name\": \"kea-dhcp6\",
+            \"output-options\": [
+                {
+                    \"output\": \"$LOG_FILE\"
+                }
+            ],
+            \"severity\": \"INFO\"
+        }
+        ]
+    }
+}"
+
+# Invalid configuration (poll after load throws exception) to check that performing
+# extra configuration checks detects the error.
+INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_POLL="{
+    \"Dhcp6\":
+    {
+        \"interfaces-config\": {
+            \"interfaces\": [ ]
+        },
+        \"multi-threading\": {
+            \"enable-multi-threading\": false
+        },
+        \"server-id\": {
+            \"type\": \"LLT\",
+            \"persist\": false
         },
         \"preferred-lifetime\": 3000,
         \"valid-lifetime\": 4000,
@@ -271,7 +330,7 @@ INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
         },
         \"hooks-libraries\": [
         {
-            \"library\": \"$HOOK_PATH\",
+            \"library\": \"$HOOK_FAIL_POLL_PATH\",
                 \"parameters\": {
                     \"mode\": \"fail-without-error\"
             }
@@ -602,5 +661,6 @@ syntax_check_test "dhcpv6.syntax_check_success" "${CONFIG}" 0 -t
 syntax_check_test "dhcpv6.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1 -t
 syntax_check_test "dhcpv6.syntax_check_bad_values" "${CONFIG_BAD_VALUES}" 1 -t
 syntax_check_test "dhcpv6.syntax_check_hooks_load_fail" "${INVALID_CONFIG_HOOKS_LOAD}" 1 -T
-syntax_check_test "dhcpv6.syntax_check_hooks_callout_fail" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL}" 1 -T
+syntax_check_test "dhcpv6.syntax_check_hooks_callout_fail_on_load" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD}" 1 -T
+syntax_check_test "dhcpv6.syntax_check_hooks_callout_fail_on_poll" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_POLL}" 1 -T
 password_redact_test "dhcpv6.password_redact_test" "$(kea_dhcp_config 6)" 0
index 0b3dcb0a36b389b7a5708944f63c706c39ab74c1..2e86a9bee0ad401e02c7b2f592f907d9d2add5b4 100644 (file)
@@ -9,6 +9,7 @@
 #include <asiolink/asio_wrapper.h>
 #include <asiolink/io_address.h>
 #include <asiolink/io_error.h>
+#include <asiolink/io_service_mgr.h>
 #include <cc/command_interpreter.h>
 #include <config/timeouts.h>
 #include <netconf/netconf.h>
@@ -65,7 +66,7 @@ NetconfProcess::run() {
 
 size_t
 NetconfProcess::runIO() {
-    getIOService()->pollExternalIOServices();
+    IOServiceMgr::instance().pollIOServices();
     size_t cnt = getIOService()->poll();
     if (!cnt) {
         cnt = getIOService()->runOne();
@@ -89,7 +90,7 @@ NetconfProcess::configure(isc::data::ConstElementPtr config_set,
 
     /// Let postponed hook initializations to run.
     try {
-        getIOService()->pollExternalIOServices();
+        IOServiceMgr::instance().pollIOServices();
     } catch (const std::exception& ex) {
         std::ostringstream err;
         err << "Error initializing hooks: "
index fa90fb081e8ab0fc631b32a5978e6078526c59d0..d658d9f24829b6f9baf10becfbb43f83420efbb2 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <cc/data.h>
 #include <cc/dhcp_config_error.h>
 #include <hooks/hooks_manager.h>
@@ -14,6 +15,7 @@
 #include <netconf/simple_parser.h>
 
 using namespace isc::data;
+using namespace isc::asiolink;
 
 namespace isc {
 namespace netconf {
@@ -189,6 +191,7 @@ NetconfSimpleParser::parse(const NetconfConfigPtr& ctx,
         // change causes problems when trying to roll back.
         HooksManager::prepareUnloadLibraries();
         static_cast<void>(HooksManager::unloadLibraries());
+        IOServiceMgr::instance().clearIOServices();
         libraries.loadLibraries(false);
     }
 }
index cb16c0b4a75e1d0f456fd98d39f7b97514eaa12f..2ac714f9875022001709c013d78da94d5fe0f731 100644 (file)
@@ -131,20 +131,25 @@ loop), but each loop pass contains a call to:
 
 @code
 getIOService()->poll();
+IOServiceMgr::instance().pollIOServices();
 @endcode
 
 which executes callbacks for completed asynchronous operations, such as
 timers, asynchronous sends and receives. The instance of the IOService
-is owned by the DHCP servers, but hooks libraries must have access to it
-and must use this instance to schedule asynchronous tasks. This is why
-the new hook points "dhcp4_srv_configured" and "dhcp6_srv_configured"
-have been introduced. These hook points are used by the DHCPv4 and the
-DHCPv6 servers respectively, to pass the instance of the IOService
-(via "io_context" argument) to the hooks libraries which require to
-schedule asynchronous tasks.
-The hook's IOService object must be registered on the server's main IOService by
-calling registerExternalIOService and must unregister it on "unload" hook point
-by calling unregisterExternalIOService.
+is owned by the DHCP servers, but hooks libraries must create their own
+IOService access to schedule asynchronous tasks.
+The hook's IOService object must be registered on the IOServiceMgr by
+calling registerIOService and must unregister it on "unload" hook point
+by calling unregisterIOService.
+
+
+The hook points "dhcp4_srv_configured" and "dhcp6_srv_configured" have been
+introduced to give access to the server configuration if needed.
+These hook points are used by the DHCPv4 and the DHCPv6 servers respectively, to
+pass the server configuration to the hooks libraries which require it.
+The "io_context" parameter gives access to the main IOService, but it's use
+has been deprecated in favor of a local IOService to avoid issues when
+unloading the library. The parameter will be removed in future versions.
 
 It is also worth to note that the blocking reception of the DHCP packets
 may cause up to 1 second delays in the asynchronous operations. This is
@@ -152,25 +157,27 @@ due to the structure of the main server loop:
 
 @code
 bool
-Dhcpv4Srv::run() {
+Dhcpv[4|6]Srv::run() {
+[...]
     while (!shutdown_) {
+[...]
         try {
             runOne();
+            IOServiceMgr::instance().pollIOServices();
             getIOService()->poll();
         } catch (const std::exception& e) {
             // General catch-all exception that are not caught by more specific
             // catches. This one is for exceptions derived from std::exception.
-            LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_STD_EXCEPTION)
-                .arg(e.what());
+            [...]
         } catch (...) {
             // General catch-all exception that are not caught by more specific
             // catches. This one is for other exceptions, not derived from
             // std::exception.
-            LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_EXCEPTION);
+            [...]
         }
     }
 
-    return (true);
+    [...]
 }
 @endcode
 
index 200efd0f6b2d3822d2464f1ba98023f6f451d366..014080f8e8f9146c1dfa8d28c82d3ebdac795f09 100644 (file)
@@ -13,6 +13,7 @@
 #include <ha_impl.h>
 #include <ha_log.h>
 #include <asiolink/io_service.h>
+#include <asiolink/io_service_mgr.h>
 #include <cc/command_interpreter.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/network_state.h>
@@ -31,6 +32,7 @@ HAImplPtr impl;
 } // end of namespace isc::ha
 } // end of namespace isc
 
+using namespace isc::asiolink;
 using namespace isc::config;
 using namespace isc::data;
 using namespace isc::dhcp;
@@ -46,18 +48,10 @@ extern "C" {
 /// @param handle callout handle.
 int dhcp4_srv_configured(CalloutHandle& handle) {
     try {
-        handle.getArgument("io_context", impl->getMainIOService());
-        if (!impl->getMainIOService()) {
-            // Should not happen!
-            handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
-            const string error("Error: io_context is null");
-            handle.setArgument("error", error);
-            return (1);
-        }
         isc::dhcp::NetworkStatePtr network_state;
         handle.getArgument("network_state", network_state);
         impl->startServices(network_state, HAServerType::DHCPv4);
-        impl->getMainIOService()->registerExternalIOService(impl->getIOService());
+        IOServiceMgr::instance().registerIOService(impl->getIOService());
 
     } catch (const std::exception& ex) {
         LOG_ERROR(ha_logger, HA_DHCP4_START_SERVICE_FAILED)
@@ -164,18 +158,10 @@ int lease4_server_decline(CalloutHandle& handle) {
 /// @param handle callout handle.
 int dhcp6_srv_configured(CalloutHandle& handle) {
     try {
-        handle.getArgument("io_context", impl->getMainIOService());
-        if (!impl->getMainIOService()) {
-            // Should not happen!
-            handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
-            const string error("Error: io_context is null");
-            handle.setArgument("error", error);
-            return (1);
-        }
         isc::dhcp::NetworkStatePtr network_state;
         handle.getArgument("network_state", network_state);
         impl->startServices(network_state, HAServerType::DHCPv6);
-        impl->getMainIOService()->registerExternalIOService(impl->getIOService());
+        IOServiceMgr::instance().registerIOService(impl->getIOService());
 
     } catch (const std::exception& ex) {
         LOG_ERROR(ha_logger, HA_DHCP6_START_SERVICE_FAILED)
@@ -443,9 +429,7 @@ int load(LibraryHandle& handle) {
 /// @return 0 if deregistration was successful, 1 otherwise
 int unload() {
     if (impl) {
-        if (impl->getMainIOService()) {
-            impl->getMainIOService()->unregisterExternalIOService(impl->getIOService());
-        }
+        IOServiceMgr::instance().unregisterIOService(impl->getIOService());
         impl->getIOService()->stop();
         impl->getIOService()->restart();
         try {
index 041ade8c828a5eeae1ded686dbf1f89584cd6e84..d7920cf737cae8740b0ab480bdf5008d6c1b253e 100644 (file)
@@ -224,7 +224,7 @@ public:
     /// @brief Get the hook I/O service.
     ///
     /// @return the hook I/O service.
-    isc::asiolink::IOServicePtr& getIOService() {
+    isc::asiolink::IOServicePtr getIOService() {
         return (io_service_);
     }
 
@@ -235,28 +235,11 @@ public:
         io_service_ = io_service;
     }
 
-    /// @brief Get the main I/O service.
-    ///
-    /// @return the main I/O service.
-    isc::asiolink::IOServicePtr& getMainIOService() {
-        return (main_io_service_);
-    }
-
-    /// @brief Set the main I/O service.
-    ///
-    /// @param io_service the main I/O service.
-    void setMainIOService(isc::asiolink::IOServicePtr io_service) {
-        main_io_service_ = io_service;
-    }
-
 protected:
 
     /// @brief The hook I/O service.
     isc::asiolink::IOServicePtr io_service_;
 
-    /// @brief The main I/O service.
-    isc::asiolink::IOServicePtr main_io_service_;
-
     /// @brief Holds parsed configuration.
     HAConfigMapperPtr config_;
 
index 41c5a57f60cbe49d3fcfb4e6da0279bfd28b9bc3..b1b148cc808f539d0c3a1cab2ca7cdab2fa759be 100644 (file)
@@ -380,7 +380,6 @@ TEST_F(CloseHATest, close4) {
     EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp4_srv_configured_));
     {
         CalloutHandlePtr handle = HooksManager::createCalloutHandle();
-        handle->setArgument("io_context", io_service);
         handle->setArgument("network_state", network_state);
         HooksManager::callCallouts(testHooks.hook_index_dhcp4_srv_configured_,
                                    *handle);
@@ -515,7 +514,6 @@ TEST_F(CloseHATest, close4Backup) {
     EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp4_srv_configured_));
     {
         CalloutHandlePtr handle = HooksManager::createCalloutHandle();
-        handle->setArgument("io_context", io_service);
         handle->setArgument("network_state", network_state);
         HooksManager::callCallouts(testHooks.hook_index_dhcp4_srv_configured_,
                                    *handle);
@@ -619,7 +617,6 @@ TEST_F(CloseHATest, close6) {
     EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp6_srv_configured_));
     {
         CalloutHandlePtr handle = HooksManager::createCalloutHandle();
-        handle->setArgument("io_context", io_service);
         handle->setArgument("network_state", network_state);
         HooksManager::callCallouts(testHooks.hook_index_dhcp6_srv_configured_,
                                    *handle);
@@ -754,7 +751,6 @@ TEST_F(CloseHATest, close6Backup) {
     EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp6_srv_configured_));
     {
         CalloutHandlePtr handle = HooksManager::createCalloutHandle();
-        handle->setArgument("io_context", io_service);
         handle->setArgument("network_state", network_state);
         HooksManager::callCallouts(testHooks.hook_index_dhcp6_srv_configured_,
                                    *handle);
index 81750ed82bfde63ee0b0a098e880407e1027bf4e..f9365d5413c6ec93dfa02142de09c915d0968726 100644 (file)
@@ -71,7 +71,6 @@ void
 HATest::startHAService() {
     if (HooksManager::calloutsPresent(Hooks.hooks_index_dhcp4_srv_configured_)) {
         CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
-        callout_handle->setArgument("io_context", io_service_);
         callout_handle->setArgument("network_state", network_state_);
         HooksManager::callCallouts(Hooks.hooks_index_dhcp4_srv_configured_,
                                    *callout_handle);
index 2186dbf31202c4bce8a7a370bcaa0daea3366114..a3f5e5bab0accffe69f8ee9c40d7b6e93fad2343 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <config.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <hooks/hooks.h>
 #include <process/daemon.h>
@@ -68,15 +69,8 @@ int load(LibraryHandle& /* handle */) {
 /// @param handle callout handle passed to the callout.
 /// @return 0 on success, 1 otherwise.
 int dhcp4_srv_configured(CalloutHandle& handle) {
-    handle.getArgument("io_context", isc::dhcp::MySqlConfigBackendImpl::getMainIOService());
-    if (!isc::dhcp::MySqlConfigBackendImpl::getMainIOService()) {
-        const string error("Error: io_context is null");
-        handle.setArgument("error", error);
-        handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
-        return (1);
-    }
     isc::dhcp::MySqlConfigBackendImpl::getIOService().reset(new IOService());
-    isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
+    IOServiceMgr::instance().registerIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
     return (0);
 }
 
@@ -87,15 +81,8 @@ int dhcp4_srv_configured(CalloutHandle& handle) {
 /// @param handle callout handle passed to the callout.
 /// @return 0 on success, 1 otherwise.
 int dhcp6_srv_configured(CalloutHandle& handle) {
-    handle.getArgument("io_context", isc::dhcp::MySqlConfigBackendImpl::getMainIOService());
-    if (!isc::dhcp::MySqlConfigBackendImpl::getMainIOService()) {
-        const string error("Error: io_context is null");
-        handle.setArgument("error", error);
-        handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
-        return (1);
-    }
     isc::dhcp::MySqlConfigBackendImpl::getIOService().reset(new IOService());
-    isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
+    IOServiceMgr::instance().registerIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
     return (0);
 }
 
@@ -107,9 +94,7 @@ int unload() {
     // Unregister the factories and remove MySQL backends
     isc::dhcp::MySqlConfigBackendDHCPv4::unregisterBackendType();
     isc::dhcp::MySqlConfigBackendDHCPv6::unregisterBackendType();
-    if (isc::dhcp::MySqlConfigBackendImpl::getMainIOService()) {
-        isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->unregisterExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
-    }
+    IOServiceMgr::instance().unregisterIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
     if (isc::dhcp::MySqlConfigBackendImpl::getIOService()) {
         isc::dhcp::MySqlConfigBackendImpl::getIOService()->stop();
         isc::dhcp::MySqlConfigBackendImpl::getIOService()->restart();
index 390bf9cd2f7b7c9faaca79139edaed4866f6aaf9..4e1475b3636dd88f98d3d0e78794935d58adcd2c 100644 (file)
@@ -30,7 +30,6 @@ namespace isc {
 namespace dhcp {
 
 isc::asiolink::IOServicePtr MySqlConfigBackendImpl::io_service_;
-isc::asiolink::IOServicePtr MySqlConfigBackendImpl::main_io_service_;
 
 MySqlConfigBackendImpl::
 ScopedAuditRevision::ScopedAuditRevision(MySqlConfigBackendImpl* impl,
index 9931c8a551f1cc182ee311c5b148b53c360e01d7..24de344f5f82e5ce0556304b9adf92b0a1737d2b 100644 (file)
@@ -839,7 +839,7 @@ public:
     /// @brief Get the hook I/O service.
     ///
     /// @return the hook I/O service.
-    static isc::asiolink::IOServicePtr& getIOService() {
+    static isc::asiolink::IOServicePtr getIOService() {
         return (io_service_);
     }
 
@@ -850,20 +850,6 @@ public:
         io_service_ = io_service;
     }
 
-    /// @brief Get the main I/O service.
-    ///
-    /// @return the main I/O service.
-    static isc::asiolink::IOServicePtr& getMainIOService() {
-        return (main_io_service_);
-    }
-
-    /// @brief Set the main I/O service.
-    ///
-    /// @param io_service the main I/O service.
-    static void setMainIOService(isc::asiolink::IOServicePtr io_service) {
-        main_io_service_ = io_service;
-    }
-
     /// @brief Represents connection to the MySQL database.
     db::MySqlConnection conn_;
 
@@ -882,9 +868,6 @@ private:
 
     /// @brief The hook I/O service.
     static isc::asiolink::IOServicePtr io_service_;
-
-    /// @brief The main I/O service.
-    static isc::asiolink::IOServicePtr main_io_service_;
 };
 
 } // end of namespace isc::dhcp
index f824a0c59f5e147b5705d7d7ad4d9b2bfd9b59fb..03a24ac750e0bf052a134f16cca3150e3995d90d 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <config.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <hooks/hooks.h>
 #include <process/daemon.h>
@@ -68,15 +69,8 @@ int load(LibraryHandle& /* handle */) {
 /// @param handle callout handle passed to the callout.
 /// @return 0 on success, 1 otherwise.
 int dhcp4_srv_configured(CalloutHandle& handle) {
-    handle.getArgument("io_context", isc::dhcp::PgSqlConfigBackendImpl::getMainIOService());
-    if (!isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()) {
-        const string error("Error: io_context is null");
-        handle.setArgument("error", error);
-        handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
-        return (1);
-    }
     isc::dhcp::PgSqlConfigBackendImpl::getIOService().reset(new IOService());
-    isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
+    IOServiceMgr::instance().registerIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
     return (0);
 }
 
@@ -87,15 +81,8 @@ int dhcp4_srv_configured(CalloutHandle& handle) {
 /// @param handle callout handle passed to the callout.
 /// @return 0 on success, 1 otherwise.
 int dhcp6_srv_configured(CalloutHandle& handle) {
-    handle.getArgument("io_context", isc::dhcp::PgSqlConfigBackendImpl::getMainIOService());
-    if (!isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()) {
-        const string error("Error: io_context is null");
-        handle.setArgument("error", error);
-        handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
-        return (1);
-    }
     isc::dhcp::PgSqlConfigBackendImpl::getIOService().reset(new IOService());
-    isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
+    IOServiceMgr::instance().registerIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
     return (0);
 }
 
@@ -107,9 +94,7 @@ int unload() {
     // Unregister the factories and remove PostgreSQL backends
     isc::dhcp::PgSqlConfigBackendDHCPv4::unregisterBackendType();
     isc::dhcp::PgSqlConfigBackendDHCPv6::unregisterBackendType();
-    if (isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()) {
-        isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->unregisterExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
-    }
+    IOServiceMgr::instance().unregisterIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
     if (isc::dhcp::PgSqlConfigBackendImpl::getIOService()) {
         isc::dhcp::PgSqlConfigBackendImpl::getIOService()->stop();
         isc::dhcp::PgSqlConfigBackendImpl::getIOService()->restart();
index 2104e450a11fc043bd61ee1e16101be7bd8dcbfd..76a643458f49007e57736f850fc95ae606ae944d 100644 (file)
@@ -29,7 +29,6 @@ namespace isc {
 namespace dhcp {
 
 isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::io_service_;
-isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::main_io_service_;
 
 PgSqlTaggedStatement&
 PgSqlConfigBackendImpl::getStatement(size_t /* index */) const {
index a4d1d93db4aa8a49b975fb91ff62a6bf1874220b..2c848082bbd6fe4f3ec4e1c6352b1ba3dd2bb682 100644 (file)
@@ -863,7 +863,7 @@ public:
     /// @brief Get the hook I/O service.
     ///
     /// @return the hook I/O service.
-    static isc::asiolink::IOServicePtr& getIOService() {
+    static isc::asiolink::IOServicePtr getIOService() {
         return (io_service_);
     }
 
@@ -874,20 +874,6 @@ public:
         io_service_ = io_service;
     }
 
-    /// @brief Get the main I/O service.
-    ///
-    /// @return the main I/O service.
-    static isc::asiolink::IOServicePtr& getMainIOService() {
-        return (main_io_service_);
-    }
-
-    /// @brief Set the main I/O service.
-    ///
-    /// @param io_service the main I/O service.
-    static void setMainIOService(isc::asiolink::IOServicePtr io_service) {
-        main_io_service_ = io_service;
-    }
-
     /// @brief Represents connection to the PostgreSQL database.
     db::PgSqlConnection conn_;
 
@@ -907,9 +893,6 @@ private:
     /// @brief The hook I/O service.
     static isc::asiolink::IOServicePtr io_service_;
 
-    /// @brief The main I/O service.
-    static isc::asiolink::IOServicePtr main_io_service_;
-
     /// @brief Statement index of the SQL statement to use for fetching
     /// last inserted id in a given table.
     size_t last_insert_id_index_;
index 54ddb4139bdd5dfe18c79aed9767b34e485d368e..f496cfcbe44108be39f5f107a08d7cefe995075e 100644 (file)
@@ -19,7 +19,6 @@ namespace isc {
 namespace run_script {
 
 IOServicePtr RunScriptImpl::io_service_;
-IOServicePtr RunScriptImpl::main_io_service_;
 
 RunScriptImpl::RunScriptImpl() : io_context_(new IOService()), name_(), sync_(false) {
 }
index dc9f9b8a4268a69462533b97b0d3eb23b4a3ac30..b276de76dff4ff13a9712520a81cdc8af7446969 100644 (file)
@@ -245,7 +245,7 @@ public:
     /// @brief Get the hook I/O service.
     ///
     /// @return the hook I/O service.
-    isc::asiolink::IOServicePtr& getIOContext() {
+    isc::asiolink::IOServicePtr getIOContext() {
         return (io_context_);
     }
 
@@ -259,7 +259,7 @@ public:
     /// @brief Get the hook I/O service.
     ///
     /// @return the hook I/O service.
-    static isc::asiolink::IOServicePtr& getIOService() {
+    static isc::asiolink::IOServicePtr getIOService() {
         return (io_service_);
     }
 
@@ -270,20 +270,6 @@ public:
         io_service_ = io_service;
     }
 
-    /// @brief Get the main I/O service.
-    ///
-    /// @return the main I/O service.
-    static isc::asiolink::IOServicePtr& getMainIOService() {
-        return (main_io_service_);
-    }
-
-    /// @brief Set the main I/O service.
-    ///
-    /// @param io_service the main I/O service.
-    static void setMainIOService(isc::asiolink::IOServicePtr io_service) {
-        main_io_service_ = io_service;
-    }
-
 private:
 
     /// @brief The IOService object, used for all ASIO operations.
@@ -301,9 +287,6 @@ private:
 
     /// @brief The hook I/O service.
     static isc::asiolink::IOServicePtr io_service_;
-
-    /// @brief The main I/O service.
-    static isc::asiolink::IOServicePtr main_io_service_;
 };
 
 /// @brief The type of shared pointers to Run Script implementations.
index 22ee765c9a5c8aa703d40ba6ad19d354141b3445..2f54de78a4eb3b2f32eccd1feca495a91f53d255 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <cc/command_interpreter.h>
 #include <hooks/hooks.h>
 #include <run_script.h>
@@ -80,8 +81,8 @@ int load(LibraryHandle& handle) {
 ///
 /// @return always 0.
 int unload() {
-    if (RunScriptImpl::getMainIOService()) {
-        RunScriptImpl::getMainIOService()->unregisterExternalIOService(impl->getIOContext());
+    if (impl) {
+        IOServiceMgr::instance().unregisterIOService(impl->getIOContext());
     }
     impl.reset();
     if (RunScriptImpl::getIOService()) {
@@ -102,16 +103,8 @@ int unload() {
 /// @param handle callout handle.
 int dhcp4_srv_configured(CalloutHandle& handle) {
     try {
-        handle.getArgument("io_context", RunScriptImpl::getMainIOService());
-        if (!RunScriptImpl::getMainIOService()) {
-            // Should not happen!
-            handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
-            const string error("Error: io_context is null");
-            handle.setArgument("error", error);
-            return (1);
-        }
         RunScriptImpl::setIOService(impl->getIOContext());
-        RunScriptImpl::getMainIOService()->registerExternalIOService(impl->getIOContext());
+        IOServiceMgr::instance().registerIOService(impl->getIOContext());
 
     } catch (const exception& ex) {
         LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)
@@ -127,16 +120,8 @@ int dhcp4_srv_configured(CalloutHandle& handle) {
 /// @param handle callout handle.
 int dhcp6_srv_configured(CalloutHandle& handle) {
     try {
-        handle.getArgument("io_context", RunScriptImpl::getMainIOService());
-        if (!RunScriptImpl::getMainIOService()) {
-            // Should not happen!
-            handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
-            const string error("Error: io_context is null");
-            handle.setArgument("error", error);
-            return (1);
-        }
         RunScriptImpl::setIOService(impl->getIOContext());
-        RunScriptImpl::getMainIOService()->registerExternalIOService(impl->getIOContext());
+        IOServiceMgr::instance().registerIOService(impl->getIOContext());
 
     } catch (const exception& ex) {
         LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)
index 213322cb6a5f152d1cfacb801b96028fcec67ca7..dcf58f23457e3ec59030bad27ca3b47b1e8b6344 100644 (file)
@@ -29,6 +29,7 @@ libkea_asiolink_la_SOURCES += io_asio_socket.h
 libkea_asiolink_la_SOURCES += io_endpoint.cc io_endpoint.h
 libkea_asiolink_la_SOURCES += io_error.h
 libkea_asiolink_la_SOURCES += io_service.h io_service.cc
+libkea_asiolink_la_SOURCES += io_service_mgr.h io_service_mgr.cc
 libkea_asiolink_la_SOURCES += io_service_signal.cc io_service_signal.h
 libkea_asiolink_la_SOURCES += io_service_thread_pool.cc io_service_thread_pool.h
 libkea_asiolink_la_SOURCES += io_socket.h io_socket.cc
@@ -82,6 +83,7 @@ libkea_asiolink_include_HEADERS = \
        io_endpoint.h \
        io_error.h \
        io_service.h \
+       io_service_mgr.h \
        io_service_signal.h \
        io_service_thread_pool.h \
        io_socket.h \
index 8c42d6855f8be79da3dcac482a27e9a78b58d634..99d458a2bcb047612c85ac58efbaca96f5557a28 100644 (file)
@@ -40,7 +40,7 @@ public:
     /// @brief Start the underlying event loop.
     ///
     /// This method does not return control to the caller until
-    /// the @ref stop() method is called via some handler.
+    /// the @ref stop() or @ref stopWork() method is called via some handler.
     void run() {
         io_service_.run();
     };
@@ -179,25 +179,5 @@ IOService::post(const std::function<void ()>& callback) {
     return (io_impl_->post(callback));
 }
 
-void
-IOService::registerExternalIOService(IOServicePtr io_service) {
-    external_io_services_.push_back(io_service);
-}
-
-void
-IOService::unregisterExternalIOService(IOServicePtr io_service) {
-    auto it = std::find(external_io_services_.begin(), external_io_services_.end(), io_service);
-    if (it != external_io_services_.end()) {
-        external_io_services_.erase(it);
-    }
-}
-
-void
-IOService::pollExternalIOServices() {
-    for (auto& io_service : external_io_services_) {
-        io_service->poll();
-    }
-}
-
 }  // namespace asiolink
 }  // namespace isc
index 1800478b78072e05979cb85c4fe656695b5d85e9..14a33767d8d7617f67059aa2d4c99921ff60512c 100644 (file)
@@ -54,7 +54,7 @@ public:
     /// @brief Start the underlying event loop.
     ///
     /// This method does not return control to the caller until
-    /// the @ref stop() method is called via some handler.
+    /// the @ref stop() or @ref stopWork() method is called via some handler.
     void run();
 
     /// @brief Run the underlying event loop for a single event.
@@ -120,38 +120,10 @@ public:
     /// by small bits that are called from time to time).
     void post(const std::function<void ()>& callback);
 
-    /// @brief Register external IOService.
-    ///
-    /// @param io_service The external IOService to be registered.
-    void registerExternalIOService(IOServicePtr io_service);
-
-    /// @brief Unregister external IOService.
-    ///
-    /// @param io_service The external IOService to be unregistered.
-    void unregisterExternalIOService(IOServicePtr io_service);
-
-    /// @brief Clear the list of external IOService objects.
-    void clearExternalIOServices() {
-        external_io_services_.clear();
-    }
-
-    /// @brief The count of external IOService objects.
-    ///
-    // @return The count of external IOService objects.
-    size_t externalIOServiceCount() {
-        return (external_io_services_.size());
-    }
-
-    /// @brief Poll external IOService objects.
-    void pollExternalIOServices();
-
 private:
 
     /// @brief The implementation.
     boost::shared_ptr<IOServiceImpl> io_impl_;
-
-    /// @brief The list of external IOService objects.
-    std::list<IOServicePtr> external_io_services_;
 };
 
 }  // namespace asiolink
diff --git a/src/lib/asiolink/io_service_mgr.cc b/src/lib/asiolink/io_service_mgr.cc
new file mode 100644 (file)
index 0000000..6b8f97c
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <asiolink/io_service_mgr.h>
+
+namespace isc {
+namespace asiolink {
+
+IOServiceMgr& IOServiceMgr::instance() {
+    static IOServiceMgr instance;
+    return (instance);
+}
+
+void
+IOServiceMgr::registerIOService(IOServicePtr io_service) {
+    io_services_.push_back(io_service);
+}
+
+void
+IOServiceMgr::unregisterIOService(IOServicePtr io_service) {
+    auto it = std::find(io_services_.begin(), io_services_.end(), io_service);
+    if (it != io_services_.end()) {
+        io_services_.erase(it);
+    }
+}
+
+void
+IOServiceMgr::pollIOServices() {
+    for (auto& io_service : io_services_) {
+        io_service->poll();
+    }
+}
+
+} // namespace asiolink
+} // namespace isc
diff --git a/src/lib/asiolink/io_service_mgr.h b/src/lib/asiolink/io_service_mgr.h
new file mode 100644 (file)
index 0000000..a3b0fb9
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2024 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef IO_SERVICE_MGR_H
+#define IO_SERVICE_MGR_H
+
+#include <asiolink/io_service.h>
+
+#include <boost/noncopyable.hpp>
+
+namespace isc {
+namespace asiolink {
+
+class IOServiceMgr;
+
+class IOServiceMgr : boost::noncopyable {
+public:
+
+    /// @brief Access the IOServiceMgr singleton instance.
+    ///
+    /// @return the singleton instance.
+    static IOServiceMgr& instance();
+
+    /// @brief Register IOService.
+    ///
+    /// @param io_service The IOService to be registered.
+    void registerIOService(IOServicePtr io_service);
+
+    /// @brief Unregister IOService.
+    ///
+    /// @param io_service The IOService to be unregistered.
+    void unregisterIOService(IOServicePtr io_service);
+
+    /// @brief Clear the list of IOService objects.
+    void clearIOServices() {
+        io_services_.clear();
+    }
+
+    /// @brief The count of IOService objects.
+    ///
+    // @return The count of IOService objects.
+    size_t getIOServiceCount() {
+        return (io_services_.size());
+    }
+
+    /// @brief Poll IOService objects.
+    void pollIOServices();
+
+private:
+
+    /// @brief Constructor.
+    IOServiceMgr() = default;
+
+    /// @brief Destructor.
+    ~IOServiceMgr() = default;
+
+    /// @brief The list of IOService objects.
+    std::list<IOServicePtr> io_services_;
+};
+
+} // namespace asiolink
+} // namespace isc
+
+#endif // IO_SERVICE_MGR_H
index eac8ea73bdc43c8cfeb37a029e93144d5cfff464..e9e13d57aa2c57bae40a93b7a1c10602ecda070d 100644 (file)
@@ -34,6 +34,7 @@ run_unittests_SOURCES += tcp_socket_unittest.cc
 run_unittests_SOURCES += udp_endpoint_unittest.cc
 run_unittests_SOURCES += udp_socket_unittest.cc
 run_unittests_SOURCES += io_service_unittest.cc
+run_unittests_SOURCES += io_service_mgr_unittest.cc
 run_unittests_SOURCES += io_service_signal_unittests.cc
 run_unittests_SOURCES += io_service_thread_pool_unittests.cc
 run_unittests_SOURCES += dummy_io_callback_unittest.cc
diff --git a/src/lib/asiolink/tests/io_service_mgr_unittest.cc b/src/lib/asiolink/tests/io_service_mgr_unittest.cc
new file mode 100644 (file)
index 0000000..d180f66
--- /dev/null
@@ -0,0 +1,103 @@
+// Copyright (C) 2024 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <asiolink/io_service_mgr.h>
+
+#include <gtest/gtest.h>
+
+using namespace isc::asiolink;
+
+namespace {
+
+TEST(IOServiceMgr, testIOServiceMgr) {
+    EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 0);
+    int one_io_callback_count = 0;
+    auto one_f = [&one_io_callback_count] () {
+        one_io_callback_count++;
+    };
+    int two_io_callback_count = 0;
+    auto two_f = [&two_io_callback_count] () {
+        two_io_callback_count++;
+    };
+    {
+        IOServicePtr one_io_service(new IOService());
+        one_io_service->post(one_f);
+
+        IOServicePtr two_io_service(new IOService());
+        two_io_service->post(two_f);
+
+        IOServiceMgr::instance().pollIOServices();
+        EXPECT_EQ(one_io_callback_count, 0);
+        EXPECT_EQ(two_io_callback_count, 0);
+
+        IOServiceMgr::instance().registerIOService(one_io_service);
+        EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 1);
+
+        IOServiceMgr::instance().registerIOService(two_io_service);
+        EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 2);
+
+        IOServiceMgr::instance().pollIOServices();
+        EXPECT_EQ(one_io_callback_count, 1);
+        EXPECT_EQ(two_io_callback_count, 1);
+        one_io_service->post(one_f);
+        two_io_service->post(two_f);
+    }
+    EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 2);
+    IOServiceMgr::instance().pollIOServices();
+    EXPECT_EQ(one_io_callback_count, 2);
+    EXPECT_EQ(two_io_callback_count, 2);
+
+    IOServiceMgr::instance().clearIOServices();
+    EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 0);
+
+    IOServicePtr one_io_service(new IOService());
+    one_io_service->post(one_f);
+
+    IOServicePtr two_io_service(new IOService());
+    two_io_service->post(two_f);
+
+    IOServiceMgr::instance().pollIOServices();
+    EXPECT_EQ(one_io_callback_count, 2);
+    EXPECT_EQ(two_io_callback_count, 2);
+
+    IOServiceMgr::instance().registerIOService(one_io_service);
+    EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 1);
+
+    IOServiceMgr::instance().pollIOServices();
+    EXPECT_EQ(one_io_callback_count, 3);
+    EXPECT_EQ(two_io_callback_count, 2);
+    one_io_service->post(one_f);
+    two_io_service->post(two_f);
+
+    IOServiceMgr::instance().registerIOService(two_io_service);
+    EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 2);
+
+    IOServiceMgr::instance().pollIOServices();
+    EXPECT_EQ(one_io_callback_count, 4);
+    EXPECT_EQ(two_io_callback_count, 4);
+    one_io_service->post(one_f);
+    two_io_service->post(two_f);
+
+    IOServiceMgr::instance().unregisterIOService(one_io_service);
+    EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 1);
+
+    IOServiceMgr::instance().pollIOServices();
+    EXPECT_EQ(one_io_callback_count, 4);
+    EXPECT_EQ(two_io_callback_count, 5);
+    one_io_service->post(one_f);
+    two_io_service->post(two_f);
+
+    IOServiceMgr::instance().unregisterIOService(two_io_service);
+    EXPECT_EQ(IOServiceMgr::instance().getIOServiceCount(), 0);
+
+    IOServiceMgr::instance().pollIOServices();
+    EXPECT_EQ(one_io_callback_count, 4);
+    EXPECT_EQ(two_io_callback_count, 5);
+}
+
+} // namespace
index 01a550d0f95b36a66d2c487796f61e7a7925c868..7a96702e83b48b970b1dc4509a6b8ffa6d51588a 100644 (file)
@@ -45,105 +45,4 @@ TEST(IOService, post) {
     EXPECT_EQ(3, called[2]);
 }
 
-TEST(IOService, externalIOService) {
-    IOServicePtr main_io_service(new IOService());
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 0);
-    int one_io_callback_count = 0;
-    auto one_f = [&one_io_callback_count] () {
-        one_io_callback_count++;
-    };
-    int two_io_callback_count = 0;
-    auto two_f = [&two_io_callback_count] () {
-        two_io_callback_count++;
-    };
-    {
-        IOServicePtr one_io_service(new IOService());
-        one_io_service->post(one_f);
-
-        IOServicePtr two_io_service(new IOService());
-        two_io_service->post(two_f);
-
-        main_io_service->pollExternalIOServices();
-        EXPECT_EQ(one_io_callback_count, 0);
-        EXPECT_EQ(two_io_callback_count, 0);
-
-        main_io_service->registerExternalIOService(one_io_service);
-        EXPECT_EQ(main_io_service->externalIOServiceCount(), 1);
-
-        main_io_service->registerExternalIOService(two_io_service);
-        EXPECT_EQ(main_io_service->externalIOServiceCount(), 2);
-
-        main_io_service->pollExternalIOServices();
-        EXPECT_EQ(one_io_callback_count, 1);
-        EXPECT_EQ(two_io_callback_count, 1);
-        one_io_service->post(one_f);
-        two_io_service->post(two_f);
-    }
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 2);
-    main_io_service->pollExternalIOServices();
-    EXPECT_EQ(one_io_callback_count, 2);
-    EXPECT_EQ(two_io_callback_count, 2);
-
-    main_io_service->clearExternalIOServices();
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 0);
-
-    IOServicePtr one_io_service(new IOService());
-    one_io_service->post(one_f);
-
-    IOServicePtr two_io_service(new IOService());
-    two_io_service->post(two_f);
-
-    main_io_service->pollExternalIOServices();
-    EXPECT_EQ(one_io_callback_count, 2);
-    EXPECT_EQ(two_io_callback_count, 2);
-
-    main_io_service->registerExternalIOService(one_io_service);
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 1);
-
-    main_io_service->pollExternalIOServices();
-    EXPECT_EQ(one_io_callback_count, 3);
-    EXPECT_EQ(two_io_callback_count, 2);
-    one_io_service->post(one_f);
-    two_io_service->post(two_f);
-
-    main_io_service->registerExternalIOService(two_io_service);
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 2);
-
-    main_io_service->pollExternalIOServices();
-    EXPECT_EQ(one_io_callback_count, 4);
-    EXPECT_EQ(two_io_callback_count, 4);
-    one_io_service->post(one_f);
-    two_io_service->post(two_f);
-
-    main_io_service->unregisterExternalIOService(one_io_service);
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 1);
-
-    main_io_service->pollExternalIOServices();
-    EXPECT_EQ(one_io_callback_count, 4);
-    EXPECT_EQ(two_io_callback_count, 5);
-    one_io_service->post(one_f);
-    two_io_service->post(two_f);
-
-    main_io_service->unregisterExternalIOService(two_io_service);
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 0);
-
-    main_io_service->pollExternalIOServices();
-    EXPECT_EQ(one_io_callback_count, 4);
-    EXPECT_EQ(two_io_callback_count, 5);
-
-    EXPECT_NO_THROW(main_io_service->registerExternalIOService(main_io_service));
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 1);
-    main_io_service->post(one_f);
-
-    main_io_service->pollExternalIOServices();
-    EXPECT_EQ(one_io_callback_count, 5);
-    EXPECT_EQ(two_io_callback_count, 5);
-    EXPECT_NO_THROW(main_io_service->unregisterExternalIOService(main_io_service));
-    EXPECT_EQ(main_io_service->externalIOServiceCount(), 0);
-
-    main_io_service->pollExternalIOServices();
-    EXPECT_EQ(one_io_callback_count, 5);
-    EXPECT_EQ(two_io_callback_count, 5);
-}
-
 }
index 3cd37b532dc7779ac02f7d131ec8e34b9053b12c..c86bcd061d3a94dbdc084a54cd2499e03b81eb44 100644 (file)
@@ -6,12 +6,14 @@
 
 #include <config.h>
 
+#include <asiolink/io_service_mgr.h>
 #include <d2srv/d2_config.h>
 #include <d2srv/d2_simple_parser.h>
 #include <cc/data.h>
 #include <hooks/hooks_manager.h>
 #include <hooks/hooks_parser.h>
 
+using namespace isc::asiolink;
 using namespace isc::data;
 using namespace isc::d2;
 using namespace isc;
@@ -292,6 +294,7 @@ void D2SimpleParser::parse(const D2CfgContextPtr& ctx,
         // change causes problems when trying to roll back.
         HooksManager::prepareUnloadLibraries();
         static_cast<void>(HooksManager::unloadLibraries());
+        IOServiceMgr::instance().clearIOServices();
         libraries.loadLibraries(false);
     }
 }
index 6f2994accbca67d2e3e468ff19da8737de3f6a4f..023b58103a824035b58ebd2ab07d07827f79f9f5 100644 (file)
@@ -5,6 +5,8 @@
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 #include <config.h>
+
+#include <asiolink/io_service_mgr.h>
 #include <cc/command_interpreter.h>
 #include <process/cfgrpt/config_report.h>
 #include <cryptolink/crypto_hash.h>
@@ -415,8 +417,6 @@ DControllerBase::configFromFile() {
         // case of problems.
         storage->applyLoggingCfg();
 
-        getIOService()->clearExternalIOServices();
-
         answer = updateConfig(module_config);
         // In all cases the right logging configuration is in the context.
         process_->getCfgMgr()->getContext()->applyLoggingCfg();
@@ -657,8 +657,6 @@ DControllerBase::configSetHandler(const std::string&, ConstElementPtr args) {
         // case of problems.
         storage->applyLoggingCfg();
 
-        getIOService()->clearExternalIOServices();
-
         ConstElementPtr answer = updateConfig(module_config);
         int rcode = 0;
         parseAnswer(rcode, answer);
@@ -848,7 +846,7 @@ DControllerBase::~DControllerBase() {
         LOG_ERROR(dctl_logger, DCTL_UNLOAD_LIBRARIES_ERROR).arg(msg);
     }
 
-    getIOService()->clearExternalIOServices();
+    IOServiceMgr::instance().clearIOServices();
 
     io_signal_set_.reset();
     try {