2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-29 13:07:50 +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 <asiolink/asio_wrapper.h>
#include <asiolink/io_service_mgr.h>
#include <agent/ca_process.h>
#include <agent/ca_controller.h>
#include <agent/ca_response_creator_factory.h>
@ -89,7 +90,7 @@ CtrlAgentProcess::run() {
size_t
CtrlAgentProcess::runIO() {
getIOService()->pollExternalIOServices();
IOServiceMgr::instance().pollIOServices();
size_t cnt = getIOService()->poll();
if (!cnt) {
cnt = getIOService()->runOne();
@ -196,7 +197,7 @@ CtrlAgentProcess::configure(isc::data::ConstElementPtr config_set,
/// Let postponed hook initializations to run.
try {
getIOService()->pollExternalIOServices();
IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "

View File

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

View File

@ -57,12 +57,15 @@ to the end of this list.
its (re)configuration. The server provides received and parsed configuration
structures to the hook library.
If the library uses any IO operations, it should create a local IOService
object and register it to the main IOService which is also provided. This way
the local IOService is used by the server to run asynchronous operations. The
hooks library can use the local IOService object to schedule asynchronous
tasks which are triggered by the D2 server's main loop. The hook library
should hold the provided pointer until the library is unloaded at which stage
it must unregister the local IOService.
object and register it to the IOServiceMgr. This way the local IOService is
used by the server to run asynchronous operations. The hooks library can use
the local IOService object to schedule asynchronous tasks which are triggered
by the D2 server's main loop. The hook library can use the local IOService
until the library is unloaded at which stage it must unregister it.
The "io_context" parameter gives access to the main IOService, but it's use
has been deprecated in favor of a local IOService to avoid issues when
unloading the library. The parameter has been deprecated and will be removed
in future versions.
The D2CfgContext object provides access to the D2 running configuration.
- <b>Next step status</b>: If any callout sets the status to DROP, the server

View File

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

View File

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

View File

@ -57,12 +57,15 @@ to the end of this list.
its (re)configuration. The server provides received and parsed configuration
structures to the hook library.
If the library uses any IO operations, it should create a local IOService
object and register it to the main IOService which is also provided. This way
the local IOService is used by the server to run asynchronous operations. The
hooks library can use the local IOService object to schedule asynchronous
tasks which are triggered by the DHCP server's main loop. The hook library
should hold the provided pointer until the library is unloaded at which stage
it must unregister the local IOService.
object and register it to the IOServiceMgr. This way the local IOService is
used by the server to run asynchronous operations. The hooks library can use
the local IOService object to schedule asynchronous tasks which are triggered
by the DHCP server's main loop. The hook library can use the local IOService
until the library is unloaded at which stage it must unregister it.
The "io_context" parameter gives access to the main IOService, but it's use
has been deprecated in favor of a local IOService to avoid issues when
unloading the library. The parameter has been deprecated and will be removed
in future versions.
The NetworkState object provides access to the DHCP service state of the
server and allows for enabling and disabling the DHCP service from the hooks
libraries.

View File

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

View File

@ -6,6 +6,7 @@
#include <config.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h>
#include <config/command_mgr.h>
#include <database/dbaccess_parser.h>
@ -879,6 +880,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
IOServiceMgr::instance().clearIOServices();
const HooksConfig& libraries =
CfgMgr::instance().getStagingCfg()->getHooksConfig();
bool multi_threading_enabled = true;
@ -934,6 +936,16 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
if (notify_libraries) {
return (notify_libraries);
}
/// Let postponed hook initializations to run.
try {
IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
<< ex.what();
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
}
return (answer);

View File

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

View File

@ -19,7 +19,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test_leases.csv"
# Path to the Kea LFC application
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
# Path to test hooks library
HOOK_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/.libs/libco3.so"
HOOK_FAIL_LOAD_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/.libs/libco3.so"
# Path to test hooks library
HOOK_FAIL_POLL_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/.libs/libco4.so"
# Kea configuration to be stored in the configuration file.
CONFIG="{
\"Dhcp4\":
@ -202,7 +204,7 @@ INVALID_CONFIG_HOOKS_LOAD="{
},
\"hooks-libraries\": [
{
\"library\": \"$HOOK_PATH\",
\"library\": \"$HOOK_FAIL_LOAD_PATH\",
\"parameters\": {
\"mode\": \"fail-on-load\"
}
@ -223,14 +225,14 @@ INVALID_CONFIG_HOOKS_LOAD="{
# Invalid configuration (hook point returns error) to check that performing
# extra configuration checks detects the error.
INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD="{
\"Dhcp4\":
{
\"interfaces-config\": {
\"interfaces\": [ ]
},
\"multi-threading\": {
\"enable-multi-threading\": false
\"enable-multi-threading\": false
},
\"valid-lifetime\": 4000,
\"renew-timer\": 1000,
@ -254,7 +256,59 @@ INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
},
\"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\": {
\"mode\": \"fail-without-error\"
}
@ -582,5 +636,6 @@ syntax_check_test "dhcpv4.syntax_check_success" "${CONFIG}" 0 -t
syntax_check_test "dhcpv4.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1 -t
syntax_check_test "dhcpv4.syntax_check_bad_values" "${CONFIG_BAD_VALUES}" 1 -t
syntax_check_test "dhcpv4.syntax_check_hooks_load_fail" "${INVALID_CONFIG_HOOKS_LOAD}" 1 -T
syntax_check_test "dhcpv4.syntax_check_hooks_callout_fail" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL}" 1 -T
syntax_check_test "dhcpv4.syntax_check_hooks_callout_fail_on_load" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD}" 1 -T
syntax_check_test "dhcpv4.syntax_check_hooks_callout_fail_on_poll" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_POLL}" 1 -T
password_redact_test "dhcpv4.password_redact_test" "$(kea_dhcp_config 4)" 0

