2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 05:27:55 +00:00

[#3315] addressed review comments

This commit is contained in:
Razvan Becheriu 2024-04-19 17:53:32 +03:00
parent 4398fb6c4a
commit cc104b47a8
42 changed files with 483 additions and 398 deletions

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <asiolink/asio_wrapper.h> #include <asiolink/asio_wrapper.h>
#include <asiolink/io_service_mgr.h>
#include <agent/ca_process.h> #include <agent/ca_process.h>
#include <agent/ca_controller.h> #include <agent/ca_controller.h>
#include <agent/ca_response_creator_factory.h> #include <agent/ca_response_creator_factory.h>
@ -89,7 +90,7 @@ CtrlAgentProcess::run() {
size_t size_t
CtrlAgentProcess::runIO() { CtrlAgentProcess::runIO() {
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
size_t cnt = getIOService()->poll(); size_t cnt = getIOService()->poll();
if (!cnt) { if (!cnt) {
cnt = getIOService()->runOne(); cnt = getIOService()->runOne();
@ -196,7 +197,7 @@ CtrlAgentProcess::configure(isc::data::ConstElementPtr config_set,
/// Let postponed hook initializations to run. /// Let postponed hook initializations to run.
try { try {
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::ostringstream err; std::ostringstream err;
err << "Error initializing hooks: " err << "Error initializing hooks: "

View File

@ -7,6 +7,7 @@
#include <config.h> #include <config.h>
#include <agent/simple_parser.h> #include <agent/simple_parser.h>
#include <asiolink/io_service_mgr.h>
#include <cc/data.h> #include <cc/data.h>
#include <cc/dhcp_config_error.h> #include <cc/dhcp_config_error.h>
#include <hooks/hooks_manager.h> #include <hooks/hooks_manager.h>
@ -14,6 +15,7 @@
#include <http/basic_auth_config.h> #include <http/basic_auth_config.h>
using namespace isc::data; using namespace isc::data;
using namespace isc::asiolink;
namespace isc { namespace isc {
namespace agent { namespace agent {
@ -182,6 +184,7 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx,
// change causes problems when trying to roll back. // change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries(); HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries()); static_cast<void>(HooksManager::unloadLibraries());
IOServiceMgr::instance().clearIOServices();
libraries.loadLibraries(false); libraries.loadLibraries(false);
} }
} }

View File

@ -57,12 +57,15 @@ to the end of this list.
its (re)configuration. The server provides received and parsed configuration its (re)configuration. The server provides received and parsed configuration
structures to the hook library. structures to the hook library.
If the library uses any IO operations, it should create a local IOService 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 object and register it to the IOServiceMgr. This way the local IOService is
the local IOService is used by the server to run asynchronous operations. The used by the server to run asynchronous operations. The hooks library can use
hooks library can use the local IOService object to schedule asynchronous the local IOService object to schedule asynchronous tasks which are triggered
tasks which are triggered by the D2 server's main loop. The hook library by the D2 server's main loop. The hook library can use the local IOService
should hold the provided pointer until the library is unloaded at which stage until the library is unloaded at which stage it must unregister it.
it must unregister the local IOService. 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. 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 - <b>Next step status</b>: If any callout sets the status to DROP, the server

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <asiolink/asio_wrapper.h> #include <asiolink/asio_wrapper.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <config/command_mgr.h> #include <config/command_mgr.h>
#include <d2/d2_controller.h> #include <d2/d2_controller.h>
@ -17,6 +18,7 @@
#include <hooks/hooks.h> #include <hooks/hooks.h>
#include <hooks/hooks_manager.h> #include <hooks/hooks_manager.h>
using namespace isc::asiolink;
using namespace isc::config; using namespace isc::config;
using namespace isc::hooks; using namespace isc::hooks;
using namespace isc::process; using namespace isc::process;
@ -129,7 +131,7 @@ D2Process::run() {
size_t size_t
D2Process::runIO() { D2Process::runIO() {
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
// We want to block until at least one handler is called. We'll use // We want to block until at least one handler is called. We'll use
// boost::asio::io_service directly for two reasons. First off // boost::asio::io_service directly for two reasons. First off
// asiolink::IOService::runOne is a void and boost::asio::io_service::stopped // 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. /// Let postponed hook initializations to run.
try { try {
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::ostringstream err; std::ostringstream err;
err << "Error initializing hooks: " err << "Error initializing hooks: "

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <cc/data.h> #include <cc/data.h>
#include <config/command_mgr.h> #include <config/command_mgr.h>
@ -241,7 +242,7 @@ ControlledDhcpv4Srv::commandLibReloadHandler(const string&, ConstElementPtr) {
HookLibsCollection loaded = HooksManager::getLibraryInfo(); HookLibsCollection loaded = HooksManager::getLibraryInfo();
HooksManager::prepareUnloadLibraries(); HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries()); static_cast<void>(HooksManager::unloadLibraries());
getIOService()->clearExternalIOServices(); IOServiceMgr::instance().clearIOServices();
bool multi_threading_enabled = true; bool multi_threading_enabled = true;
uint32_t thread_count = 0; uint32_t thread_count = 0;
uint32_t queue_size = 0; uint32_t queue_size = 0;
@ -453,7 +454,7 @@ ControlledDhcpv4Srv::commandConfigSetHandler(const string&,
/// Let postponed hook initializations to run. /// Let postponed hook initializations to run.
try { try {
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::ostringstream err; std::ostringstream err;
err << "Error initializing hooks: " err << "Error initializing hooks: "

View File

@ -57,12 +57,15 @@ to the end of this list.
its (re)configuration. The server provides received and parsed configuration its (re)configuration. The server provides received and parsed configuration
structures to the hook library. structures to the hook library.
If the library uses any IO operations, it should create a local IOService 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 object and register it to the IOServiceMgr. This way the local IOService is
the local IOService is used by the server to run asynchronous operations. The used by the server to run asynchronous operations. The hooks library can use
hooks library can use the local IOService object to schedule asynchronous the local IOService object to schedule asynchronous tasks which are triggered
tasks which are triggered by the DHCP server's main loop. The hook library by the DHCP server's main loop. The hook library can use the local IOService
should hold the provided pointer until the library is unloaded at which stage until the library is unloaded at which stage it must unregister it.
it must unregister the local IOService. 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 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 server and allows for enabling and disabling the DHCP service from the hooks
libraries. libraries.

View File

@ -7,6 +7,7 @@
#include <config.h> #include <config.h>
#include <kea_version.h> #include <kea_version.h>
#include <asiolink/io_service_mgr.h>
#include <dhcp/dhcp4.h> #include <dhcp/dhcp4.h>
#include <dhcp/duid.h> #include <dhcp/duid.h>
#include <dhcp/hwaddr.h> #include <dhcp/hwaddr.h>
@ -706,7 +707,7 @@ Dhcpv4Srv::~Dhcpv4Srv() {
} }
LOG_ERROR(dhcp4_logger, DHCP4_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg); LOG_ERROR(dhcp4_logger, DHCP4_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
} }
getIOService()->clearExternalIOServices(); IOServiceMgr::instance().clearIOServices();
io_service_->stop(); io_service_->stop();
io_service_->restart(); io_service_->restart();
try { try {
@ -1133,7 +1134,7 @@ Dhcpv4Srv::run() {
#endif // ENABLE_AFL #endif // ENABLE_AFL
try { try {
runOne(); runOne();
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
getIOService()->poll(); getIOService()->poll();
} catch (const std::exception& e) { } catch (const std::exception& e) {
// General catch-all exception that are not caught by more specific // General catch-all exception that are not caught by more specific

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <config/command_mgr.h> #include <config/command_mgr.h>
#include <database/dbaccess_parser.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. // change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries(); HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries()); static_cast<void>(HooksManager::unloadLibraries());
IOServiceMgr::instance().clearIOServices();
const HooksConfig& libraries = const HooksConfig& libraries =
CfgMgr::instance().getStagingCfg()->getHooksConfig(); CfgMgr::instance().getStagingCfg()->getHooksConfig();
bool multi_threading_enabled = true; bool multi_threading_enabled = true;
@ -934,6 +936,16 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
if (notify_libraries) { if (notify_libraries) {
return (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); return (answer);

View File

@ -15,6 +15,7 @@ static const int LIBRARY_NUMBER = 4;
#include <config.h> #include <config.h>
#include <asiolink/io_service.h> #include <asiolink/io_service.h>
#include <asiolink/io_service_mgr.h>
#include <dhcp4/tests/callout_library_common.h> #include <dhcp4/tests/callout_library_common.h>
#include <dhcpsrv/srv_config.h> #include <dhcpsrv/srv_config.h>
@ -32,7 +33,6 @@ void start_service(void) {
}; };
IOServicePtr io_service; IOServicePtr io_service;
IOServicePtr main_io_service;
} // end anonymous } // end anonymous
@ -57,9 +57,7 @@ do_load_impl(LibraryHandle& handle) {
int int
do_unload_impl() { do_unload_impl() {
if (main_io_service) { IOServiceMgr::instance().unregisterIOService(io_service);
main_io_service->unregisterExternalIOService(io_service);
}
return (0); return (0);
} }
@ -92,14 +90,10 @@ dhcp4_srv_configured(CalloutHandle& handle) {
// Get the IO context to post start_service on it. // Get the IO context to post start_service on it.
std::string error(""); std::string error("");
try { try {
handle.getArgument("io_context", main_io_service); IOServiceMgr::instance().registerIOService(io_service);
if (!main_io_service) {
error = "null io_context";
}
main_io_service->registerExternalIOService(io_service);
io_service->post(start_service); io_service->post(start_service);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
error = "no io_context in arguments"; error = "unknown error";
} }
if (!error.empty()) { if (!error.empty()) {
handle.setArgument("error", error); handle.setArgument("error", error);

View File

@ -19,7 +19,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test_leases.csv"
# Path to the Kea LFC application # Path to the Kea LFC application
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc" export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
# Path to test hooks library # 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. # Kea configuration to be stored in the configuration file.
CONFIG="{ CONFIG="{
\"Dhcp4\": \"Dhcp4\":
@ -202,7 +204,7 @@ INVALID_CONFIG_HOOKS_LOAD="{
}, },
\"hooks-libraries\": [ \"hooks-libraries\": [
{ {
\"library\": \"$HOOK_PATH\", \"library\": \"$HOOK_FAIL_LOAD_PATH\",
\"parameters\": { \"parameters\": {
\"mode\": \"fail-on-load\" \"mode\": \"fail-on-load\"
} }
@ -223,7 +225,7 @@ INVALID_CONFIG_HOOKS_LOAD="{
# Invalid configuration (hook point returns error) to check that performing # Invalid configuration (hook point returns error) to check that performing
# extra configuration checks detects the error. # extra configuration checks detects the error.
INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{ INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD="{
\"Dhcp4\": \"Dhcp4\":
{ {
\"interfaces-config\": { \"interfaces-config\": {
@ -254,7 +256,59 @@ INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
}, },
\"hooks-libraries\": [ \"hooks-libraries\": [
{ {
\"library\": \"$HOOK_PATH\", \"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,
\"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_POLL_PATH\",
\"parameters\": { \"parameters\": {
\"mode\": \"fail-without-error\" \"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_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_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_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 password_redact_test "dhcpv4.password_redact_test" "$(kea_dhcp_config 4)" 0

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <cc/data.h> #include <cc/data.h>
#include <config/command_mgr.h> #include <config/command_mgr.h>
@ -244,7 +245,7 @@ ControlledDhcpv6Srv::commandLibReloadHandler(const string&, ConstElementPtr) {
HookLibsCollection loaded = HooksManager::getLibraryInfo(); HookLibsCollection loaded = HooksManager::getLibraryInfo();
HooksManager::prepareUnloadLibraries(); HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries()); static_cast<void>(HooksManager::unloadLibraries());
getIOService()->clearExternalIOServices(); IOServiceMgr::instance().clearIOServices();
bool multi_threading_enabled = true; bool multi_threading_enabled = true;
uint32_t thread_count = 0; uint32_t thread_count = 0;
uint32_t queue_size = 0; uint32_t queue_size = 0;
@ -455,7 +456,7 @@ ControlledDhcpv6Srv::commandConfigSetHandler(const string&,
/// Let postponed hook initializations to run. /// Let postponed hook initializations to run.
try { try {
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::ostringstream err; std::ostringstream err;
err << "Error initializing hooks: " err << "Error initializing hooks: "

View File

@ -57,12 +57,15 @@ to the end of this list.
its (re)configuration. The server provides received and parsed configuration its (re)configuration. The server provides received and parsed configuration
structures to the hook library. structures to the hook library.
If the library uses any IO operations, it should create a local IOService 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 object and register it to the IOServiceMgr. This way the local IOService is
the local IOService is used by the server to run asynchronous operations. The used by the server to run asynchronous operations. The hooks library can use
hooks library can use the local IOService object to schedule asynchronous the local IOService object to schedule asynchronous tasks which are triggered
tasks which are triggered by the DHCP server's main loop. The hook library by the DHCP server's main loop. The hook library can use the local IOService
should hold the provided pointer until the library is unloaded at which stage until the library is unloaded at which stage it must unregister it.
it must unregister the local IOService. 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 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 server and allows for enabling and disabling the DHCP service from the hooks
libraries. libraries.

View File

@ -8,6 +8,7 @@
#include <kea_version.h> #include <kea_version.h>
#include <asiolink/io_address.h> #include <asiolink/io_address.h>
#include <asiolink/io_service_mgr.h>
#include <dhcp_ddns/ncr_msg.h> #include <dhcp_ddns/ncr_msg.h>
#include <dhcp/dhcp6.h> #include <dhcp/dhcp6.h>
#include <dhcp/docsis3_option_defs.h> #include <dhcp/docsis3_option_defs.h>
@ -302,7 +303,7 @@ Dhcpv6Srv::~Dhcpv6Srv() {
} }
LOG_ERROR(dhcp6_logger, DHCP6_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg); LOG_ERROR(dhcp6_logger, DHCP6_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
} }
getIOService()->clearExternalIOServices(); IOServiceMgr::instance().clearIOServices();
io_service_->stop(); io_service_->stop();
io_service_->restart(); io_service_->restart();
try { try {
@ -614,7 +615,7 @@ Dhcpv6Srv::run() {
#endif // ENABLE_AFL #endif // ENABLE_AFL
try { try {
runOne(); runOne();
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
getIOService()->poll(); getIOService()->poll();
} catch (const std::exception& e) { } catch (const std::exception& e) {
// General catch-all standard exceptions that are not caught by more // General catch-all standard exceptions that are not caught by more

View File

@ -7,6 +7,7 @@
#include <config.h> #include <config.h>
#include <asiolink/io_address.h> #include <asiolink/io_address.h>
#include <asiolink/io_service_mgr.h>
#include <cc/data.h> #include <cc/data.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <config/command_mgr.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. // change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries(); HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries()); static_cast<void>(HooksManager::unloadLibraries());
IOServiceMgr::instance().clearIOServices();
const HooksConfig& libraries = const HooksConfig& libraries =
CfgMgr::instance().getStagingCfg()->getHooksConfig(); CfgMgr::instance().getStagingCfg()->getHooksConfig();
bool multi_threading_enabled = true; bool multi_threading_enabled = true;
@ -1067,6 +1069,16 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
if (notify_libraries) { if (notify_libraries) {
return (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); return (answer);

View File

@ -15,6 +15,7 @@ static const int LIBRARY_NUMBER = 4;
#include <config.h> #include <config.h>
#include <asiolink/io_service.h> #include <asiolink/io_service.h>
#include <asiolink/io_service_mgr.h>
#include <dhcp6/tests/callout_library_common.h> #include <dhcp6/tests/callout_library_common.h>
#include <dhcpsrv/srv_config.h> #include <dhcpsrv/srv_config.h>
@ -32,7 +33,6 @@ void start_service(void) {
}; };
IOServicePtr io_service; IOServicePtr io_service;
IOServicePtr main_io_service;
} // end anonymous } // end anonymous
@ -57,9 +57,7 @@ do_load_impl(LibraryHandle& handle) {
int int
do_unload_impl() { do_unload_impl() {
if (main_io_service) { IOServiceMgr::instance().unregisterIOService(io_service);
main_io_service->unregisterExternalIOService(io_service);
}
return (0); return (0);
} }
@ -92,14 +90,10 @@ dhcp6_srv_configured(CalloutHandle& handle) {
// Get the IO context to post start_service on it. // Get the IO context to post start_service on it.
std::string error(""); std::string error("");
try { try {
handle.getArgument("io_context", main_io_service); IOServiceMgr::instance().registerIOService(io_service);
if (!main_io_service) {
error = "null io_context";
}
main_io_service->registerExternalIOService(io_service);
io_service->post(start_service); io_service->post(start_service);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
error = "no io_context in arguments"; error = "unknown error";
} }
if (!error.empty()) { if (!error.empty()) {
handle.setArgument("error", error); handle.setArgument("error", error);

View File

@ -19,7 +19,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test_leases.csv"
# Path to the Kea LFC application # Path to the Kea LFC application
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc" export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
# Path to test hooks library # 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. # Kea configuration to be stored in the configuration file.
CONFIG="{ CONFIG="{
\"Dhcp6\": \"Dhcp6\":
@ -214,7 +216,7 @@ INVALID_CONFIG_HOOKS_LOAD="{
}, },
\"hooks-libraries\": [ \"hooks-libraries\": [
{ {
\"library\": \"$HOOK_PATH\", \"library\": \"$HOOK_FAIL_LOAD_PATH\",
\"parameters\": { \"parameters\": {
\"mode\": \"fail-on-load\" \"mode\": \"fail-on-load\"
} }
@ -235,7 +237,7 @@ INVALID_CONFIG_HOOKS_LOAD="{
# Invalid configuration (hook point returns error) to check that performing # Invalid configuration (hook point returns error) to check that performing
# extra configuration checks detects the error. # extra configuration checks detects the error.
INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{ INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD="{
\"Dhcp6\": \"Dhcp6\":
{ {
\"interfaces-config\": { \"interfaces-config\": {
@ -271,7 +273,64 @@ INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
}, },
\"hooks-libraries\": [ \"hooks-libraries\": [
{ {
\"library\": \"$HOOK_PATH\", \"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,
\"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_POLL_PATH\",
\"parameters\": { \"parameters\": {
\"mode\": \"fail-without-error\" \"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_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_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_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 password_redact_test "dhcpv6.password_redact_test" "$(kea_dhcp_config 6)" 0

View File

@ -9,6 +9,7 @@
#include <asiolink/asio_wrapper.h> #include <asiolink/asio_wrapper.h>
#include <asiolink/io_address.h> #include <asiolink/io_address.h>
#include <asiolink/io_error.h> #include <asiolink/io_error.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <config/timeouts.h> #include <config/timeouts.h>
#include <netconf/netconf.h> #include <netconf/netconf.h>
@ -65,7 +66,7 @@ NetconfProcess::run() {
size_t size_t
NetconfProcess::runIO() { NetconfProcess::runIO() {
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
size_t cnt = getIOService()->poll(); size_t cnt = getIOService()->poll();
if (!cnt) { if (!cnt) {
cnt = getIOService()->runOne(); cnt = getIOService()->runOne();
@ -89,7 +90,7 @@ NetconfProcess::configure(isc::data::ConstElementPtr config_set,
/// Let postponed hook initializations to run. /// Let postponed hook initializations to run.
try { try {
getIOService()->pollExternalIOServices(); IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::ostringstream err; std::ostringstream err;
err << "Error initializing hooks: " err << "Error initializing hooks: "

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <cc/data.h> #include <cc/data.h>
#include <cc/dhcp_config_error.h> #include <cc/dhcp_config_error.h>
#include <hooks/hooks_manager.h> #include <hooks/hooks_manager.h>
@ -14,6 +15,7 @@
#include <netconf/simple_parser.h> #include <netconf/simple_parser.h>
using namespace isc::data; using namespace isc::data;
using namespace isc::asiolink;
namespace isc { namespace isc {
namespace netconf { namespace netconf {
@ -189,6 +191,7 @@ NetconfSimpleParser::parse(const NetconfConfigPtr& ctx,
// change causes problems when trying to roll back. // change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries(); HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries()); static_cast<void>(HooksManager::unloadLibraries());
IOServiceMgr::instance().clearIOServices();
libraries.loadLibraries(false); libraries.loadLibraries(false);
} }
} }

View File

@ -131,20 +131,25 @@ loop), but each loop pass contains a call to:
@code @code
getIOService()->poll(); getIOService()->poll();
IOServiceMgr::instance().pollIOServices();
@endcode @endcode
which executes callbacks for completed asynchronous operations, such as which executes callbacks for completed asynchronous operations, such as
timers, asynchronous sends and receives. The instance of the IOService timers, asynchronous sends and receives. The instance of the IOService
is owned by the DHCP servers, but hooks libraries must have access to it is owned by the DHCP servers, but hooks libraries must create their own
and must use this instance to schedule asynchronous tasks. This is why IOService access to schedule asynchronous tasks.
the new hook points "dhcp4_srv_configured" and "dhcp6_srv_configured" The hook's IOService object must be registered on the IOServiceMgr by
have been introduced. These hook points are used by the DHCPv4 and the calling registerIOService and must unregister it on "unload" hook point
DHCPv6 servers respectively, to pass the instance of the IOService by calling unregisterIOService.
(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 The hook points "dhcp4_srv_configured" and "dhcp6_srv_configured" have been
calling registerExternalIOService and must unregister it on "unload" hook point introduced to give access to the server configuration if needed.
by calling unregisterExternalIOService. 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 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 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 @code
bool bool
Dhcpv4Srv::run() { Dhcpv[4|6]Srv::run() {
[...]
while (!shutdown_) { while (!shutdown_) {
[...]
try { try {
runOne(); runOne();
IOServiceMgr::instance().pollIOServices();
getIOService()->poll(); getIOService()->poll();
} catch (const std::exception& e) { } catch (const std::exception& e) {
// General catch-all exception that are not caught by more specific // General catch-all exception that are not caught by more specific
// catches. This one is for exceptions derived from std::exception. // catches. This one is for exceptions derived from std::exception.
LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_STD_EXCEPTION) [...]
.arg(e.what());
} catch (...) { } catch (...) {
// General catch-all exception that are not caught by more specific // General catch-all exception that are not caught by more specific
// catches. This one is for other exceptions, not derived from // catches. This one is for other exceptions, not derived from
// std::exception. // std::exception.
LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_EXCEPTION); [...]
} }
} }
return (true); [...]
} }
@endcode @endcode

View File

@ -13,6 +13,7 @@
#include <ha_impl.h> #include <ha_impl.h>
#include <ha_log.h> #include <ha_log.h>
#include <asiolink/io_service.h> #include <asiolink/io_service.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <dhcpsrv/cfgmgr.h> #include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/network_state.h> #include <dhcpsrv/network_state.h>
@ -31,6 +32,7 @@ HAImplPtr impl;
} // end of namespace isc::ha } // end of namespace isc::ha
} // end of namespace isc } // end of namespace isc
using namespace isc::asiolink;
using namespace isc::config; using namespace isc::config;
using namespace isc::data; using namespace isc::data;
using namespace isc::dhcp; using namespace isc::dhcp;
@ -46,18 +48,10 @@ extern "C" {
/// @param handle callout handle. /// @param handle callout handle.
int dhcp4_srv_configured(CalloutHandle& handle) { int dhcp4_srv_configured(CalloutHandle& handle) {
try { 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; isc::dhcp::NetworkStatePtr network_state;
handle.getArgument("network_state", network_state); handle.getArgument("network_state", network_state);
impl->startServices(network_state, HAServerType::DHCPv4); impl->startServices(network_state, HAServerType::DHCPv4);
impl->getMainIOService()->registerExternalIOService(impl->getIOService()); IOServiceMgr::instance().registerIOService(impl->getIOService());
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
LOG_ERROR(ha_logger, HA_DHCP4_START_SERVICE_FAILED) LOG_ERROR(ha_logger, HA_DHCP4_START_SERVICE_FAILED)
@ -164,18 +158,10 @@ int lease4_server_decline(CalloutHandle& handle) {
/// @param handle callout handle. /// @param handle callout handle.
int dhcp6_srv_configured(CalloutHandle& handle) { int dhcp6_srv_configured(CalloutHandle& handle) {
try { 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; isc::dhcp::NetworkStatePtr network_state;
handle.getArgument("network_state", network_state); handle.getArgument("network_state", network_state);
impl->startServices(network_state, HAServerType::DHCPv6); impl->startServices(network_state, HAServerType::DHCPv6);
impl->getMainIOService()->registerExternalIOService(impl->getIOService()); IOServiceMgr::instance().registerIOService(impl->getIOService());
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
LOG_ERROR(ha_logger, HA_DHCP6_START_SERVICE_FAILED) 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 /// @return 0 if deregistration was successful, 1 otherwise
int unload() { int unload() {
if (impl) { if (impl) {
if (impl->getMainIOService()) { IOServiceMgr::instance().unregisterIOService(impl->getIOService());
impl->getMainIOService()->unregisterExternalIOService(impl->getIOService());
}
impl->getIOService()->stop(); impl->getIOService()->stop();
impl->getIOService()->restart(); impl->getIOService()->restart();
try { try {

View File

@ -224,7 +224,7 @@ public:
/// @brief Get the hook I/O service. /// @brief Get the hook I/O service.
/// ///
/// @return the hook I/O service. /// @return the hook I/O service.
isc::asiolink::IOServicePtr& getIOService() { isc::asiolink::IOServicePtr getIOService() {
return (io_service_); return (io_service_);
} }
@ -235,28 +235,11 @@ public:
io_service_ = 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: protected:
/// @brief The hook I/O service. /// @brief The hook I/O service.
isc::asiolink::IOServicePtr io_service_; isc::asiolink::IOServicePtr io_service_;
/// @brief The main I/O service.
isc::asiolink::IOServicePtr main_io_service_;
/// @brief Holds parsed configuration. /// @brief Holds parsed configuration.
HAConfigMapperPtr config_; HAConfigMapperPtr config_;

View File

@ -380,7 +380,6 @@ TEST_F(CloseHATest, close4) {
EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp4_srv_configured_)); EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp4_srv_configured_));
{ {
CalloutHandlePtr handle = HooksManager::createCalloutHandle(); CalloutHandlePtr handle = HooksManager::createCalloutHandle();
handle->setArgument("io_context", io_service);
handle->setArgument("network_state", network_state); handle->setArgument("network_state", network_state);
HooksManager::callCallouts(testHooks.hook_index_dhcp4_srv_configured_, HooksManager::callCallouts(testHooks.hook_index_dhcp4_srv_configured_,
*handle); *handle);
@ -515,7 +514,6 @@ TEST_F(CloseHATest, close4Backup) {
EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp4_srv_configured_)); EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp4_srv_configured_));
{ {
CalloutHandlePtr handle = HooksManager::createCalloutHandle(); CalloutHandlePtr handle = HooksManager::createCalloutHandle();
handle->setArgument("io_context", io_service);
handle->setArgument("network_state", network_state); handle->setArgument("network_state", network_state);
HooksManager::callCallouts(testHooks.hook_index_dhcp4_srv_configured_, HooksManager::callCallouts(testHooks.hook_index_dhcp4_srv_configured_,
*handle); *handle);
@ -619,7 +617,6 @@ TEST_F(CloseHATest, close6) {
EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp6_srv_configured_)); EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp6_srv_configured_));
{ {
CalloutHandlePtr handle = HooksManager::createCalloutHandle(); CalloutHandlePtr handle = HooksManager::createCalloutHandle();
handle->setArgument("io_context", io_service);
handle->setArgument("network_state", network_state); handle->setArgument("network_state", network_state);
HooksManager::callCallouts(testHooks.hook_index_dhcp6_srv_configured_, HooksManager::callCallouts(testHooks.hook_index_dhcp6_srv_configured_,
*handle); *handle);
@ -754,7 +751,6 @@ TEST_F(CloseHATest, close6Backup) {
EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp6_srv_configured_)); EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_dhcp6_srv_configured_));
{ {
CalloutHandlePtr handle = HooksManager::createCalloutHandle(); CalloutHandlePtr handle = HooksManager::createCalloutHandle();
handle->setArgument("io_context", io_service);
handle->setArgument("network_state", network_state); handle->setArgument("network_state", network_state);
HooksManager::callCallouts(testHooks.hook_index_dhcp6_srv_configured_, HooksManager::callCallouts(testHooks.hook_index_dhcp6_srv_configured_,
*handle); *handle);

View File

@ -71,7 +71,6 @@ void
HATest::startHAService() { HATest::startHAService() {
if (HooksManager::calloutsPresent(Hooks.hooks_index_dhcp4_srv_configured_)) { if (HooksManager::calloutsPresent(Hooks.hooks_index_dhcp4_srv_configured_)) {
CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle(); CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
callout_handle->setArgument("io_context", io_service_);
callout_handle->setArgument("network_state", network_state_); callout_handle->setArgument("network_state", network_state_);
HooksManager::callCallouts(Hooks.hooks_index_dhcp4_srv_configured_, HooksManager::callCallouts(Hooks.hooks_index_dhcp4_srv_configured_,
*callout_handle); *callout_handle);

View File

@ -10,6 +10,7 @@
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <dhcpsrv/cfgmgr.h> #include <dhcpsrv/cfgmgr.h>
#include <hooks/hooks.h> #include <hooks/hooks.h>
#include <process/daemon.h> #include <process/daemon.h>
@ -68,15 +69,8 @@ int load(LibraryHandle& /* handle */) {
/// @param handle callout handle passed to the callout. /// @param handle callout handle passed to the callout.
/// @return 0 on success, 1 otherwise. /// @return 0 on success, 1 otherwise.
int dhcp4_srv_configured(CalloutHandle& handle) { 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::getIOService().reset(new IOService());
isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService()); IOServiceMgr::instance().registerIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
return (0); return (0);
} }
@ -87,15 +81,8 @@ int dhcp4_srv_configured(CalloutHandle& handle) {
/// @param handle callout handle passed to the callout. /// @param handle callout handle passed to the callout.
/// @return 0 on success, 1 otherwise. /// @return 0 on success, 1 otherwise.
int dhcp6_srv_configured(CalloutHandle& handle) { 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::getIOService().reset(new IOService());
isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService()); IOServiceMgr::instance().registerIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
return (0); return (0);
} }
@ -107,9 +94,7 @@ int unload() {
// Unregister the factories and remove MySQL backends // Unregister the factories and remove MySQL backends
isc::dhcp::MySqlConfigBackendDHCPv4::unregisterBackendType(); isc::dhcp::MySqlConfigBackendDHCPv4::unregisterBackendType();
isc::dhcp::MySqlConfigBackendDHCPv6::unregisterBackendType(); isc::dhcp::MySqlConfigBackendDHCPv6::unregisterBackendType();
if (isc::dhcp::MySqlConfigBackendImpl::getMainIOService()) { IOServiceMgr::instance().unregisterIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->unregisterExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
}
if (isc::dhcp::MySqlConfigBackendImpl::getIOService()) { if (isc::dhcp::MySqlConfigBackendImpl::getIOService()) {
isc::dhcp::MySqlConfigBackendImpl::getIOService()->stop(); isc::dhcp::MySqlConfigBackendImpl::getIOService()->stop();
isc::dhcp::MySqlConfigBackendImpl::getIOService()->restart(); isc::dhcp::MySqlConfigBackendImpl::getIOService()->restart();

View File

@ -30,7 +30,6 @@ namespace isc {
namespace dhcp { namespace dhcp {
isc::asiolink::IOServicePtr MySqlConfigBackendImpl::io_service_; isc::asiolink::IOServicePtr MySqlConfigBackendImpl::io_service_;
isc::asiolink::IOServicePtr MySqlConfigBackendImpl::main_io_service_;
MySqlConfigBackendImpl:: MySqlConfigBackendImpl::
ScopedAuditRevision::ScopedAuditRevision(MySqlConfigBackendImpl* impl, ScopedAuditRevision::ScopedAuditRevision(MySqlConfigBackendImpl* impl,

View File

@ -839,7 +839,7 @@ public:
/// @brief Get the hook I/O service. /// @brief Get the hook I/O service.
/// ///
/// @return the hook I/O service. /// @return the hook I/O service.
static isc::asiolink::IOServicePtr& getIOService() { static isc::asiolink::IOServicePtr getIOService() {
return (io_service_); return (io_service_);
} }
@ -850,20 +850,6 @@ public:
io_service_ = 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. /// @brief Represents connection to the MySQL database.
db::MySqlConnection conn_; db::MySqlConnection conn_;
@ -882,9 +868,6 @@ private:
/// @brief The hook I/O service. /// @brief The hook I/O service.
static isc::asiolink::IOServicePtr io_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 } // end of namespace isc::dhcp

View File

@ -10,6 +10,7 @@
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <dhcpsrv/cfgmgr.h> #include <dhcpsrv/cfgmgr.h>
#include <hooks/hooks.h> #include <hooks/hooks.h>
#include <process/daemon.h> #include <process/daemon.h>
@ -68,15 +69,8 @@ int load(LibraryHandle& /* handle */) {
/// @param handle callout handle passed to the callout. /// @param handle callout handle passed to the callout.
/// @return 0 on success, 1 otherwise. /// @return 0 on success, 1 otherwise.
int dhcp4_srv_configured(CalloutHandle& handle) { 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::getIOService().reset(new IOService());
isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService()); IOServiceMgr::instance().registerIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
return (0); return (0);
} }
@ -87,15 +81,8 @@ int dhcp4_srv_configured(CalloutHandle& handle) {
/// @param handle callout handle passed to the callout. /// @param handle callout handle passed to the callout.
/// @return 0 on success, 1 otherwise. /// @return 0 on success, 1 otherwise.
int dhcp6_srv_configured(CalloutHandle& handle) { 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::getIOService().reset(new IOService());
isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService()); IOServiceMgr::instance().registerIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
return (0); return (0);
} }
@ -107,9 +94,7 @@ int unload() {
// Unregister the factories and remove PostgreSQL backends // Unregister the factories and remove PostgreSQL backends
isc::dhcp::PgSqlConfigBackendDHCPv4::unregisterBackendType(); isc::dhcp::PgSqlConfigBackendDHCPv4::unregisterBackendType();
isc::dhcp::PgSqlConfigBackendDHCPv6::unregisterBackendType(); isc::dhcp::PgSqlConfigBackendDHCPv6::unregisterBackendType();
if (isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()) { IOServiceMgr::instance().unregisterIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->unregisterExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
}
if (isc::dhcp::PgSqlConfigBackendImpl::getIOService()) { if (isc::dhcp::PgSqlConfigBackendImpl::getIOService()) {
isc::dhcp::PgSqlConfigBackendImpl::getIOService()->stop(); isc::dhcp::PgSqlConfigBackendImpl::getIOService()->stop();
isc::dhcp::PgSqlConfigBackendImpl::getIOService()->restart(); isc::dhcp::PgSqlConfigBackendImpl::getIOService()->restart();

View File

@ -29,7 +29,6 @@ namespace isc {
namespace dhcp { namespace dhcp {
isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::io_service_; isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::io_service_;
isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::main_io_service_;
PgSqlTaggedStatement& PgSqlTaggedStatement&
PgSqlConfigBackendImpl::getStatement(size_t /* index */) const { PgSqlConfigBackendImpl::getStatement(size_t /* index */) const {

View File

@ -863,7 +863,7 @@ public:
/// @brief Get the hook I/O service. /// @brief Get the hook I/O service.
/// ///
/// @return the hook I/O service. /// @return the hook I/O service.
static isc::asiolink::IOServicePtr& getIOService() { static isc::asiolink::IOServicePtr getIOService() {
return (io_service_); return (io_service_);
} }
@ -874,20 +874,6 @@ public:
io_service_ = 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. /// @brief Represents connection to the PostgreSQL database.
db::PgSqlConnection conn_; db::PgSqlConnection conn_;
@ -907,9 +893,6 @@ private:
/// @brief The hook I/O service. /// @brief The hook I/O service.
static isc::asiolink::IOServicePtr io_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 /// @brief Statement index of the SQL statement to use for fetching
/// last inserted id in a given table. /// last inserted id in a given table.
size_t last_insert_id_index_; size_t last_insert_id_index_;

View File

@ -19,7 +19,6 @@ namespace isc {
namespace run_script { namespace run_script {
IOServicePtr RunScriptImpl::io_service_; IOServicePtr RunScriptImpl::io_service_;
IOServicePtr RunScriptImpl::main_io_service_;
RunScriptImpl::RunScriptImpl() : io_context_(new IOService()), name_(), sync_(false) { RunScriptImpl::RunScriptImpl() : io_context_(new IOService()), name_(), sync_(false) {
} }

View File

@ -245,7 +245,7 @@ public:
/// @brief Get the hook I/O service. /// @brief Get the hook I/O service.
/// ///
/// @return the hook I/O service. /// @return the hook I/O service.
isc::asiolink::IOServicePtr& getIOContext() { isc::asiolink::IOServicePtr getIOContext() {
return (io_context_); return (io_context_);
} }
@ -259,7 +259,7 @@ public:
/// @brief Get the hook I/O service. /// @brief Get the hook I/O service.
/// ///
/// @return the hook I/O service. /// @return the hook I/O service.
static isc::asiolink::IOServicePtr& getIOService() { static isc::asiolink::IOServicePtr getIOService() {
return (io_service_); return (io_service_);
} }
@ -270,20 +270,6 @@ public:
io_service_ = 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: private:
/// @brief The IOService object, used for all ASIO operations. /// @brief The IOService object, used for all ASIO operations.
@ -301,9 +287,6 @@ private:
/// @brief The hook I/O service. /// @brief The hook I/O service.
static isc::asiolink::IOServicePtr io_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. /// @brief The type of shared pointers to Run Script implementations.

View File

@ -6,6 +6,7 @@
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <hooks/hooks.h> #include <hooks/hooks.h>
#include <run_script.h> #include <run_script.h>
@ -80,8 +81,8 @@ int load(LibraryHandle& handle) {
/// ///
/// @return always 0. /// @return always 0.
int unload() { int unload() {
if (RunScriptImpl::getMainIOService()) { if (impl) {
RunScriptImpl::getMainIOService()->unregisterExternalIOService(impl->getIOContext()); IOServiceMgr::instance().unregisterIOService(impl->getIOContext());
} }
impl.reset(); impl.reset();
if (RunScriptImpl::getIOService()) { if (RunScriptImpl::getIOService()) {
@ -102,16 +103,8 @@ int unload() {
/// @param handle callout handle. /// @param handle callout handle.
int dhcp4_srv_configured(CalloutHandle& handle) { int dhcp4_srv_configured(CalloutHandle& handle) {
try { 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::setIOService(impl->getIOContext());
RunScriptImpl::getMainIOService()->registerExternalIOService(impl->getIOContext()); IOServiceMgr::instance().registerIOService(impl->getIOContext());
} catch (const exception& ex) { } catch (const exception& ex) {
LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR) LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)
@ -127,16 +120,8 @@ int dhcp4_srv_configured(CalloutHandle& handle) {
/// @param handle callout handle. /// @param handle callout handle.
int dhcp6_srv_configured(CalloutHandle& handle) { int dhcp6_srv_configured(CalloutHandle& handle) {
try { 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::setIOService(impl->getIOContext());
RunScriptImpl::getMainIOService()->registerExternalIOService(impl->getIOContext()); IOServiceMgr::instance().registerIOService(impl->getIOContext());
} catch (const exception& ex) { } catch (const exception& ex) {
LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR) LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)

View 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_endpoint.cc io_endpoint.h
libkea_asiolink_la_SOURCES += io_error.h libkea_asiolink_la_SOURCES += io_error.h
libkea_asiolink_la_SOURCES += io_service.h io_service.cc 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_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_service_thread_pool.cc io_service_thread_pool.h
libkea_asiolink_la_SOURCES += io_socket.h io_socket.cc libkea_asiolink_la_SOURCES += io_socket.h io_socket.cc
@ -82,6 +83,7 @@ libkea_asiolink_include_HEADERS = \
io_endpoint.h \ io_endpoint.h \
io_error.h \ io_error.h \
io_service.h \ io_service.h \
io_service_mgr.h \
io_service_signal.h \ io_service_signal.h \
io_service_thread_pool.h \ io_service_thread_pool.h \
io_socket.h \ io_socket.h \

View File

@ -40,7 +40,7 @@ public:
/// @brief Start the underlying event loop. /// @brief Start the underlying event loop.
/// ///
/// This method does not return control to the caller until /// 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() { void run() {
io_service_.run(); io_service_.run();
}; };
@ -179,25 +179,5 @@ IOService::post(const std::function<void ()>& callback) {
return (io_impl_->post(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 asiolink
} // namespace isc } // namespace isc

View File

@ -54,7 +54,7 @@ public:
/// @brief Start the underlying event loop. /// @brief Start the underlying event loop.
/// ///
/// This method does not return control to the caller until /// 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(); void run();
/// @brief Run the underlying event loop for a single event. /// @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). /// by small bits that are called from time to time).
void post(const std::function<void ()>& callback); 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: private:
/// @brief The implementation. /// @brief The implementation.
boost::shared_ptr<IOServiceImpl> io_impl_; boost::shared_ptr<IOServiceImpl> io_impl_;
/// @brief The list of external IOService objects.
std::list<IOServicePtr> external_io_services_;
}; };
} // namespace asiolink } // namespace asiolink

View File

@ -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

View File

@ -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

View File

@ -34,6 +34,7 @@ run_unittests_SOURCES += tcp_socket_unittest.cc
run_unittests_SOURCES += udp_endpoint_unittest.cc run_unittests_SOURCES += udp_endpoint_unittest.cc
run_unittests_SOURCES += udp_socket_unittest.cc run_unittests_SOURCES += udp_socket_unittest.cc
run_unittests_SOURCES += io_service_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_signal_unittests.cc
run_unittests_SOURCES += io_service_thread_pool_unittests.cc run_unittests_SOURCES += io_service_thread_pool_unittests.cc
run_unittests_SOURCES += dummy_io_callback_unittest.cc run_unittests_SOURCES += dummy_io_callback_unittest.cc

View File

@ -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

View File

@ -45,105 +45,4 @@ TEST(IOService, post) {
EXPECT_EQ(3, called[2]); 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);
}
} }

View File

@ -6,12 +6,14 @@
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <d2srv/d2_config.h> #include <d2srv/d2_config.h>
#include <d2srv/d2_simple_parser.h> #include <d2srv/d2_simple_parser.h>
#include <cc/data.h> #include <cc/data.h>
#include <hooks/hooks_manager.h> #include <hooks/hooks_manager.h>
#include <hooks/hooks_parser.h> #include <hooks/hooks_parser.h>
using namespace isc::asiolink;
using namespace isc::data; using namespace isc::data;
using namespace isc::d2; using namespace isc::d2;
using namespace isc; using namespace isc;
@ -292,6 +294,7 @@ void D2SimpleParser::parse(const D2CfgContextPtr& ctx,
// change causes problems when trying to roll back. // change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries(); HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries()); static_cast<void>(HooksManager::unloadLibraries());
IOServiceMgr::instance().clearIOServices();
libraries.loadLibraries(false); libraries.loadLibraries(false);
} }
} }

View File

@ -5,6 +5,8 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h> #include <config.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h> #include <cc/command_interpreter.h>
#include <process/cfgrpt/config_report.h> #include <process/cfgrpt/config_report.h>
#include <cryptolink/crypto_hash.h> #include <cryptolink/crypto_hash.h>
@ -415,8 +417,6 @@ DControllerBase::configFromFile() {
// case of problems. // case of problems.
storage->applyLoggingCfg(); storage->applyLoggingCfg();
getIOService()->clearExternalIOServices();
answer = updateConfig(module_config); answer = updateConfig(module_config);
// In all cases the right logging configuration is in the context. // In all cases the right logging configuration is in the context.
process_->getCfgMgr()->getContext()->applyLoggingCfg(); process_->getCfgMgr()->getContext()->applyLoggingCfg();
@ -657,8 +657,6 @@ DControllerBase::configSetHandler(const std::string&, ConstElementPtr args) {
// case of problems. // case of problems.
storage->applyLoggingCfg(); storage->applyLoggingCfg();
getIOService()->clearExternalIOServices();
ConstElementPtr answer = updateConfig(module_config); ConstElementPtr answer = updateConfig(module_config);
int rcode = 0; int rcode = 0;
parseAnswer(rcode, answer); parseAnswer(rcode, answer);
@ -848,7 +846,7 @@ DControllerBase::~DControllerBase() {
LOG_ERROR(dctl_logger, DCTL_UNLOAD_LIBRARIES_ERROR).arg(msg); LOG_ERROR(dctl_logger, DCTL_UNLOAD_LIBRARIES_ERROR).arg(msg);
} }
getIOService()->clearExternalIOServices(); IOServiceMgr::instance().clearIOServices();
io_signal_set_.reset(); io_signal_set_.reset();
try { try {