#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>
size_t
CtrlAgentProcess::runIO() {
- getIOService()->pollExternalIOServices();
+ IOServiceMgr::instance().pollIOServices();
size_t cnt = getIOService()->poll();
if (!cnt) {
cnt = getIOService()->runOne();
/// Let postponed hook initializations to run.
try {
- getIOService()->pollExternalIOServices();
+ IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
#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>
#include <http/basic_auth_config.h>
using namespace isc::data;
+using namespace isc::asiolink;
namespace isc {
namespace agent {
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
+ IOServiceMgr::instance().clearIOServices();
libraries.loadLibraries(false);
}
}
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
#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>
#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;
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
/// Let postponed hook initializations to run.
try {
- getIOService()->pollExternalIOServices();
+ IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
#include <config.h>
+#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h>
#include <cc/data.h>
#include <config/command_mgr.h>
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;
/// Let postponed hook initializations to run.
try {
- getIOService()->pollExternalIOServices();
+ IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
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.
#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>
}
LOG_ERROR(dhcp4_logger, DHCP4_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
}
- getIOService()->clearExternalIOServices();
+ IOServiceMgr::instance().clearIOServices();
io_service_->stop();
io_service_->restart();
try {
#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
#include <config.h>
+#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h>
#include <config/command_mgr.h>
#include <database/dbaccess_parser.h>
// 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;
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);
#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>
};
IOServicePtr io_service;
-IOServicePtr main_io_service;
} // end anonymous
int
do_unload_impl() {
- if (main_io_service) {
- main_io_service->unregisterExternalIOService(io_service);
- }
+ IOServiceMgr::instance().unregisterIOService(io_service);
return (0);
}
// 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);
# 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\":
},
\"hooks-libraries\": [
{
- \"library\": \"$HOOK_PATH\",
+ \"library\": \"$HOOK_FAIL_LOAD_PATH\",
\"parameters\": {
\"mode\": \"fail-on-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,
},
\"hooks-libraries\": [
{
- \"library\": \"$HOOK_PATH\",
+ \"library\": \"$HOOK_FAIL_POLL_PATH\",
\"parameters\": {
\"mode\": \"fail-without-error\"
}
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
#include <config.h>
+#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h>
#include <cc/data.h>
#include <config/command_mgr.h>
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;
/// Let postponed hook initializations to run.
try {
- getIOService()->pollExternalIOServices();
+ IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
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.
#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>
}
LOG_ERROR(dhcp6_logger, DHCP6_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
}
- getIOService()->clearExternalIOServices();
+ IOServiceMgr::instance().clearIOServices();
io_service_->stop();
io_service_->restart();
try {
#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
#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>
// 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;
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);
#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>
};
IOServicePtr io_service;
-IOServicePtr main_io_service;
} // end anonymous
int
do_unload_impl() {
- if (main_io_service) {
- main_io_service->unregisterExternalIOService(io_service);
- }
+ IOServiceMgr::instance().unregisterIOService(io_service);
return (0);
}
// 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);
# 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\":
},
\"hooks-libraries\": [
{
- \"library\": \"$HOOK_PATH\",
+ \"library\": \"$HOOK_FAIL_LOAD_PATH\",
\"parameters\": {
\"mode\": \"fail-on-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,
},
\"hooks-libraries\": [
{
- \"library\": \"$HOOK_PATH\",
+ \"library\": \"$HOOK_FAIL_POLL_PATH\",
\"parameters\": {
\"mode\": \"fail-without-error\"
}
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
#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>
size_t
NetconfProcess::runIO() {
- getIOService()->pollExternalIOServices();
+ IOServiceMgr::instance().pollIOServices();
size_t cnt = getIOService()->poll();
if (!cnt) {
cnt = getIOService()->runOne();
/// Let postponed hook initializations to run.
try {
- getIOService()->pollExternalIOServices();
+ IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
#include <config.h>
+#include <asiolink/io_service_mgr.h>
#include <cc/data.h>
#include <cc/dhcp_config_error.h>
#include <hooks/hooks_manager.h>
#include <netconf/simple_parser.h>
using namespace isc::data;
+using namespace isc::asiolink;
namespace isc {
namespace netconf {
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
+ IOServiceMgr::instance().clearIOServices();
libraries.loadLibraries(false);
}
}
@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
@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
#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>
} // 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;
/// @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)
/// @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)
/// @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 {
/// @brief Get the hook I/O service.
///
/// @return the hook I/O service.
- isc::asiolink::IOServicePtr& getIOService() {
+ isc::asiolink::IOServicePtr getIOService() {
return (io_service_);
}
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_;
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);
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);
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);
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);
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);
#include <config.h>
+#include <asiolink/io_service_mgr.h>
#include <dhcpsrv/cfgmgr.h>
#include <hooks/hooks.h>
#include <process/daemon.h>
/// @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);
}
/// @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);
}
// 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();
namespace dhcp {
isc::asiolink::IOServicePtr MySqlConfigBackendImpl::io_service_;
-isc::asiolink::IOServicePtr MySqlConfigBackendImpl::main_io_service_;
MySqlConfigBackendImpl::
ScopedAuditRevision::ScopedAuditRevision(MySqlConfigBackendImpl* impl,
/// @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_);
}
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_;
/// @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
#include <config.h>
+#include <asiolink/io_service_mgr.h>
#include <dhcpsrv/cfgmgr.h>
#include <hooks/hooks.h>
#include <process/daemon.h>
/// @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);
}
/// @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);
}
// 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();
namespace dhcp {
isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::io_service_;
-isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::main_io_service_;
PgSqlTaggedStatement&
PgSqlConfigBackendImpl::getStatement(size_t /* index */) const {
/// @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_);
}
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_;
/// @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_;
namespace run_script {
IOServicePtr RunScriptImpl::io_service_;
-IOServicePtr RunScriptImpl::main_io_service_;
RunScriptImpl::RunScriptImpl() : io_context_(new IOService()), name_(), sync_(false) {
}
/// @brief Get the hook I/O service.
///
/// @return the hook I/O service.
- isc::asiolink::IOServicePtr& getIOContext() {
+ isc::asiolink::IOServicePtr getIOContext() {
return (io_context_);
}
/// @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_);
}
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.
/// @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.
#include <config.h>
+#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h>
#include <hooks/hooks.h>
#include <run_script.h>
///
/// @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()) {
/// @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)
/// @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)
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
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 \
/// @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();
};
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
/// @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.
/// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
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
--- /dev/null
+// 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
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);
-}
-
}
#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;
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
+ IOServiceMgr::instance().clearIOServices();
libraries.loadLibraries(false);
}
}
// 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>
// 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();
// case of problems.
storage->applyLoggingCfg();
- getIOService()->clearExternalIOServices();
-
ConstElementPtr answer = updateConfig(module_config);
int rcode = 0;
parseAnswer(rcode, answer);
LOG_ERROR(dctl_logger, DCTL_UNLOAD_LIBRARIES_ERROR).arg(msg);
}
- getIOService()->clearExternalIOServices();
+ IOServiceMgr::instance().clearIOServices();
io_signal_set_.reset();
try {