View File

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

View File

@ -57,12 +57,15 @@ to the end of this list.
its (re)configuration. The server provides received and parsed configuration
structures to the hook library.
If the library uses any IO operations, it should create a local IOService
object and register it to the main IOService which is also provided. This way
the local IOService is used by the server to run asynchronous operations. The
hooks library can use the local IOService object to schedule asynchronous
tasks which are triggered by the DHCP server's main loop. The hook library
should hold the provided pointer until the library is unloaded at which stage
it must unregister the local IOService.
object and register it to the IOServiceMgr. This way the local IOService is
used by the server to run asynchronous operations. The hooks library can use
the local IOService object to schedule asynchronous tasks which are triggered
by the DHCP server's main loop. The hook library can use the local IOService
until the library is unloaded at which stage it must unregister it.
The "io_context" parameter gives access to the main IOService, but it's use
has been deprecated in favor of a local IOService to avoid issues when
unloading the library. The parameter has been deprecated and will be removed
in future versions.
The NetworkState object provides access to the DHCP service state of the
server and allows for enabling and disabling the DHCP service from the hooks
libraries.

View File

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

View File

@ -7,6 +7,7 @@
#include <config.h>
#include <asiolink/io_address.h>
#include <asiolink/io_service_mgr.h>
#include <cc/data.h>
#include <cc/command_interpreter.h>
#include <config/command_mgr.h>
@ -1012,6 +1013,7 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
IOServiceMgr::instance().clearIOServices();
const HooksConfig& libraries =
CfgMgr::instance().getStagingCfg()->getHooksConfig();
bool multi_threading_enabled = true;
@ -1067,6 +1069,16 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
if (notify_libraries) {
return (notify_libraries);
}
/// Let postponed hook initializations to run.
try {
IOServiceMgr::instance().pollIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
<< ex.what();
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
}
return (answer);

View File

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

View File

