size_t
CtrlAgentProcess::runIO() {
+ getIOService()->pollExternalIOServices();
size_t cnt = getIOService()->poll();
if (!cnt) {
cnt = getIOService()->runOne();
int rcode = 0;
config::parseAnswer(rcode, answer);
+
+ /// Let postponed hook initializations to run.
+ try {
+ getIOService()->pollExternalIOServices();
+ } 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);
}
CheckExistsAddTransaction::
CheckExistsAddTransaction(asiolink::IOServicePtr& io_service,
- dhcp_ddns::NameChangeRequestPtr& ncr,
- DdnsDomainPtr& forward_domain,
- DdnsDomainPtr& reverse_domain,
- D2CfgMgrPtr& cfg_mgr)
+ dhcp_ddns::NameChangeRequestPtr& ncr,
+ DdnsDomainPtr& forward_domain,
+ DdnsDomainPtr& reverse_domain,
+ D2CfgMgrPtr& cfg_mgr)
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
cfg_mgr) {
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_ADD) {
CheckExistsRemoveTransaction::
CheckExistsRemoveTransaction(asiolink::IOServicePtr& io_service,
- dhcp_ddns::NameChangeRequestPtr& ncr,
- DdnsDomainPtr& forward_domain,
- DdnsDomainPtr& reverse_domain,
- D2CfgMgrPtr& cfg_mgr)
+ dhcp_ddns::NameChangeRequestPtr& ncr,
+ DdnsDomainPtr& forward_domain,
+ DdnsDomainPtr& reverse_domain,
+ D2CfgMgrPtr& cfg_mgr)
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
cfg_mgr) {
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_REMOVE) {
- @b Description: this callout is executed when the server has completed
its (re)configuration. The server provides received and parsed configuration
- structures to the hook library. It also provides a pointer to the IOService
- object which is used by the server to run asynchronous operations. The hooks
- libraries can use this IOService object to schedule asynchronous tasks which
- are triggered by the Kea DHCP DDNS's main loop. The hook library should hold
- the provided pointer until the library is unloaded. The D2CfgContext
- object provides access to the D2 running 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.
+ 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
considers the configuration is incorrect and rejects it using the error
size_t
D2Process::runIO() {
+ getIOService()->pollExternalIOServices();
// 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
// service is stopped it will return immediately with a cnt of zero.
cnt = getIOService()->runOne();
}
-
return (cnt);
}
}
}
+ /// Let postponed hook initializations to run.
+ try {
+ getIOService()->pollExternalIOServices();
+ } catch (const std::exception& ex) {
+ std::ostringstream err;
+ err << "Error initializing hooks: "
+ << ex.what();
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
+ }
+
// If we are here, configuration was valid, at least it parsed correctly
// and therefore contained no invalid values.
// Return the success answer from above.
NameRemoveTransaction::
NameRemoveTransaction(asiolink::IOServicePtr& io_service,
- dhcp_ddns::NameChangeRequestPtr& ncr,
- DdnsDomainPtr& forward_domain,
- DdnsDomainPtr& reverse_domain,
- D2CfgMgrPtr& cfg_mgr)
+ dhcp_ddns::NameChangeRequestPtr& ncr,
+ DdnsDomainPtr& forward_domain,
+ DdnsDomainPtr& reverse_domain,
+ D2CfgMgrPtr& cfg_mgr)
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
cfg_mgr) {
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_REMOVE) {
SimpleAddTransaction::
SimpleAddTransaction(asiolink::IOServicePtr& io_service,
- dhcp_ddns::NameChangeRequestPtr& ncr,
- DdnsDomainPtr& forward_domain,
- DdnsDomainPtr& reverse_domain,
- D2CfgMgrPtr& cfg_mgr)
+ dhcp_ddns::NameChangeRequestPtr& ncr,
+ DdnsDomainPtr& forward_domain,
+ DdnsDomainPtr& reverse_domain,
+ D2CfgMgrPtr& cfg_mgr)
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
cfg_mgr) {
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_ADD) {
SimpleAddWithoutDHCIDTransaction::
SimpleAddWithoutDHCIDTransaction(asiolink::IOServicePtr& io_service,
- dhcp_ddns::NameChangeRequestPtr& ncr,
- DdnsDomainPtr& forward_domain,
- DdnsDomainPtr& reverse_domain,
- D2CfgMgrPtr& cfg_mgr)
+ dhcp_ddns::NameChangeRequestPtr& ncr,
+ DdnsDomainPtr& forward_domain,
+ DdnsDomainPtr& reverse_domain,
+ D2CfgMgrPtr& cfg_mgr)
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
cfg_mgr) {
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_ADD) {
SimpleRemoveTransaction::
SimpleRemoveTransaction(asiolink::IOServicePtr& io_service,
- dhcp_ddns::NameChangeRequestPtr& ncr,
- DdnsDomainPtr& forward_domain,
- DdnsDomainPtr& reverse_domain,
- D2CfgMgrPtr& cfg_mgr)
+ dhcp_ddns::NameChangeRequestPtr& ncr,
+ DdnsDomainPtr& forward_domain,
+ DdnsDomainPtr& reverse_domain,
+ D2CfgMgrPtr& cfg_mgr)
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
cfg_mgr) {
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_REMOVE) {
SimpleRemoveWithoutDHCIDTransaction::
SimpleRemoveWithoutDHCIDTransaction(asiolink::IOServicePtr& io_service,
- dhcp_ddns::NameChangeRequestPtr& ncr,
- DdnsDomainPtr& forward_domain,
- DdnsDomainPtr& reverse_domain,
- D2CfgMgrPtr& cfg_mgr)
+ dhcp_ddns::NameChangeRequestPtr& ncr,
+ DdnsDomainPtr& forward_domain,
+ DdnsDomainPtr& reverse_domain,
+ D2CfgMgrPtr& cfg_mgr)
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
cfg_mgr) {
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_REMOVE) {
// Post a server IO error event. This simulates an IO error occurring
// and a need to select the new server.
ASSERT_NO_THROW(name_remove->postNextEvent(NameChangeTransaction::
- SERVER_IO_ERROR_EVT))
+ SERVER_IO_ERROR_EVT))
<< " num_servers: " << num_servers
<< " selections: " << i;
}
/// @return the number of default items added to the tree
size_t setDefaults(data::ElementPtr config) {
return (SimpleParser::setListDefaults(config, D2SimpleParser::
- TSIG_KEY_DEFAULTS));
+ TSIG_KEY_DEFAULTS));
}
/// @brief Attempts to parse the given element into a list of TSIGKeyInfos
/// @return the number of default items added to the tree
virtual size_t setDefaults(data::ElementPtr config) {
return (SimpleParser::setDefaults(config, D2SimpleParser::
- DNS_SERVER_DEFAULTS));
+ DNS_SERVER_DEFAULTS));
}
/// @brief Attempts to parse the given element into a DnsServerInfo
/// @return the number of default items added to the tree
virtual size_t setDefaults(data::ElementPtr config) {
return (SimpleParser::setListDefaults(config, D2SimpleParser::
- DNS_SERVER_DEFAULTS));
+ DNS_SERVER_DEFAULTS));
}
/// @brief Attempts to parse the given element into a list of DnsServerInfos
// We don't use SimpleParser::setListDefaults() as this does
// not handle sub-lists or sub-maps
for (auto const& domain : config->listValue()) {
- cnt += D2SimpleParser::
- setDdnsDomainDefaults(domain, D2SimpleParser::
- DDNS_DOMAIN_DEFAULTS);
+ cnt += D2SimpleParser::setDdnsDomainDefaults(domain, D2SimpleParser::
+ DDNS_DOMAIN_DEFAULTS);
}
return (cnt);
// Post a server IO error event. This simulates an IO error occurring
// and a need to select the new server.
ASSERT_NO_THROW(name_remove->postNextEvent(NameChangeTransaction::
- SERVER_IO_ERROR_EVT))
+ SERVER_IO_ERROR_EVT))
<< " num_servers: " << num_servers
<< " selections: " << i;
}
// Post a server IO error event. This simulates an IO error occurring
// and a need to select the new server.
ASSERT_NO_THROW(name_remove->postNextEvent(NameChangeTransaction::
- SERVER_IO_ERROR_EVT));
+ SERVER_IO_ERROR_EVT));
}
// We should have exhausted the list of servers. Processing another
// Post a server IO error event. This simulates an IO error occurring
// and a need to select the new server.
ASSERT_NO_THROW(name_remove->postNextEvent(NameChangeTransaction::
- SERVER_IO_ERROR_EVT));
+ SERVER_IO_ERROR_EVT));
}
// We should have exhausted the list of servers. Processing another
HookLibsCollection loaded = HooksManager::getLibraryInfo();
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
+ getIOService()->clearExternalIOServices();
bool multi_threading_enabled = true;
uint32_t thread_count = 0;
uint32_t queue_size = 0;
/// Let postponed hook initializations to run.
try {
- getIOService()->poll();
+ getIOService()->pollExternalIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
- @b Description: this callout is executed when the server has completed
its (re)configuration. The server provides received and parsed configuration
- structures to the hook library. It also provides a pointer to the IOService
- object which is used by the server to run asynchronous operations. The hooks
- libraries can use this 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. 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.
+ 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.
+ 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.
- <b>Next step status</b>: If any callout sets the status to DROP, the server
will interrupt the reconfiguration process. The hook callout is expected to
}
LOG_ERROR(dhcp4_logger, DHCP4_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
}
+ getIOService()->clearExternalIOServices();
io_service_->stop();
io_service_->restart();
try {
#endif // ENABLE_AFL
try {
runOne();
+ getIOService()->pollExternalIOServices();
getIOService()->poll();
} catch (const std::exception& e) {
// General catch-all exception that are not caught by more specific
isc_throw(isc::Unexpected, "start service failed");
};
+IOServicePtr io_service;
+IOServicePtr main_io_service;
+
} // end anonymous
// Functions accessed by the hooks framework use C linkage to avoid the name
int
do_load_impl(LibraryHandle& handle) {
+ io_service.reset(new IOService());
// Determine if this callout is configured to fail.
isc::dhcp::SrvConfigPtr config;
isc::data::ConstElementPtr const& parameters(handle.getParameters());
return (0);
}
+int
+do_unload_impl() {
+ if (main_io_service) {
+ main_io_service->unregisterExternalIOService(io_service);
+ }
+ return (0);
+}
+
int (*do_load)(LibraryHandle& handle) = do_load_impl;
-int (*do_unload)();
+int (*do_unload)() = do_unload_impl;
/// @brief Callout which appends library number and provided arguments to
/// the marker file for dhcp4_srv_configured callout.
// Get the IO context to post start_service on it.
std::string error("");
- IOServicePtr io_context;
try {
- handle.getArgument("io_context", io_context);
- if (!io_context) {
+ handle.getArgument("io_context", main_io_service);
+ if (!main_io_service) {
error = "null io_context";
}
- io_context->post(start_service);
+ main_io_service->registerExternalIOService(io_service);
+ io_service->post(start_service);
} catch (const std::exception& ex) {
error = "no io_context in arguments";
}
HookLibsCollection loaded = HooksManager::getLibraryInfo();
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
+ getIOService()->clearExternalIOServices();
bool multi_threading_enabled = true;
uint32_t thread_count = 0;
uint32_t queue_size = 0;
/// Let postponed hook initializations to run.
try {
- getIOService()->poll();
+ getIOService()->pollExternalIOServices();
} catch (const std::exception& ex) {
std::ostringstream err;
err << "Error initializing hooks: "
- @b Description: this callout is executed when the server has completed
its (re)configuration. The server provides received and parsed configuration
- structures to the hook library. It also provides a pointer to the IOService
- object which is used by the server to run asynchronous operations. The hooks
- libraries can use this 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. 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.
-
+ 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.
+ 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.
- <b>Next step status</b>: If any callout sets the status to DROP, the server
will interrupt the reconfiguration process. The hook callout is expected to
}
LOG_ERROR(dhcp6_logger, DHCP6_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
}
+ getIOService()->clearExternalIOServices();
io_service_->stop();
io_service_->restart();
try {
#endif // ENABLE_AFL
try {
runOne();
+ getIOService()->pollExternalIOServices();
getIOService()->poll();
} catch (const std::exception& e) {
// General catch-all standard exceptions that are not caught by more
isc_throw(isc::Unexpected, "start service failed");
};
+IOServicePtr io_service;
+IOServicePtr main_io_service;
+
} // end anonymous
// Functions accessed by the hooks framework use C linkage to avoid the name
int
do_load_impl(LibraryHandle& handle) {
+ io_service.reset(new IOService());
// Determine if this callout is configured to fail.
isc::dhcp::SrvConfigPtr config;
isc::data::ConstElementPtr const& parameters(handle.getParameters());
return (0);
}
+int
+do_unload_impl() {
+ if (main_io_service) {
+ main_io_service->unregisterExternalIOService(io_service);
+ }
+ return (0);
+}
+
int (*do_load)(LibraryHandle& handle) = do_load_impl;
-int (*do_unload)();
+int (*do_unload)() = do_unload_impl;
/// @brief Callout which appends library number and provided arguments to
/// the marker file for dhcp6_srv_configured callout.
// Get the IO context to post start_service on it.
std::string error("");
- IOServicePtr io_context;
try {
- handle.getArgument("io_context", io_context);
- if (!io_context) {
+ handle.getArgument("io_context", main_io_service);
+ if (!main_io_service) {
error = "null io_context";
}
- io_context->post(start_service);
+ main_io_service->registerExternalIOService(io_service);
+ io_service->post(start_service);
} catch (const std::exception& ex) {
error = "no io_context in arguments";
}
size_t
NetconfProcess::runIO() {
+ getIOService()->pollExternalIOServices();
size_t cnt = getIOService()->poll();
if (!cnt) {
cnt = getIOService()->runOne();
getCfgMgr()->simpleParseConfig(config_set, check_only);
int rcode = 0;
config::parseAnswer(rcode, answer);
+
+ /// Let postponed hook initializations to run.
+ try {
+ getIOService()->pollExternalIOServices();
+ } catch (const std::exception& ex) {
+ std::ostringstream err;
+ err << "Error initializing hooks: "
+ << ex.what();
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
+ }
+
return (answer);
}
#include <config.h>
-#include <cc/data.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
#include <testutils/gtest_utils.h>
-#include <testutils/lib_load_test_fixture.h>
#include <gtest/gtest.h>
#include <errno.h>
#include <config.h>
-#include <flex_option.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
-#include <testutils/lib_load_test_fixture.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
+#include <testutils/gtest_utils.h>
#include <gtest/gtest.h>
#include <errno.h>
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.
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
/// @param handle callout handle.
int dhcp4_srv_configured(CalloutHandle& handle) {
try {
- isc::asiolink::IOServicePtr io_service;
- handle.getArgument("io_context", io_service);
- if (!io_service) {
+ 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");
}
isc::dhcp::NetworkStatePtr network_state;
handle.getArgument("network_state", network_state);
- impl->startServices(io_service, network_state, HAServerType::DHCPv4);
+ impl->startServices(network_state, HAServerType::DHCPv4);
+ impl->getMainIOService()->registerExternalIOService(impl->getIOService());
} catch (const std::exception& ex) {
LOG_ERROR(ha_logger, HA_DHCP4_START_SERVICE_FAILED)
/// @param handle callout handle.
int dhcp6_srv_configured(CalloutHandle& handle) {
try {
- isc::asiolink::IOServicePtr io_service;
- handle.getArgument("io_context", io_service);
- if (!io_service) {
+ 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");
}
isc::dhcp::NetworkStatePtr network_state;
handle.getArgument("network_state", network_state);
- impl->startServices(io_service, network_state, HAServerType::DHCPv6);
+ impl->startServices(network_state, HAServerType::DHCPv6);
+ impl->getMainIOService()->registerExternalIOService(impl->getIOService());
} catch (const std::exception& ex) {
LOG_ERROR(ha_logger, HA_DHCP6_START_SERVICE_FAILED)
///
/// @return 0 if deregistration was successful, 1 otherwise
int unload() {
+ if (impl) {
+ if (impl->getMainIOService()) {
+ impl->getMainIOService()->unregisterExternalIOService(impl->getIOService());
+ }
+ impl->getIOService()->stop();
+ impl->getIOService()->restart();
+ try {
+ impl->getIOService()->poll();
+ } catch (...) {
+ }
+ }
impl.reset();
LOG_INFO(ha_logger, HA_DEINIT_OK);
return (0);
namespace ha {
HAImpl::HAImpl()
- : config_(), services_(new HAServiceMapper()) {
+ : io_service_(new IOService()), config_(), services_(new HAServiceMapper()) {
}
void
}
void
-HAImpl::startServices(const IOServicePtr& io_service,
- const NetworkStatePtr& network_state,
+HAImpl::startServices(const NetworkStatePtr& network_state,
const HAServerType& server_type) {
auto configs = config_->getAll();
for (auto id = 0; id < configs.size(); ++id) {
// Create the HA service and crank up the state machine.
- auto service = boost::make_shared<HAService>(id, io_service, network_state,
+ auto service = boost::make_shared<HAService>(id, io_service_, network_state,
configs[id], server_type);
for (auto const& peer_config : configs[id]->getAllServersConfig()) {
services_->map(peer_config.first, service);
}
// Schedule a start of the services. This ensures we begin after
// the dust has settled and Kea MT mode has been firmly established.
- io_service->post([&]() {
+ io_service_->post([&]() {
for (auto const& service : services_->getAll()) {
service->startClientAndListener();
}
/// The caller must ensure that the HA configuration is valid before
/// calling this function.
///
- /// @param io_service IO service object provided by the DHCP server.
/// @param network_state pointer to the object holding a state of the
/// DHCP service (enabled/disabled).
/// @param server_type DHCP server type for which the HA service should
/// be created.
- void startServices(const asiolink::IOServicePtr& io_service,
- const dhcp::NetworkStatePtr& network_state,
+ void startServices(const dhcp::NetworkStatePtr& network_state,
const HAServerType& server_type);
/// @brief Destructor.
HAServicePtr getHAServiceByServerName(const std::string& command_name,
data::ConstElementPtr args) const;
+ /// @brief Get the hook I/O service.
+ ///
+ /// @return the hook I/O service.
+ isc::asiolink::IOServicePtr& getIOService() {
+ return (io_service_);
+ }
+
+ /// @brief Set the hook I/O service.
+ ///
+ /// @param io_service the hook I/O service.
+ void setIOService(isc::asiolink::IOServicePtr io_service) {
+ io_service_ = io_service;
+ }
+
+ /// @brief Get the main I/O service.
+ ///
+ /// @return the main I/O service.
+ isc::asiolink::IOServicePtr& getMainIOService() {
+ return (main_io_service_);
+ }
+
+ /// @brief Set the main I/O service.
+ ///
+ /// @param io_service the main I/O service.
+ void setMainIOService(isc::asiolink::IOServicePtr io_service) {
+ main_io_service_ = io_service;
+ }
+
protected:
+ /// @brief The hook I/O service.
+ isc::asiolink::IOServicePtr io_service_;
+
+ /// @brief The main I/O service.
+ isc::asiolink::IOServicePtr main_io_service_;
+
/// @brief Holds parsed configuration.
HAConfigMapperPtr config_;
#include <config.h>
-#include <cc/data.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
-#include <testutils/lib_load_test_fixture.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
+#include <testutils/gtest_utils.h>
#include <gtest/gtest.h>
#include <errno.h>
const std::string& expected_response) {
io_service_.reset(new IOService());
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(ha_sync_command);
TEST_F(HAImplTest, startServices) {
// Valid configuration must be provided prior to starting the service.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
// Network state is also required.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
// Start the service for DHCPv4 server.
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// Make sure that the HA service has been created for the requested
TEST_F(HAImplTest, startServices6) {
// Valid configuration must be provided prior to starting the service.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
// Network state is also required.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
// Start the service for DHCPv4 server.
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// Make sure that the HA service has been created for the requested
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// Initially the HA service is in the waiting state and serves no scopes.
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// The hub is a standby server and by default serves no scopes. Explicitly
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// The hub is a standby server and by default serves no scopes. Explicitly
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// Create callout handle to be used for passing arguments to the
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// The hub is a standby server and by default serves no scopes. Explicitly
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// The hub is a standby server and by default serves no scopes. Explicitly
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// This server serves server1/server2 scopes but not server3/server4 scopes.
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
test_ha_impl_->services_->get("server2")->serveFailoverScopes();
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// Initially the HA service is in the waiting state and serves no scopes.
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// The hub is a standby server and by default serves no scopes. Explicitly
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// The hub is a standby server and by default serves no scopes. Explicitly
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// Create callout handle to be used for passing arguments to the
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// The hub is a standby server and by default serves no scopes. Explicitly
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// The hub is a standby server and by default serves no scopes. Explicitly
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// This server serves server1/server2 scopes but not server3/server4 scopes.
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
// Starting the service is required before any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
test_ha_impl_->services_->get("server2")->serveFailoverScopes();
TEST_F(HAImplTest, leases4Committed) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// Make sure we wait for the acks from the backup server to be able to
TEST_F(HAImplTest, leases4CommittedMultipleRelationships) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
// Starting the service is required before running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// By enabling this setting we ensure that the lease updates are always
TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsNoServerName) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
// Starting the service is required before running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// By enabling this setting we ensure that the lease updates are always
TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsInvalidServerName) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
// Starting the service is required before running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// By enabling this setting we ensure that the lease updates are always
TEST_F(HAImplTest, leases6Committed) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// Make sure we wait for the acks from the backup server to be able to
TEST_F(HAImplTest, leases6CommittedMultipleRelationships) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
// Starting the service is required before running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// By enabling this setting we ensure that the lease updates are always
TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsNoServerName) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
// Starting the service is required before running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// By enabling this setting we ensure that the lease updates are always
TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsInvalidServerName) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
// Starting the service is required before running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv6));
// By enabling this setting we ensure that the lease updates are always
// Tests ha-continue command handler with a specified server name.
TEST_F(HAImplTest, continueHandler) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON("{"
// Tests ha-continue command handler without a server name.
TEST_F(HAImplTest, continueHandlerWithNoServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON("{ \"command\": \"ha-continue\" }");
// Tests ha-continue command handler with wrong server name.
TEST_F(HAImplTest, continueHandlerWithWrongServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON("{"
// Tests status-get command processed handler.
TEST_F(HAImplTest, statusGet) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
std::string name = "status-get";
// Tests status-get command processed handler for backup server.
TEST_F(HAImplTest, statusGetBackupServer) {
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
test_ha_impl_->config_->get()->setThisServerName("server3");
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
std::string name = "status-get";
// passive-backup state.
TEST_F(HAImplTest, statusGetPassiveBackup) {
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidPassiveBackupJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
std::string name = "status-get";
// hub-and-spoke mode.
TEST_F(HAImplTest, statusGetHubAndSpoke) {
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
std::string name = "status-get";
// Test ha-maintenance-notify command handler with server name.
TEST_F(HAImplTest, maintenanceNotify) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-maintenance-notify command handler without server name.
TEST_F(HAImplTest, maintenanceNotifyNoServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-maintenance-notify command handler without server name.
TEST_F(HAImplTest, maintenanceNotifyBadServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-reset command handler with a specified server name.
TEST_F(HAImplTest, haReset) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-reset command handler without a specified server name.
TEST_F(HAImplTest, haResetNoServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-reset command handler with a wrong server name.
TEST_F(HAImplTest, haResetBadServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-heartbeat command handler with a specified server name.
TEST_F(HAImplTest, haHeartbeat) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-heartbeat command handler without a specified server name.
TEST_F(HAImplTest, haHeartbeatNoServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-heartbeat command handler with a wrong server name.
TEST_F(HAImplTest, haHeartbeatBadServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-sync-complete-notify command handler with a specified server name.
TEST_F(HAImplTest, haSyncCompleteNotify) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-sync-complete-notify command handler without a specified server name.
TEST_F(HAImplTest, haSyncCompleteNotifyNoServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-sync-complete-notify command handler with a wrong server name.
TEST_F(HAImplTest, haSyncCompleteNotifyBadServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-scopes command handler with a specified server name.
TEST_F(HAImplTest, haScopes) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-scopes command handler without a specified server name.
TEST_F(HAImplTest, haScopesNoServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
// Test ha-scopes command handler with a wrong server name.
TEST_F(HAImplTest, haScopesBadServerName) {
ha_impl_.reset(new HAImpl());
+ ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
ConstElementPtr command = Element::fromJSON(
TEST_F(HAImplTest, lease4ServerDecline) {
// Create implementation object and configure it.
test_ha_impl_.reset(new TestHAImpl());
+ test_ha_impl_->setIOService(io_service_);
ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
// Starting the service is required prior to running any callouts.
NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
- ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+ ASSERT_NO_THROW(test_ha_impl_->startServices(network_state,
HAServerType::DHCPv4));
// Make sure we wait for the acks from the backup server to be able to
#include <config.h>
-#include <cc/data.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
#include <testutils/gtest_utils.h>
-#include <testutils/lib_load_test_fixture.h>
#include <gtest/gtest.h>
#include <errno.h>
#include <config.h>
-#include <cc/data.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
#include <testutils/gtest_utils.h>
-#include <testutils/lib_load_test_fixture.h>
#include <gtest/gtest.h>
#include <errno.h>
#include <sstream>
#include <string>
+using namespace isc::asiolink;
using namespace isc::cb;
using namespace isc::dhcp;
using namespace isc::hooks;
/// @param handle callout handle passed to the callout.
/// @return 0 on success, 1 otherwise.
int dhcp4_srv_configured(CalloutHandle& handle) {
- isc::asiolink::IOServicePtr io_service;
- handle.getArgument("io_context", io_service);
- if (!io_service) {
+ 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::setIOService(io_service);
+ isc::dhcp::MySqlConfigBackendImpl::getIOService().reset(new IOService());
+ isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
return (0);
}
/// @param handle callout handle passed to the callout.
/// @return 0 on success, 1 otherwise.
int dhcp6_srv_configured(CalloutHandle& handle) {
- isc::asiolink::IOServicePtr io_service;
- handle.getArgument("io_context", io_service);
- if (!io_service) {
+ 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::setIOService(io_service);
+ isc::dhcp::MySqlConfigBackendImpl::getIOService().reset(new IOService());
+ isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
return (0);
}
// Unregister the factories and remove MySQL backends
isc::dhcp::MySqlConfigBackendDHCPv4::unregisterBackendType();
isc::dhcp::MySqlConfigBackendDHCPv6::unregisterBackendType();
+ if (isc::dhcp::MySqlConfigBackendImpl::getMainIOService()) {
+ isc::dhcp::MySqlConfigBackendImpl::getMainIOService()->unregisterExternalIOService(isc::dhcp::MySqlConfigBackendImpl::getIOService());
+ }
+ if (isc::dhcp::MySqlConfigBackendImpl::getIOService()) {
+ isc::dhcp::MySqlConfigBackendImpl::getIOService()->stop();
+ isc::dhcp::MySqlConfigBackendImpl::getIOService()->restart();
+ try {
+ isc::dhcp::MySqlConfigBackendImpl::getIOService()->poll();
+ } catch (...) {
+ }
+ }
return (0);
}
namespace isc {
namespace dhcp {
-isc::asiolink::IOServicePtr MySqlConfigBackendImpl::io_service_ = isc::asiolink::IOServicePtr();
+isc::asiolink::IOServicePtr MySqlConfigBackendImpl::io_service_;
+isc::asiolink::IOServicePtr MySqlConfigBackendImpl::main_io_service_;
MySqlConfigBackendImpl::
ScopedAuditRevision::ScopedAuditRevision(MySqlConfigBackendImpl* impl,
}
}
+MySqlConfigBackendImpl::~MySqlConfigBackendImpl() {
+ /// nothing to do there. The conn_ connection will be deleted and its dtor
+ /// will take care of releasing the compiled statements and similar.
+}
+
MySqlBindingPtr
MySqlConfigBackendImpl::createBinding(const Triplet<uint32_t>& triplet) {
if (triplet.unspecified()) {
const db::DbCallback db_reconnect_callback);
/// @brief Destructor.
- virtual ~MySqlConfigBackendImpl() {};
+ virtual ~MySqlConfigBackendImpl();
/// @brief Creates MySQL binding from an @c Optional of integer type.
///
return (parameters_);
}
- /// @brief Sets IO service to be used by the MySQL config backend.
+ /// @brief Get the hook I/O service.
///
- /// @param IOService object, used for all ASIO operations.
- static void setIOService(const isc::asiolink::IOServicePtr& io_service) {
+ /// @return the hook I/O service.
+ static isc::asiolink::IOServicePtr& getIOService() {
+ return (io_service_);
+ }
+
+ /// @brief Set the hook I/O service.
+ ///
+ /// @param io_service the hook I/O service.
+ static void setIOService(isc::asiolink::IOServicePtr io_service) {
io_service_ = io_service;
}
- /// @brief Returns pointer to the IO service.
- static isc::asiolink::IOServicePtr& getIOService() {
- return (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 Connection parameters
isc::db::DatabaseConnection::ParameterMap parameters_;
- /// @brief The IOService object, used for all ASIO operations.
+ /// @brief The hook I/O service.
static isc::asiolink::IOServicePtr io_service_;
+
+ /// @brief The main I/O service.
+ static isc::asiolink::IOServicePtr main_io_service_;
};
} // end of namespace isc::dhcp
#include <config.h>
-#include <cc/data.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
#include <testutils/gtest_utils.h>
-#include <testutils/lib_load_test_fixture.h>
#include <gtest/gtest.h>
#include <errno.h>
#include <config.h>
-#include <cc/data.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
#include <testutils/gtest_utils.h>
-#include <testutils/lib_load_test_fixture.h>
#include <gtest/gtest.h>
#include <errno.h>
#include <sstream>
#include <string>
+using namespace isc::asiolink;
using namespace isc::cb;
using namespace isc::dhcp;
using namespace isc::hooks;
/// @param handle callout handle passed to the callout.
/// @return 0 on success, 1 otherwise.
int dhcp4_srv_configured(CalloutHandle& handle) {
- isc::asiolink::IOServicePtr io_service;
- handle.getArgument("io_context", io_service);
- if (!io_service) {
+ 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::setIOService(io_service);
+ isc::dhcp::PgSqlConfigBackendImpl::getIOService().reset(new IOService());
+ isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
return (0);
}
/// @param handle callout handle passed to the callout.
/// @return 0 on success, 1 otherwise.
int dhcp6_srv_configured(CalloutHandle& handle) {
- isc::asiolink::IOServicePtr io_service;
- handle.getArgument("io_context", io_service);
- if (!io_service) {
+ 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::setIOService(io_service);
+ isc::dhcp::PgSqlConfigBackendImpl::getIOService().reset(new IOService());
+ isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->registerExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
return (0);
}
// Unregister the factories and remove PostgreSQL backends
isc::dhcp::PgSqlConfigBackendDHCPv4::unregisterBackendType();
isc::dhcp::PgSqlConfigBackendDHCPv6::unregisterBackendType();
+ if (isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()) {
+ isc::dhcp::PgSqlConfigBackendImpl::getMainIOService()->unregisterExternalIOService(isc::dhcp::PgSqlConfigBackendImpl::getIOService());
+ }
+ if (isc::dhcp::PgSqlConfigBackendImpl::getIOService()) {
+ isc::dhcp::PgSqlConfigBackendImpl::getIOService()->stop();
+ isc::dhcp::PgSqlConfigBackendImpl::getIOService()->restart();
+ try {
+ isc::dhcp::PgSqlConfigBackendImpl::getIOService()->poll();
+ } catch (...) {
+ }
+ }
return (0);
}
namespace isc {
namespace dhcp {
-isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::io_service_ = isc::asiolink::IOServicePtr();
+isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::io_service_;
+isc::asiolink::IOServicePtr PgSqlConfigBackendImpl::main_io_service_;
PgSqlTaggedStatement&
PgSqlConfigBackendImpl::getStatement(size_t /* index */) const {
return (parameters_);
}
- /// @brief Sets IO service to be used by the PostgreSQL config backend.
- ///
- /// @param IOService object, used for all ASIO operations.
- static void setIOService(const isc::asiolink::IOServicePtr& io_service) {
- io_service_ = io_service;
- }
-
- /// @brief Returns pointer to the IO service.
- static isc::asiolink::IOServicePtr& getIOService() {
- return (io_service_);
- }
-
/// @brief Fetches the SQL statement for a given statement index.
///
/// Derivations must override the implementation. The reference
/// @return Number of affected rows.
uint64_t updateDeleteQuery(size_t index, const db::PsqlBindArray& in_bindings);
+ /// @brief Get the hook I/O service.
+ ///
+ /// @return the hook I/O service.
+ static isc::asiolink::IOServicePtr& getIOService() {
+ return (io_service_);
+ }
+
+ /// @brief Set the hook I/O service.
+ ///
+ /// @param io_service the hook I/O service.
+ static void setIOService(isc::asiolink::IOServicePtr io_service) {
+ io_service_ = io_service;
+ }
+
+ /// @brief Get the main I/O service.
+ ///
+ /// @return the main I/O service.
+ static isc::asiolink::IOServicePtr& getMainIOService() {
+ return (main_io_service_);
+ }
+
+ /// @brief Set the main I/O service.
+ ///
+ /// @param io_service the main I/O service.
+ static void setMainIOService(isc::asiolink::IOServicePtr io_service) {
+ main_io_service_ = io_service;
+ }
+
/// @brief Represents connection to the PostgreSQL database.
db::PgSqlConnection conn_;
/// @brief Connection parameters
isc::db::DatabaseConnection::ParameterMap parameters_;
- /// @brief The IOService object, used for all ASIO operations.
+ /// @brief The hook I/O service.
static isc::asiolink::IOServicePtr io_service_;
+ /// @brief The main I/O service.
+ static isc::asiolink::IOServicePtr main_io_service_;
+
/// @brief Statement index of the SQL statement to use for fetching
/// last inserted id in a given table.
size_t last_insert_id_index_;
#include <config.h>
-#include <cc/data.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
-#include <testutils/lib_load_test_fixture.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
+#include <testutils/gtest_utils.h>
#include <gtest/gtest.h>
#include <errno.h>
namespace run_script {
IOServicePtr RunScriptImpl::io_service_;
+IOServicePtr RunScriptImpl::main_io_service_;
-RunScriptImpl::RunScriptImpl() : name_(), sync_(false) {
+RunScriptImpl::RunScriptImpl() : io_context_(new IOService()), name_(), sync_(false) {
}
void
/// @brief Destructor.
~RunScriptImpl() = default;
- /// @brief Sets IO service to be used by the @ref ProcessSpawn instance.
- ///
- /// @param io_service The IOService object, used for all ASIO operations.
- static void setIOService(const isc::asiolink::IOServicePtr& io_service) {
- io_service_ = io_service;
- }
-
- /// @brief Gets IO service to be used by the @ref ProcessSpawn instance.
- ///
- /// @return The IOService object, used for all ASIO operations.
- static isc::asiolink::IOServicePtr getIOService() {
- return (io_service_);
- }
-
/// @brief Extract boolean data and append to environment.
///
/// @param value The value to be exported to target script environment.
/// @brief This function parses and applies configuration parameters.
void configure(isc::hooks::LibraryHandle& handle);
+ /// @brief Get the hook I/O service.
+ ///
+ /// @return the hook I/O service.
+ isc::asiolink::IOServicePtr& getIOContext() {
+ return (io_context_);
+ }
+
+ /// @brief Set the hook I/O service.
+ ///
+ /// @param io_service the hook I/O service.
+ void setIOContext(isc::asiolink::IOServicePtr io_service) {
+ io_context_ = io_service;
+ }
+
+ /// @brief Get the hook I/O service.
+ ///
+ /// @return the hook I/O service.
+ static isc::asiolink::IOServicePtr& getIOService() {
+ return (io_service_);
+ }
+
+ /// @brief Set the hook I/O service.
+ ///
+ /// @param io_service the hook I/O service.
+ static void setIOService(isc::asiolink::IOServicePtr io_service) {
+ io_service_ = io_service;
+ }
+
+ /// @brief Get the main I/O service.
+ ///
+ /// @return the main I/O service.
+ static isc::asiolink::IOServicePtr& getMainIOService() {
+ return (main_io_service_);
+ }
+
+ /// @brief Set the main I/O service.
+ ///
+ /// @param io_service the main I/O service.
+ static void setMainIOService(isc::asiolink::IOServicePtr io_service) {
+ main_io_service_ = io_service;
+ }
+
private:
+
+ /// @brief The IOService object, used for all ASIO operations.
+ isc::asiolink::IOServicePtr io_context_;
+
/// @brief Script name.
std::string name_;
/// started.
bool sync_;
- /// @brief The IOService object, used for all ASIO operations.
+ /// @brief The hook I/O service.
static isc::asiolink::IOServicePtr io_service_;
+
+ /// @brief The main I/O service.
+ static isc::asiolink::IOServicePtr main_io_service_;
};
/// @brief The type of shared pointers to Run Script implementations.
///
/// @return always 0.
int unload() {
+ if (RunScriptImpl::getMainIOService()) {
+ RunScriptImpl::getMainIOService()->unregisterExternalIOService(impl->getIOContext());
+ }
impl.reset();
+ if (RunScriptImpl::getIOService()) {
+ RunScriptImpl::getIOService()->stop();
+ RunScriptImpl::getIOService()->restart();
+ try {
+ RunScriptImpl::getIOService()->poll();
+ } catch (...) {
+ }
+ }
RunScriptImpl::setIOService(IOServicePtr());
LOG_INFO(run_script_logger, RUN_SCRIPT_UNLOAD);
return (0);
/// @param handle callout handle.
int dhcp4_srv_configured(CalloutHandle& handle) {
try {
- isc::asiolink::IOServicePtr io_service;
- handle.getArgument("io_context", io_service);
- if (!io_service) {
+ 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(io_service);
+ RunScriptImpl::setIOService(impl->getIOContext());
+ RunScriptImpl::getMainIOService()->registerExternalIOService(impl->getIOContext());
} catch (const exception& ex) {
LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)
/// @param handle callout handle.
int dhcp6_srv_configured(CalloutHandle& handle) {
try {
- isc::asiolink::IOServicePtr io_service;
- handle.getArgument("io_context", io_service);
- if (!io_service) {
+ 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(io_service);
+ RunScriptImpl::setIOService(impl->getIOContext());
+ RunScriptImpl::getMainIOService()->registerExternalIOService(impl->getIOContext());
} catch (const exception& ex) {
LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)
#include <config.h>
-#include <cc/data.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <hooks/hooks_manager.h>
-#include <process/daemon.h>
+#include <dhcpsrv/testutils/lib_load_test_fixture.h>
#include <testutils/gtest_utils.h>
-#include <testutils/lib_load_test_fixture.h>
#include <gtest/gtest.h>
#include <errno.h>
namespace asiolink {
class IOServiceImpl {
+ /// @brief Constructors and Destructor.
+ ///
+ /// @note The copy constructor and the assignment operator are
+ /// intentionally defined as private, making this class non-copyable.
+ //@{
private:
IOServiceImpl(const IOService& source);
IOServiceImpl& operator=(const IOService& source);
public:
- /// \brief The constructor
+ /// @brief The constructor.
IOServiceImpl() :
io_service_(),
work_(new boost::asio::io_service::work(io_service_)) {
};
- /// \brief The destructor.
- ~IOServiceImpl() {
- };
+ /// @brief The destructor.
+ ~IOServiceImpl() = default;
//@}
- /// \brief Start the underlying event loop.
+ /// @brief Start the underlying event loop.
///
/// This method does not return control to the caller until
- /// the \c stop() method is called via some handler.
+ /// the @ref stop() method is called via some handler.
void run() {
io_service_.run();
};
- /// \brief Run the underlying event loop for a single event.
+ /// @brief Run the underlying event loop for a single event.
///
/// This method return control to the caller as soon as the
/// first handler has completed. (If no handlers are ready when
/// it is run, it will block until one is.)
///
- /// \return The number of handlers that were executed.
+ /// @return The number of handlers that were executed.
size_t runOne() {
return (static_cast<size_t>(io_service_.run_one()));
};
- /// \brief Run the underlying event loop for a ready events.
+ /// @brief Run the underlying event loop for a ready events.
///
/// This method executes handlers for all ready events and returns.
/// It will return immediately if there are no ready events.
///
- /// \return The number of handlers that were executed.
+ /// @return The number of handlers that were executed.
size_t poll() {
return (static_cast<size_t>(io_service_.poll()));
};
- /// \brief Run the underlying event loop for a ready events.
+ /// @brief Run the underlying event loop for a ready events.
///
/// This method executes handlers for all ready events and returns.
/// It will return immediately if there are no ready events.
///
- /// \return The number of handlers that were executed.
+ /// @return The number of handlers that were executed.
size_t pollOne() {
return (static_cast<size_t>(io_service_.poll_one()));
};
- /// \brief Stop the underlying event loop.
+ /// @brief Stop the underlying event loop.
///
- /// This will return the control to the caller of the \c run() method.
+ /// This will return the control to the caller of the @ref run() method.
void stop() {
io_service_.stop();
}
- /// \brief Indicates if the IOService has been stopped.
+ /// @brief Indicates if the IOService has been stopped.
///
- /// \return true if the IOService has been stopped, false otherwise.
+ /// @return true if the IOService has been stopped, false otherwise.
bool stopped() const {
return (io_service_.stopped());
}
- /// \brief Restarts the IOService in preparation for a subsequent \c run() invocation.
+ /// @brief Restarts the IOService in preparation for a subsequent @ref run() invocation.
void restart() {
io_service_.reset();
}
- /// \brief Removes IO service work object to let it finish running
+ /// @brief Removes IO service work object to let it finish running
/// when all handlers have been invoked.
void stopWork() {
work_.reset();
}
- /// \brief Return the native \c io_service object used in this wrapper.
+ /// @brief Return the native @ref io_service object used in this wrapper.
///
/// This is a short term work around to support other Kea modules
- /// that share the same \c io_service with the authoritative server.
+ /// that share the same @ref io_service with the authoritative server.
/// It will eventually be removed once the wrapper interface is
/// generalized.
boost::asio::io_service& getInternalIOService() {
return (io_service_);
}
- /// \brief Post a callback on the IO service
+ /// @brief Post a callback on the IO service.
///
- /// \param callback The callback to be run on the IO service.
+ /// @param callback The callback to be run on the IO service.
void post(const std::function<void ()>& callback) {
io_service_.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 isc
#include <boost/version.hpp>
#include <boost/shared_ptr.hpp>
#include <functional>
+#include <list>
namespace boost {
namespace asio {
namespace asiolink {
class IOServiceImpl;
+class IOService;
-/// \brief The \c IOService class is a wrapper for the ASIO \c io_service
+/// @brief Defines a smart pointer to an IOService instance.
+typedef boost::shared_ptr<IOService> IOServicePtr;
+
+/// @brief The @ref IOService class is a wrapper for the ASIO @ref io_service
/// class.
-///
class IOService {
+ /// @brief Constructors and Destructor.
///
- /// \name Constructors and Destructor
- ///
- /// Note: The copy constructor and the assignment operator are
+ /// @note The copy constructor and the assignment operator are
/// intentionally defined as private, making this class non-copyable.
//@{
private:
IOService(const IOService& source);
IOService& operator=(const IOService& source);
public:
- /// \brief The constructor
+ /// @brief The constructor.
IOService();
- /// \brief The destructor.
+
+ /// @brief The destructor.
~IOService();
//@}
- /// \brief Start the underlying event loop.
+ /// @brief Start the underlying event loop.
///
/// This method does not return control to the caller until
- /// the \c stop() method is called via some handler.
+ /// the @ref stop() method is called via some handler.
void run();
- /// \brief Run the underlying event loop for a single event.
+ /// @brief Run the underlying event loop for a single event.
///
/// This method return control to the caller as soon as the
/// first handler has completed. (If no handlers are ready when
/// it is run, it will block until one is.)
///
- /// \return The number of handlers that were executed.
+ /// @return The number of handlers that were executed.
size_t runOne();
- /// \brief Run the underlying event loop for a ready events.
+ /// @brief Run the underlying event loop for a ready events.
///
/// This method executes handlers for all ready events and returns.
/// It will return immediately if there are no ready events.
///
- /// \return The number of handlers that were executed.
+ /// @return The number of handlers that were executed.
size_t poll();
- /// \brief Run the underlying event loop for a ready events.
+ /// @brief Run the underlying event loop for a ready events.
///
/// This method executes handlers for all ready events and returns.
/// It will return immediately if there are no ready events.
///
- /// \return The number of handlers that were executed.
+ /// @return The number of handlers that were executed.
size_t pollOne();
- /// \brief Stop the underlying event loop.
+ /// @brief Stop the underlying event loop.
///
- /// This will return the control to the caller of the \c run() method.
+ /// This will return the control to the caller of the @ref run() method.
void stop();
- /// \brief Indicates if the IOService has been stopped.
+ /// @brief Indicates if the IOService has been stopped.
///
- /// \return true if the IOService has been stopped, false otherwise.
+ /// @return true if the IOService has been stopped, false otherwise.
bool stopped() const;
- /// \brief Restarts the IOService in preparation for a subsequent \c run() invocation.
+ /// @brief Restarts the IOService in preparation for a subsequent @ref run() invocation.
void restart();
- /// \brief Removes IO service work object to let it finish running
+ /// @brief Removes IO service work object to let it finish running
/// when all handlers have been invoked.
void stopWork();
- /// \brief Return the native \c io_service object used in this wrapper.
+ /// @brief Return the native @ref io_service object used in this wrapper.
///
/// This is a short term work around to support other Kea modules
- /// that share the same \c io_service with the authoritative server.
+ /// that share the same @ref io_service with the authoritative server.
/// It will eventually be removed once the wrapper interface is
/// generalized.
+ ///
+ /// @return The internal io_service object.
boost::asio::io_service& getInternalIOService();
- /// \brief Post a callback to the end of the queue.
+ /// @brief Post a callback to the end of the queue.
///
/// Requests the callback be called sometime later. It is not guaranteed
/// by the underlying asio, but it can reasonably be expected the callback
/// 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 Defines a smart pointer to an IOService instance.
-typedef boost::shared_ptr<IOService> IOServicePtr;
+ /// @brief The list of external IOService objects.
+ std::list<IOServicePtr> external_io_services_;
+};
} // namespace asiolink
} // namespace isc
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);
+}
+
}
EXPECT_EQ("IO_STOPPED", name_change_->responseString());
ASSERT_NO_THROW(name_change_->setDnsUpdateStatus(DNSClient::
- INVALID_RESPONSE));
+ INVALID_RESPONSE));
EXPECT_EQ("INVALID_RESPONSE", name_change_->responseString());
ASSERT_NO_THROW(name_change_->setDnsUpdateStatus(DNSClient::OTHER));
dns::RRsetPtr rrset;
checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1);
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 0));
+ SECTION_PREREQUISITE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::ANY(), 0, ncr);
// Verify the UPDATE SECTION
// First, Verify the FQDN/IP add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr);
// Now, verify the DHCID add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
ttl, ncr);
// Verify the FQDN test RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 0));
+ SECTION_PREREQUISITE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::ANY(), 0, ncr);
// Verify the DHCID test RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 1));
+ SECTION_PREREQUISITE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(), 0, ncr);
// Verify the UPDATE SECTION
// Verify the FQDN delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr);
// Verify the FQDN/IP add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr);
// Verify there are no RRs in the ADDITIONAL Section.
// Verify the PTR delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::PTR(),
0, ncr);
// Verify the DHCID delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::DHCID(),
0, ncr);
// Verify the PTR add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 2));
+ SECTION_UPDATE, 2));
checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::PTR(),
ttl, ncr);
// Verify the DHCID add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 3));
+ SECTION_UPDATE, 3));
checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::DHCID(),
ttl, ncr);
// Verify the DHCID matching assertion RR.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 0));
+ SECTION_PREREQUISITE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
0, ncr);
// Verify the FQDN/IP delete RR.
const dns::RRType& exp_ip_rr_type = tran.getAddressRRType();
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), exp_ip_rr_type,
0, ncr);
// Verify the DHCID matches assertion.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 0));
+ SECTION_PREREQUISITE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
0, ncr);
// Verify the NO A RRs assertion.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 1));
+ SECTION_PREREQUISITE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::A(),
0, ncr, NO_RDATA);
// Verify the NO AAAA RRs assertion.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 2));
+ SECTION_PREREQUISITE, 2));
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::AAAA(),
0, ncr, NO_RDATA);
// Verify the delete all for the FQDN RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::ANY(),
0, ncr);
// Verify the FQDN-PTRNAME assertion RR.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 0));
+ SECTION_PREREQUISITE, 0));
checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::PTR(),
0, ncr);
// Verify the delete all for the FQDN RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::ANY(),
0, ncr);
// Verify the FQDN delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr);
// Verify the DHCID delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::DHCID(),
0, ncr);
// Verify the FQDN/IP add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 2));
+ SECTION_UPDATE, 2));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr);
// Now, verify the DHCID add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 3));
+ SECTION_UPDATE, 3));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
ttl, ncr);
// Verify the FQDN delete RR.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr);
// Verify the DHCID delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::DHCID(),
0, ncr);
// Verify the FQDN delete RR.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::PTR(), 0, ncr);
// Verify the DHCID delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::DHCID(), 0, ncr);
// Verify that it will render toWire without throwing.
// Verify the DHCID test RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 0));
+ SECTION_PREREQUISITE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::DHCID(), 0, ncr);
// Verify the UPDATE SECTION
// Verify the FQDN delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr);
// Verify the DHCID delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::DHCID(), 0, ncr);
// Verify the FQDN/IP add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 2));
+ SECTION_UPDATE, 2));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr);
// Verify the DHCID add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 3));
+ SECTION_UPDATE, 3));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
ttl, ncr);
// Verify the DHCID exists assertion RR.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 0));
+ SECTION_PREREQUISITE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::DHCID(),
0, ncr);
// Verify the FQDN/IP delete RR.
const dns::RRType& exp_ip_rr_type = tran.getAddressRRType();
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), exp_ip_rr_type,
0, ncr);
// Verify the NO A RRs assertion.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 0));
+ SECTION_PREREQUISITE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::A(),
0, ncr, NO_RDATA);
// Verify the NO AAAA RRs assertion.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_PREREQUISITE, 1));
+ SECTION_PREREQUISITE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::AAAA(),
0, ncr, NO_RDATA);
// Verify the DHCID delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::DHCID(),
0, ncr);
// Verify the FQDN delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr);
// Verify the FQDN/IP add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr);
// Verify there are no RRs in the ADDITIONAL Section.
// Verify the FQDN delete RR.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr);
// Verify that it will render toWire without throwing.
// Verify the PTR delete RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::PTR(),
0, ncr);
// Verify the PTR add RR.
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 1));
+ SECTION_UPDATE, 1));
checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::PTR(),
ttl, ncr);
// Verify the FQDN delete RR.
dns::RRsetPtr rrset;
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
- SECTION_UPDATE, 0));
+ SECTION_UPDATE, 0));
checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::PTR(), 0, ncr);
// Verify that it will render toWire without throwing.
libdhcpsrvtest_la_SOURCES += config_result_check.cc config_result_check.h
libdhcpsrvtest_la_SOURCES += dhcp4o6_test_ipc.cc dhcp4o6_test_ipc.h
libdhcpsrvtest_la_SOURCES += host_data_source_utils.cc host_data_source_utils.h
+libdhcpsrvtest_la_SOURCES += lib_load_test_fixture.h
libdhcpsrvtest_la_SOURCES += memory_host_data_source.cc memory_host_data_source.h
libdhcpsrvtest_la_SOURCES += test_utils.cc test_utils.h
libdhcpsrvtest_la_SOURCES += generic_backend_unittest.cc generic_backend_unittest.h
#include <cc/data.h>
#include <dhcpsrv/cfgmgr.h>
+#include <hooks/hooks_manager.h>
#include <process/daemon.h>
+
#include <testutils/gtest_utils.h>
namespace isc {
Other hook library entry points are called by the main thread:
- io service (io context is recent boost versions) is polled by the main
- thread
+ thread
- external socket callbacks are executed by the main thread
- commands including command_process
// case of problems.
storage->applyLoggingCfg();
+ getIOService()->clearExternalIOServices();
+
answer = updateConfig(module_config);
// In all cases the right logging configuration is in the context.
process_->getCfgMgr()->getContext()->applyLoggingCfg();
// case of problems.
storage->applyLoggingCfg();
+ getIOService()->clearExternalIOServices();
+
ConstElementPtr answer = updateConfig(module_config);
int rcode = 0;
parseAnswer(rcode, answer);
LOG_ERROR(dctl_logger, DCTL_UNLOAD_LIBRARIES_ERROR).arg(msg);
}
+ getIOService()->clearExternalIOServices();
+
io_signal_set_.reset();
try {
getIOService()->poll();
libkea_testutils_la_SOURCES += user_context_utils.cc user_context_utils.h
libkea_testutils_la_SOURCES += gtest_utils.h
libkea_testutils_la_SOURCES += multi_threading_utils.h
-libkea_testutils_la_SOURCES += lib_load_test_fixture.h
libkea_testutils_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
libkea_testutils_la_LIBADD = $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
libkea_testutils_la_LIBADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
--- /dev/null
+#!/bin/bash
+
+# extract folder name containing file
+#
+# param ${1} file name
+# return folder name
+extract_folder_name() {
+ # return name of the file until last '/'
+ echo "$(echo "${1}" | rev | cut -d '/' -f 2- | rev)"
+}
+
+# extract all includes found in source files found in the same folder as specified Makefile.am
+#
+# param ${1} path to a Makefile.am
+# return all dependencies libs in the order of compilation
+extract_includes() {
+ # extract folder name from current library Makefile.am
+ CURRENT_FOLDER=$(extract_folder_name "${1}")"/"
+ # select only files in current folder
+ SEARCH_FILES=$(echo "${FILE_LIST}" | grep "${CURRENT_FOLDER}")
+ # select all lines containing '#include ' directive
+ RAW_INCLUDES_LIST=$(echo "${SEARCH_FILES}" | xargs grep "^#include " 2>/dev/null)
+ # filter only included dependencies found in other libraries by using the form 'other_lib_name/header_file.h'
+ # to do this it is required to select the string between '<' and '>', searching for '/' character and returning the name until last '/'
+ RAW_INCLUDES_LIST=$(echo "${RAW_INCLUDES_LIST}" | cut -d "#" -f 2 | tr "\"" " " | cut -d "<" -f 2 | cut -d ">" -f 1 | grep "\/" | rev | cut -d "/" -f 2 | rev | sort | uniq)
+ # filter includes that are not compiled by the project's Makefiles
+ INCLUDES_LIST=
+ for i in ${LIBRARIES_LIST}; do
+ for j in ${RAW_INCLUDES_LIST}; do
+ if test "${j}" = "${i}"; then
+ INCLUDES_LIST="${i} ${INCLUDES_LIST}"
+ break
+ fi
+ done
+ done
+ # remove empty spaces
+ INCLUDES_LIST=$(echo ${INCLUDES_LIST} | tr -s " ")
+ # order dependencies in the order of compilation
+ FILTERED_INCLUDES_LIST=
+ for i in ${LIBRARIES_LIST}; do
+ if test $(echo "${INCLUDES_LIST}" | grep "\b${i}\b" | wc -l) -ne 0; then
+ FILTERED_INCLUDES_LIST="${i} ${FILTERED_INCLUDES_LIST}"
+ fi
+ done
+ echo "${FILTERED_INCLUDES_LIST}"
+}
+
+# extract all header only files and headers and source files found in the external library required by specified library
+# param ${1} name of the current library
+# param ${2} name of the external dependency library required by current library
+# return the list of header only files as 'HEADERS: heaser1.h header2.h' and header and source files as 'HEADERS_AND_SOURCES: source1.h source1.cc source2.h source2.cpp'
+extract_non_include_files() {
+ # extract folder name for current library Makefile.am
+ CURRENT_FOLDER=$(extract_folder_name "src/lib/${1}/Makefile.am")"/"
+ # extract folder name for external dependency library Makefile.am
+ EXTERNAL_FOLDER=$(extract_folder_name "src/lib/${2}/Makefile.am")"/"
+ # select only files in current folder
+ SEARCH_FILES=$(echo "${FILE_LIST}" | grep "${CURRENT_FOLDER}")
+ HEADERS_LIST=
+ NON_HEADERS_LIST=
+ # select all lines containing '#include ' directive
+ RAW_INCLUDES_LIST=$(echo "${SEARCH_FILES}" | xargs grep "^#include " 2>/dev/null)
+ # filter only included headers found in other libraries by using the form 'other_lib_name/header_file.h'
+ # to do this it is required to select the string between '<' and '>', searching for '/' character, search for the extension marker '.' and returning the name after last '/'
+ RAW_INCLUDES_LIST=$(echo "${RAW_INCLUDES_LIST}" | cut -d "#" -f 2 | tr "\"" " " | cut -d "<" -f 2 | cut -d ">" -f 1 | grep "\/" | grep "\b${2}\b" | cut -d "/" -f 2 | grep "\." | sort | uniq)
+ # select only files in dependency library folder and strip full path
+ RELATIVE_SEARCH_FILES=$(echo "${FILE_LIST}" | grep "${EXTERNAL_FOLDER}" | sed -e "s#${REPO_FOLDER}${EXTERNAL_FOLDER}##g")
+ # search for the header file but also for source files
+ for i in ${RAW_INCLUDES_LIST}; do
+ # filter by name only (no extension)
+ FILTER=$(echo "${i}" | cut -d "." -f 1)
+ # filter non header files with exact name of the header file without the extension
+ NON_HEADER=$(echo "${RELATIVE_SEARCH_FILES}" | grep "\b${FILTER}\." | grep -v "${i}")
+ if test $(echo "${NON_HEADER}" | wc -w) -ne 0; then
+ # append header and source file names
+ NON_HEADERS_LIST="${i} ${NON_HEADER} ${NON_HEADERS_LIST}"
+ else
+ # append header only file name
+ HEADERS_LIST="${i} ${HEADERS_LIST}"
+ fi
+ done
+ # sort header only files
+ HEADERS_LIST=$(echo ${HEADERS_LIST} | tr -s " " | sort | uniq)
+ # sort header and source files
+ NON_HEADERS_LIST=$(echo ${NON_HEADERS_LIST} | tr -s " " | sort | uniq)
+ echo "HEADERS_AND_SOURCES:${NON_HEADERS_LIST}"
+ echo "HEADERS:${HEADERS_LIST}"
+}
+
+# extract all valid dependencies of a specified library
+#
+# param ${1} list of all libraries in the reverse compilation order
+# param ${2} library name for which the dependency list is computed
+# return the list of dependencies for specified library in the reverse compilation order
+extract_dependencies() {
+ echo "${1}" | grep -Eo "\b${2}\b.*$"
+}
+
+# extract computed dependency for specified library
+#
+# param ${1} library name for which the dependency list is retrieved
+# param ${2} library path for which the dependency list is retrieved
+# return stored value of computed dependencies or 'NONE' if dependencies have not been computed yet
+extract_computed_dependencies() {
+ PATH_TO_NAME=$(echo "${2}" | tr -s "/" "_")
+ NAME="COMPUTED_DEPENDENCIES_${PATH_TO_NAME}_${1}"
+ if test -n "${!NAME+x}"; then
+ echo "${!NAME}"
+ else
+ echo "NONE"
+ fi
+}
+
+# extract library directive
+#
+# param ${1} artifact path
+extract_library_directive() {
+ ARTIFACT_PATH="${1}"
+ echo `cat ${ARTIFACT_PATH}/Makefile.am | grep "LIBADD\|LDADD" | sort | tr -s ' ' | cut -d " " -f 1 | sort -u`
+}
+
+# extract library name
+#
+# param ${1} artifact path
+extract_library_name() {
+ ARTIFACT_PATH="${1}"
+ echo `cat ${ARTIFACT_PATH}/Makefile.am | grep "LIBRARIES" | tr -s ' ' | cut -d " " -f 3`
+}
+
+# compute artifact dependencies
+#
+# param ${1} artifact name
+# param ${2} artifact path
+compute_dependencies() {
+ ARTIFACT="${1}"
+ ARTIFACT_PATH="${2}"
+ echo ""
+ echo "########################################"
+ echo "### ${ARTIFACT_PATH}/${ARTIFACT}"
+ echo "########################################"
+ echo ""
+ # all valid dependencies that can be added by each dependency library
+ echo "${ARTIFACT_PATH}/${ARTIFACT} valid dependencies:"
+ echo "${VALID_LIST}"
+ # detect dependencies errors by searching for dependencies that are compiled after the current library and can generate missing symbols
+ NON_RECURSIVE_BASE_DEPENDENCIES=
+ for j in ${BASE_DEPENDENCIES}; do
+ # only add the dependency if it is in the valid dependencies list to prevent infinite recursion and log the error otherwise
+ if test $(echo "${VALID_LIST}" | grep "\b${j}\b" | wc -l) -eq 0; then
+ # search for external header and source files
+ INVALID_EXTERNAL_DEPENDENCIES=$(extract_non_include_files "${ARTIFACT}" "${j}")
+ # filter header only external files
+ EXTERNAL_HEADERS=$(echo "${INVALID_EXTERNAL_DEPENDENCIES}" | grep "HEADERS:" | cut -d ":" -f 2)
+ # filter header and source external files
+ EXTERNAL_ALL=$(echo "${INVALID_EXTERNAL_DEPENDENCIES}" | grep "HEADERS_AND_SOURCES:" | cut -d ":" -f 2)
+ echo "### ERROR ### dependencies ERROR for ${ARTIFACT_PATH}/${ARTIFACT} on ${j} with:"
+ # if there are any header only external files
+ if test $(echo "${EXTERNAL_ALL}" | wc -w) -ne 0; then
+ echo "non header only files: ${EXTERNAL_ALL}"
+ fi
+ # if there are any header and source external files
+ if test $(echo "${EXTERNAL_HEADERS}" | wc -w) -ne 0; then
+ echo "header only files: ${EXTERNAL_HEADERS}"
+ fi
+ else
+ # don't add current library to it's dependencies list
+ if test ${j} != ${ARTIFACT}; then
+ NON_RECURSIVE_BASE_DEPENDENCIES="${NON_RECURSIVE_BASE_DEPENDENCIES} ${j}"
+ fi
+ fi
+ done
+ # all found dependencies in the reverse compilation order
+ BASE_DEPENDENCIES=$(echo "${BASE_DEPENDENCIES}" | xargs)
+ # all found and valid dependencies in the reverse compilation order
+ NON_RECURSIVE_BASE_DEPENDENCIES=$(echo "${NON_RECURSIVE_BASE_DEPENDENCIES}" | xargs)
+ echo "${ARTIFACT_PATH}/${ARTIFACT} base dependencies:"
+ echo "${BASE_DEPENDENCIES}"
+ echo "${ARTIFACT_PATH}/${ARTIFACT} non recursive dependencies:"
+ echo "${NON_RECURSIVE_BASE_DEPENDENCIES}"
+ # minimum set of dependencies for current library
+ DEPENDENCIES=
+ for j in ${NON_RECURSIVE_BASE_DEPENDENCIES}; do
+ NEW_DEPENDENCIES=$(extract_computed_dependencies "${j}" "src/lib")
+ if test "${NEW_DEPENDENCIES}" == "NONE"; then
+ echo "### ERROR ### computed dependency not found for ${j}"
+ else
+ DEPENDENCIES="${NEW_DEPENDENCIES} ${DEPENDENCIES}"
+ fi
+ done
+ DEPENDENCIES=$(echo "${DEPENDENCIES} ${NON_RECURSIVE_BASE_DEPENDENCIES}" | tr -s " " "\n" | sort | uniq | xargs)
+ # order dependencies in the order of compilation
+ SORTED_DEPENDENCIES=
+ for j in ${LIBRARIES_LIST}; do
+ if test $(echo "${DEPENDENCIES}" | grep "\b${j}\b" | wc -l) -ne 0; then
+ SORTED_DEPENDENCIES="${j} ${SORTED_DEPENDENCIES}"
+ fi
+ done
+ echo "${ARTIFACT_PATH}/${ARTIFACT} minimum dependencies:"
+ echo "${SORTED_DEPENDENCIES}"
+ echo ""
+ echo "++++++++++++++++++++++++++++++++++++++++"
+ ARTIFACT_DIRECTIVE=$(extract_library_directive ${ARTIFACT_PATH}/${ARTIFACT})
+ for j in ${SORTED_DEPENDENCIES}; do
+ DEPENDENCY_LIBRARY_NAME=$(extract_library_name "src/lib/${j}")
+ echo "${ARTIFACT_DIRECTIVE} += \$(top_builddir)/src/lib/${j}/${DEPENDENCY_LIBRARY_NAME}"
+ done
+ echo "++++++++++++++++++++++++++++++++++++++++"
+ echo "########################################"
+ echo ""
+}
+
+# if wrong number of parameters print usage
+if test ${#} -ne 1; then
+ echo "Usage: ${0} path/to/kea/repo"
+ exit
+fi
+
+# folder containing full repo
+REPO_FOLDER=${1}
+
+if test $(echo -n ${REPO_FOLDER} | tail -c 1) != "/"; then
+ REPO_FOLDER="${REPO_FOLDER}/"
+fi
+
+# filter all Makefile.am files
+MAKEFILES_LIST=$(find ${REPO_FOLDER} | grep "Makefile\.am" | sed -e "s#${REPO_FOLDER}##g" | grep "src\/" | sort)
+
+# if no Makefile.am found exit
+if test -z "${MAKEFILES_LIST}"; then
+ echo "invalid repo path: no Makefile.am file found"
+ exit
+fi
+
+echo "list of Makefile.am:"
+echo "${MAKEFILES_LIST}"
+
+# base Makefile.am for all sources is in src/lib/Makefile.am
+BASE_MAKEFILE=$(echo "${MAKEFILES_LIST}" | grep "src\/lib\/Makefile.am")
+
+# if no src/lib/Makefile.am found exit
+if test -z ${BASE_MAKEFILE}; then
+ echo "invalid repo path: no src/lib/Makefile.am file found"
+ exit
+fi
+
+echo "base Makefile.am:"
+echo "${BASE_MAKEFILE}"
+
+# generate the list of libraries in the compilation order
+LIBRARIES_LIST=
+RAW_LIBRARIES_LIST=$(cat "${REPO_FOLDER}${BASE_MAKEFILE}" | grep "SUBDIRS")
+for i in ${RAW_LIBRARIES_LIST}; do
+ LIBRARIES_LIST="${LIBRARIES_LIST} $(echo ${i} | grep -v "SUBDIRS" | grep -v '=')"
+done
+
+# remove empty spaces
+LIBRARIES_LIST=$(echo "${LIBRARIES_LIST}" | tr -s ' ' | xargs)
+
+# generate the list of libraries in the reverse compilation order
+REVERSE_LIBRARIES_LIST=
+for i in ${LIBRARIES_LIST}; do
+ REVERSE_LIBRARIES_LIST="${i} ${REVERSE_LIBRARIES_LIST}"
+done
+
+echo "list of libraries:"
+echo "${LIBRARIES_LIST}"
+
+echo "reverse list of libraries:"
+echo "${REVERSE_LIBRARIES_LIST}"
+
+# filter all files of interest ignoring irrelevant ones
+# ignore .git, .libs, .deps doc folders and .o .lo .Plo .Po .gcno .gcda .m4 .dox .json .mes files
+FILE_LIST=$(find "${REPO_FOLDER}" 2>/dev/null | grep -v "\.git" | grep -v "\/\.libs\/" | grep -v "\.o$" | grep -v "\/\.deps\/" | grep -v "\.lo$" | grep -v "\.Plo$" | grep -v "\.Po$" | grep -v "\.gcno$" | grep -v "gcda" | grep -v "\.m4$" | grep -v "\.dox$" | grep -v "\.json$" | grep -v "\/doc\/" | grep -v "\.mes$" | sort)
+
+#echo "files:"
+#echo "${FILE_LIST}"
+
+BASE_LIBRARIES_MAKEFILES=
+
+# generate the list of dependencies for all libraries in src/lib
+for i in ${LIBRARIES_LIST}; do
+ # generate current library Makefile.am path
+ BASE_LIBRARIES_MAKEFILES="${BASE_LIBRARIES_MAKEFILES} src/lib/${i}/Makefile.am"
+ # extract dependencies found in the library folder
+ BASE_DEPENDENCIES=$(extract_includes "src/lib/${i}/Makefile.am")
+ # generate the list of valid dependencies for the current library (take compilation order into account)
+ VALID_LIST=$(extract_dependencies "${REVERSE_LIBRARIES_LIST}" "${i}")
+ compute_dependencies "${i}" "src/lib"
+ PATH_TO_NAME=$(echo "src/lib" | tr -s "/" "_")
+ declare COMPUTED_DEPENDENCIES_${PATH_TO_NAME}_${i}="${SORTED_DEPENDENCIES}"
+done
+
+# remove empty spaces
+BASE_LIBRARIES_MAKEFILES=$(echo "${BASE_LIBRARIES_MAKEFILES}" | xargs | tr -s " " "\n")
+
+echo "base Makefiles.am files:"
+echo "${BASE_LIBRARIES_MAKEFILES}"
+
+OTHER_MAKEFILES=$(echo "${MAKEFILES_LIST}" | tr -s " " "\n" | grep -v "src/lib/" | grep -v "src/share/" | grep -v "src/Makefile.am")
+# remove empty spaces
+OTHER_MAKEFILES=$(echo "${OTHER_MAKEFILES}" | xargs | tr -s " " "\n")
+
+echo "remaining Makefile.am files:"
+echo "${OTHER_MAKEFILES}"
+
+for i in ${OTHER_MAKEFILES}; do
+ # extract dependencies found in the artifact folder
+ BASE_DEPENDENCIES=$(extract_includes "${i}")
+ # generate the list of valid dependencies for the current artifact (take compilation order into account)
+ VALID_LIST="${REVERSE_LIBRARIES_LIST}"
+ ARTIFACT=$(echo "${i}" | rev | cut -d "/" -f 2 | rev)
+ ARTIFACT_PATH=$(echo "${i}" | rev | cut -d "/" -f 3- | rev)
+ compute_dependencies "${ARTIFACT}" "${ARTIFACT_PATH}"
+ PATH_TO_NAME=$(echo "${ARTIFACT_PATH}" | tr -s "/" "_")
+ declare COMPUTED_DEPENDENCIES_${PATH_TO_NAME}_${ARTIFACT}="${SORTED_DEPENDENCIES}"
+done
+
+exit
+