@ -19,7 +19,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test_leases.csv"
# Path to the Kea LFC application
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
# Path to test hooks library
HOOK_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/.libs/libco3.so"
HOOK_FAIL_LOAD_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/.libs/libco3.so"
# Path to test hooks library
HOOK_FAIL_POLL_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/.libs/libco3.so"
# Kea configuration to be stored in the configuration file.
CONFIG="{
\"Dhcp6\":
@ -214,7 +216,7 @@ INVALID_CONFIG_HOOKS_LOAD="{
},
\"hooks-libraries\": [
{
\"library\": \"$HOOK_PATH\",
\"library\": \"$HOOK_FAIL_LOAD_PATH\",
\"parameters\": {
\"mode\": \"fail-on-load\"
}
@ -235,18 +237,18 @@ INVALID_CONFIG_HOOKS_LOAD="{
# Invalid configuration (hook point returns error) to check that performing
# extra configuration checks detects the error.
INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD="{
\"Dhcp6\":
{
\"interfaces-config\": {
\"interfaces\": [ ]
\"interfaces\": [ ]
},
\"multi-threading\": {
\"enable-multi-threading\": false
\"enable-multi-threading\": false
},
\"server-id\": {
\"type\": \"LLT\",
\"persist\": false
\"type\": \"LLT\",
\"persist\": false
},
\"preferred-lifetime\": 3000,
\"valid-lifetime\": 4000,
@ -271,7 +273,64 @@ INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
},
\"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\": {
\"mode\": \"fail-without-error\"
}
@ -602,5 +661,6 @@ syntax_check_test "dhcpv6.syntax_check_success" "${CONFIG}" 0 -t
syntax_check_test "dhcpv6.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1 -t
syntax_check_test "dhcpv6.syntax_check_bad_values" "${CONFIG_BAD_VALUES}" 1 -t
syntax_check_test "dhcpv6.syntax_check_hooks_load_fail" "${INVALID_CONFIG_HOOKS_LOAD}" 1 -T
syntax_check_test "dhcpv6.syntax_check_hooks_callout_fail" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL}" 1 -T
syntax_check_test "dhcpv6.syntax_check_hooks_callout_fail_on_load" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_LOAD}" 1 -T
syntax_check_test "dhcpv6.syntax_check_hooks_callout_fail_on_poll" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL_ON_POLL}" 1 -T
password_redact_test "dhcpv6.password_redact_test" "$(kea_dhcp_config 6)" 0

View File

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

View File

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

View File

@ -131,20 +131,25 @@ loop), but each loop pass contains a call to:
@code
getIOService()->poll();
IOServiceMgr::instance().pollIOServices();
@endcode
which executes callbacks for completed asynchronous operations, such as
timers, asynchronous sends and receives. The instance of the IOService
is owned by the DHCP servers, but hooks libraries must have access to it
and must use this instance to schedule asynchronous tasks. This is why
the new hook points "dhcp4_srv_configured" and "dhcp6_srv_configured"
have been introduced. These hook points are used by the DHCPv4 and the
DHCPv6 servers respectively, to pass the instance of the IOService
(via "io_context" argument) to the hooks libraries which require to
schedule asynchronous tasks.
The hook's IOService object must be registered on the server's main IOService by
calling registerExternalIOService and must unregister it on "unload" hook point
by calling unregisterExternalIOService.
is owned by the DHCP servers, but hooks libraries must create their own
IOService access to schedule asynchronous tasks.
The hook's IOService object must be registered on the IOServiceMgr by
calling registerIOService and must unregister it on "unload" hook point
by calling unregisterIOService.
The hook points "dhcp4_srv_configured" and "dhcp6_srv_configured" have been
introduced to give access to the server configuration if needed.
These hook points are used by the DHCPv4 and the DHCPv6 servers respectively, to
pass the server configuration to the hooks libraries which require it.
The "io_context" parameter gives access to the main IOService, but it's use
has been deprecated in favor of a local IOService to avoid issues when
unloading the library. The parameter will be removed in future versions.
It is also worth to note that the blocking reception of the DHCP packets
may cause up to 1 second delays in the asynchronous operations. This is
@ -152,25 +157,27 @@ due to the structure of the main server loop:
@code
bool
Dhcpv4Srv::run() {
Dhcpv[4|6]Srv::run() {
[...]
while (!shutdown_) {
[...]
try {
runOne();
IOServiceMgr::instance().pollIOServices();
getIOService()->poll();
} catch (const std::exception& e) {
// General catch-all exception that are not caught by more specific
// catches. This one is for exceptions derived from std::exception.
LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_STD_EXCEPTION)
.arg(e.what());
[...]
} catch (...) {
// General catch-all exception that are not caught by more specific
// catches. This one is for other exceptions, not derived from
// std::exception.
LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_EXCEPTION);
[...]
}
}
return (true);
[...]
}
@endcode

View File

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

View File

@ -224,7 +224,7 @@ public:
/// @brief Get the hook I/O service.
///
/// @return the hook I/O service.
isc::asiolink::IOServicePtr& getIOService() {
isc::asiolink::IOServicePtr getIOService() {
return (io_service_);
}
@ -235,28 +235,11 @@ public:
io_service_ = io_service;
}
/// @brief Get the main I/O service.
///
/// @return the main I/O service.
isc::asiolink::IOServicePtr& getMainIOService() {
return (main_io_service_);
}
/// @brief Set the main I/O service.
///
/// @param io_service the main I/O service.
void setMainIOService(isc::asiolink::IOServicePtr io_service) {
main_io_service_ = io_service;
}
protected:
/// @brief The hook I/O service.
isc::asiolink::IOServicePtr io_service_;
/// @brief The main I/O service.
isc::asiolink::IOServicePtr main_io_service_;
/// @brief Holds parsed configuration.
HAConfigMapperPtr config_;

View File

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

View File

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

View File

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

View File

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

View File

@ -839,7 +839,7 @@ public:
/// @brief Get the hook I/O service.
///
/// @return the hook I/O service.
static isc::asiolink::IOServicePtr& getIOService() {
static isc::asiolink::IOServicePtr getIOService() {
return (io_service_);
}
@ -850,20 +850,6 @@ public:
io_service_ = io_service;
}
/// @brief Get the main I/O service.
///
/// @return the main I/O service.
static isc::asiolink::IOServicePtr& getMainIOService() {
return (main_io_service_);
}
/// @brief Set the main I/O service.
///
/// @param io_service the main I/O service.
static void setMainIOService(isc::asiolink::IOServicePtr io_service) {
main_io_service_ = io_service;
}
/// @brief Represents connection to the MySQL database.
db::MySqlConnection conn_;
@ -882,9 +868,6 @@ private:
/// @brief The hook I/O service.
static isc::asiolink::IOServicePtr io_service_;
/// @brief The main I/O service.
static isc::asiolink::IOServicePtr main_io_service_;
};
} // end of namespace isc::dhcp

View File

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

View File

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

View File

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

View File

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

View File

@ -245,7 +245,7 @@ public:
/// @brief Get the hook I/O service.
///
/// @return the hook I/O service.
isc::asiolink::IOServicePtr& getIOContext() {
isc::asiolink::IOServicePtr getIOContext() {
return (io_context_);
}
@ -259,7 +259,7 @@ public:
/// @brief Get the hook I/O service.
///
/// @return the hook I/O service.
static isc::asiolink::IOServicePtr& getIOService() {
static isc::asiolink::IOServicePtr getIOService() {
return (io_service_);
}
@ -270,20 +270,6 @@ public:
io_service_ = io_service;
}
/// @brief Get the main I/O service.
///
/// @return the main I/O service.
static isc::asiolink::IOServicePtr& getMainIOService() {
return (main_io_service_);
}
/// @brief Set the main I/O service.
///
/// @param io_service the main I/O service.
static void setMainIOService(isc::asiolink::IOServicePtr io_service) {
main_io_service_ = io_service;
}
private:
/// @brief The IOService object, used for all ASIO operations.
@ -301,9 +287,6 @@ private:
/// @brief The hook I/O service.
static isc::asiolink::IOServicePtr io_service_;
/// @brief The main I/O service.
static isc::asiolink::IOServicePtr main_io_service_;
};
/// @brief The type of shared pointers to Run Script implementations.

View File

@ -6,6 +6,7 @@
#include <config.h>
#include <asiolink/io_service_mgr.h>
#include <cc/command_interpreter.h>
#include <hooks/hooks.h>
#include <run_script.h>
@ -80,8 +81,8 @@ int load(LibraryHandle& handle) {
///
/// @return always 0.
int unload() {
if (RunScriptImpl::getMainIOService()) {
RunScriptImpl::getMainIOService()->unregisterExternalIOService(impl->getIOContext());
if (impl) {
IOServiceMgr::instance().unregisterIOService(impl->getIOContext());
}
impl.reset();
if (RunScriptImpl::getIOService()) {
@ -102,16 +103,8 @@ int unload() {
/// @param handle callout handle.
int dhcp4_srv_configured(CalloutHandle& handle) {
try {
handle.getArgument("io_context", RunScriptImpl::getMainIOService());
if (!RunScriptImpl::getMainIOService()) {
// Should not happen!
handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
const string error("Error: io_context is null");
handle.setArgument("error", error);
return (1);
}
RunScriptImpl::setIOService(impl->getIOContext());
RunScriptImpl::getMainIOService()->registerExternalIOService(impl->getIOContext());
IOServiceMgr::instance().registerIOService(impl->getIOContext());
} catch (const exception& ex) {
LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)
@ -127,16 +120,8 @@ int dhcp4_srv_configured(CalloutHandle& handle) {
/// @param handle callout handle.
int dhcp6_srv_configured(CalloutHandle& handle) {
try {
handle.getArgument("io_context", RunScriptImpl::getMainIOService());
if (!RunScriptImpl::getMainIOService()) {
// Should not happen!
handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
const string error("Error: io_context is null");
handle.setArgument("error", error);
return (1);
}
RunScriptImpl::setIOService(impl->getIOContext());
RunScriptImpl::getMainIOService()->registerExternalIOService(impl->getIOContext());
IOServiceMgr::instance().registerIOService(impl->getIOContext());
} catch (const exception& ex) {
LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)

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

View File

@ -40,7 +40,7 @@ public:
/// @brief Start the underlying event loop.
///
/// This method does not return control to the caller until
/// the @ref stop() method is called via some handler.
/// the @ref stop() or @ref stopWork() method is called via some handler.
void run() {
io_service_.run();
};
@ -179,25 +179,5 @@ IOService::post(const std::function<void ()>& callback) {
return (io_impl_->post(callback));
}
void
IOService::registerExternalIOService(IOServicePtr io_service) {
external_io_services_.push_back(io_service);
}
void
IOService::unregisterExternalIOService(IOServicePtr io_service) {
auto it = std::find(external_io_services_.begin(), external_io_services_.end(), io_service);
if (it != external_io_services_.end()) {
external_io_services_.erase(it);
}
}
void
IOService::pollExternalIOServices() {
for (auto& io_service : external_io_services_) {
io_service->poll();
}
}
} // namespace asiolink
} // namespace isc

View File

@ -54,7 +54,7 @@ public:
/// @brief Start the underlying event loop.
///
/// This method does not return control to the caller until
/// the @ref stop() method is called via some handler.
/// the @ref stop() or @ref stopWork() method is called via some handler.
void run();
/// @brief Run the underlying event loop for a single event.
@ -120,38 +120,10 @@ public:
/// by small bits that are called from time to time).
void post(const std::function<void ()>& callback);
/// @brief Register external IOService.
///
/// @param io_service The external IOService to be registered.
void registerExternalIOService(IOServicePtr io_service);
/// @brief Unregister external IOService.
///
/// @param io_service The external IOService to be unregistered.
void unregisterExternalIOService(IOServicePtr io_service);
/// @brief Clear the list of external IOService objects.
void clearExternalIOServices() {
external_io_services_.clear();
}
/// @brief The count of external IOService objects.
///
// @return The count of external IOService objects.
size_t externalIOServiceCount() {
return (external_io_services_.size());
}
/// @brief Poll external IOService objects.
void pollExternalIOServices();
private:
/// @brief The implementation.
boost::shared_ptr<IOServiceImpl> io_impl_;
/// @brief The list of external IOService objects.
std::list<IOServicePtr> external_io_services_;
};
} // namespace asiolink

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

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

View File

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