if (hooks) {
HooksLibrariesParser hooks_parser;
hooks_parser.parse(libraries, hooks);
- libraries.verifyLibraries(hooks->getPosition());
+ libraries.verifyLibraries(hooks->getPosition(), false);
}
if (!check_only) {
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
- libraries.loadLibraries();
+ libraries.loadLibraries(false);
}
}
ConstElementPtr auth_json;
ASSERT_NO_THROW(auth_json = Element::fromJSON(auth_cfg));
hooks_cfg.add(std::string(BASIC_AUTH_LIBRARY), auth_json);
- ASSERT_NO_THROW(hooks_cfg.loadLibraries());
+ ASSERT_NO_THROW(hooks_cfg.loadLibraries(false));
HttpResponsePtr response;
ASSERT_NO_THROW(response = response_creator_.createHttpResponse(request_));
ConstElementPtr auth_json;
ASSERT_NO_THROW(auth_json = Element::fromJSON(auth_cfg));
hooks_cfg.add(std::string(BASIC_AUTH_LIBRARY), auth_json);
- ASSERT_NO_THROW(hooks_cfg.loadLibraries());
+ ASSERT_NO_THROW(hooks_cfg.loadLibraries(false));
HttpResponsePtr response;
ASSERT_NO_THROW(response = response_creator_.createHttpResponse(request_));
HookLibsCollection loaded = HooksManager::getLibraryInfo();
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
- bool status = HooksManager::loadLibraries(loaded);
+ bool multi_threading_enabled = true;
+ uint32_t thread_count = 0;
+ uint32_t queue_size = 0;
+ CfgMultiThreading::extract(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading(),
+ multi_threading_enabled, thread_count, queue_size);
+ bool status = HooksManager::loadLibraries(loaded, multi_threading_enabled);
if (!status) {
isc_throw(Unexpected, "Failed to reload hooks libraries "
"(WARNING: libreload is deprecated).");
#include <dhcp/libdhcp++.h>
#include <dhcp/option_definition.h>
#include <dhcpsrv/cb_ctl_dhcp4.h>
+#include <dhcpsrv/cfg_multi_threading.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/config_backend_dhcp4_mgr.h>
parser.parse(*srv_config, multi_threading);
}
+ bool multi_threading_enabled = true;
+ uint32_t thread_count = 0;
+ uint32_t queue_size = 0;
+ CfgMultiThreading::extract(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading(),
+ multi_threading_enabled, thread_count, queue_size);
+
/// depends on "multi-threading" being enabled, so it must come after.
ConstElementPtr queue_control = mutable_cfg->get("dhcp-queue-control");
if (queue_control) {
parameter_name = "dhcp-queue-control";
DHCPQueueControlParser parser;
- srv_config->setDHCPQueueControl(parser.parse(queue_control));
+ srv_config->setDHCPQueueControl(parser.parse(queue_control, multi_threading_enabled));
}
/// depends on "multi-threading" being enabled, so it must come after.
ConstElementPtr reservations_lookup_first = mutable_cfg->get("reservations-lookup-first");
if (reservations_lookup_first) {
parameter_name = "reservations-lookup-first";
- if (MultiThreadingMgr::instance().getMode()) {
+ if (multi_threading_enabled) {
LOG_WARN(dhcp4_logger, DHCP4_RESERVATIONS_LOOKUP_FIRST_ENABLED);
}
srv_config->setReservationsLookupFirst(reservations_lookup_first->boolValue());
HooksLibrariesParser hooks_parser;
HooksConfig& libraries = srv_config->getHooksConfig();
hooks_parser.parse(libraries, hooks_libraries);
- libraries.verifyLibraries(hooks_libraries->getPosition());
+ libraries.verifyLibraries(hooks_libraries->getPosition(),
+ multi_threading_enabled);
}
// D2 client configuration.
static_cast<void>(HooksManager::unloadLibraries());
const HooksConfig& libraries =
CfgMgr::instance().getStagingCfg()->getHooksConfig();
- libraries.loadLibraries();
+ bool multi_threading_enabled = true;
+ uint32_t thread_count = 0;
+ uint32_t queue_size = 0;
+ CfgMultiThreading::extract(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading(),
+ multi_threading_enabled, thread_count, queue_size);
+ libraries.loadLibraries(multi_threading_enabled);
} catch (const isc::Exception& ex) {
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(ex.what());
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
ASSERT_NO_THROW(server_.reset(new NakedDhcpv4Srv()));
- MultiThreadingMgr::instance().setMode(true);
-
// Ensure no marker files to start with.
ASSERT_FALSE(checkMarkerFileExists(LOAD_MARKER_FILE));
ASSERT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE));
libraries.push_back(make_pair(std::string(CALLOUT_LIBRARY_2),
ConstElementPtr()));
- ASSERT_FALSE(HooksManager::loadLibraries(libraries));
+ ASSERT_FALSE(HooksManager::loadLibraries(libraries, true));
// The library is missing multi_threading_compatible function so loading
// should fail
libraries.push_back(make_pair(std::string(CALLOUT_LIBRARY_3),
ConstElementPtr()));
- ASSERT_FALSE(HooksManager::loadLibraries(libraries));
+ ASSERT_FALSE(HooksManager::loadLibraries(libraries, true));
// The library is not multi threading compatible so loading should fail
EXPECT_FALSE(checkMarkerFileExists(LOAD_MARKER_FILE));
HookLibsCollection loaded = HooksManager::getLibraryInfo();
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
- bool status = HooksManager::loadLibraries(loaded);
+ bool multi_threading_enabled = true;
+ uint32_t thread_count = 0;
+ uint32_t queue_size = 0;
+ CfgMultiThreading::extract(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading(),
+ multi_threading_enabled, thread_count, queue_size);
+ bool status = HooksManager::loadLibraries(loaded, multi_threading_enabled);
if (!status) {
isc_throw(Unexpected, "Failed to reload hooks libraries"
" (WARNING: libreload is deprecated).");
#include <dhcp/libdhcp++.h>
#include <dhcp/iface_mgr.h>
#include <dhcpsrv/cb_ctl_dhcp4.h>
+#include <dhcpsrv/cfg_multi_threading.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/db_type.h>
parser.parse(*srv_config, multi_threading);
}
+ bool multi_threading_enabled = true;
+ uint32_t thread_count = 0;
+ uint32_t queue_size = 0;
+ CfgMultiThreading::extract(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading(),
+ multi_threading_enabled, thread_count, queue_size);
+
/// depends on "multi-threading" being enabled, so it must come after.
ConstElementPtr queue_control = mutable_cfg->get("dhcp-queue-control");
if (queue_control) {
parameter_name = "dhcp-queue-control";
DHCPQueueControlParser parser;
- srv_config->setDHCPQueueControl(parser.parse(queue_control));
+ srv_config->setDHCPQueueControl(parser.parse(queue_control, multi_threading_enabled));
}
/// depends on "multi-threading" being enabled, so it must come after.
ConstElementPtr reservations_lookup_first = mutable_cfg->get("reservations-lookup-first");
if (reservations_lookup_first) {
parameter_name = "reservations-lookup-first";
- if (MultiThreadingMgr::instance().getMode()) {
+ if (multi_threading_enabled) {
LOG_WARN(dhcp6_logger, DHCP6_RESERVATIONS_LOOKUP_FIRST_ENABLED);
}
srv_config->setReservationsLookupFirst(reservations_lookup_first->boolValue());
HooksLibrariesParser hooks_parser;
HooksConfig& libraries = srv_config->getHooksConfig();
hooks_parser.parse(libraries, hooks_libraries);
- libraries.verifyLibraries(hooks_libraries->getPosition());
+ libraries.verifyLibraries(hooks_libraries->getPosition(),
+ multi_threading_enabled);
}
// D2 client configuration.
static_cast<void>(HooksManager::unloadLibraries());
const HooksConfig& libraries =
CfgMgr::instance().getStagingCfg()->getHooksConfig();
- libraries.loadLibraries();
+ bool multi_threading_enabled = true;
+ uint32_t thread_count = 0;
+ uint32_t queue_size = 0;
+ CfgMultiThreading::extract(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading(),
+ multi_threading_enabled, thread_count, queue_size);
+ libraries.loadLibraries(multi_threading_enabled);
} catch (const isc::Exception& ex) {
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(ex.what());
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
ASSERT_NO_THROW(server_.reset(new NakedDhcpv6Srv(0)));
- MultiThreadingMgr::instance().setMode(true);
-
// Ensure no marker files to start with.
ASSERT_FALSE(checkMarkerFileExists(LOAD_MARKER_FILE));
ASSERT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE));
libraries.push_back(make_pair(std::string(CALLOUT_LIBRARY_2),
ConstElementPtr()));
- ASSERT_FALSE(HooksManager::loadLibraries(libraries));
+ ASSERT_FALSE(HooksManager::loadLibraries(libraries, true));
// The library is missing multi_threading_compatible function so loading
// should fail
libraries.push_back(make_pair(std::string(CALLOUT_LIBRARY_3),
ConstElementPtr()));
- ASSERT_FALSE(HooksManager::loadLibraries(libraries));
+ ASSERT_FALSE(HooksManager::loadLibraries(libraries, true));
// The library is not multi threading compatible so loading should fail
EXPECT_FALSE(checkMarkerFileExists(LOAD_MARKER_FILE));
if (hooks) {
HooksLibrariesParser hooks_parser;
hooks_parser.parse(libraries, hooks);
- libraries.verifyLibraries(hooks->getPosition());
+ libraries.verifyLibraries(hooks->getPosition(), false);
}
if (!check_only) {
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
- libraries.loadLibraries();
+ libraries.loadLibraries(false);
}
}
} catch (const std::exception& ex) {
LOG_ERROR(ha_logger, HA_DHCP4_START_SERVICE_FAILED)
.arg(ex.what());
+ handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
return (1);
}
return (0);
} catch (const std::exception& ex) {
LOG_ERROR(ha_logger, HA_DHCP6_START_SERVICE_FAILED)
.arg(ex.what());
+ handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
return (1);
}
return (0);
} catch (const std::exception& ex) {
LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)
.arg(ex.what());
+ handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
return (1);
}
return (0);
} catch (const std::exception& ex) {
LOG_ERROR(run_script_logger, RUN_SCRIPT_LOAD_ERROR)
.arg(ex.what());
+ handle.setStatus(isc::hooks::CalloutHandle::NEXT_STEP_DROP);
return (1);
}
return (0);
if (hooks) {
HooksLibrariesParser hooks_parser;
hooks_parser.parse(libraries, hooks);
- libraries.verifyLibraries(hooks->getPosition());
+ libraries.verifyLibraries(hooks->getPosition(), false);
}
// Attempt to create the new client config. This ought to fly as
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
- libraries.loadLibraries();
+ libraries.loadLibraries(false);
}
}
void
CfgMultiThreading::extract(ConstElementPtr value, bool& enabled,
uint32_t& thread_count, uint32_t& queue_size) {
- enabled = false;
+ enabled = true;
thread_count = 0;
queue_size = 0;
if (value) {
namespace dhcp {
ElementPtr
-DHCPQueueControlParser::parse(const ConstElementPtr& control_elem) {
+DHCPQueueControlParser::parse(const ConstElementPtr& control_elem,
+ bool multi_threading_enabled) {
// All we really do here is verify that it is a map that
// contains at least queue-type. All other content depends
// on the packet queue implementation of that type.
ElementPtr result = data::copy(control_elem);
// Currently not compatible with multi-threading.
- if (MultiThreadingMgr::instance().getMode()) {
+ if (multi_threading_enabled) {
// Silently disable it.
result->set("enable-queue", Element::create(false));
}
class DHCPQueueControlParser : public isc::data::SimpleParser {
public:
- /// @brief Constructor
- ///
+ /// @brief Constructor.
DHCPQueueControlParser(){};
/// @brief Parses content of the "dhcp-queue-control".
///
/// @param control_elem MapElement containing the queue control values to
- /// parse
+ /// parse.
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled.
///
/// @return A copy of the of the input MapElement.
///
/// @throw DhcpConfigError if any of the values are invalid.
- data::ElementPtr parse(const isc::data::ConstElementPtr& control_elem);
+ data::ElementPtr parse(const isc::data::ConstElementPtr& control_elem,
+ bool multi_threading_enabled);
private:
};
}
// enable-multi-threading is mandatory
- auto enabled = getBoolean(value, "enable-multi-threading");
+ getBoolean(value, "enable-multi-threading");
// thread-pool-size is not mandatory
if (value->get("thread-pool-size")) {
}
srv_cfg.setDHCPMultiThreading(value);
-
- // Set the mode so that it can be inspected by other configuration parsers
- // such as the ones in hook libraries. This creates a dangerous discordance
- // between the MT mode and the real configuration. For instance, it may
- // result in packets not being processed because the listener thread sees
- // the MT mode enabled, but in fact there are 0 threads to handle the
- // packets. In production code, it is expected that a call to
- // ControlledDhcpvXSrv::processConfig() applies the configuration, which
- // should properly create the threads and close this divide.
- MultiThreadingMgr::instance().setMode(enabled);
}
} // namespace dhcp
//check empty config
ASSERT_NO_THROW(CfgMultiThreading::extract(param, enabled, thread_count,
queue_size));
- EXPECT_EQ(enabled, false);
+ EXPECT_EQ(enabled, true);
EXPECT_EQ(thread_count, 0);
EXPECT_EQ(queue_size, 0);
// check empty data
ASSERT_NO_THROW(CfgMultiThreading::extract(ConstElementPtr(), enabled,
thread_count, queue_size));
- EXPECT_EQ(enabled, false);
+ EXPECT_EQ(enabled, true);
EXPECT_EQ(thread_count, 0);
EXPECT_EQ(queue_size, 0);
}
EXPECT_NO_THROW(parser.parse(sources, values));
// Finally, check the sources that were configured
- CfgMACSources configured_sources = cfg->getMACSources().get();
+ CfgMACSources configured_sources = cfg->getMACSources().get();
ASSERT_EQ(2, configured_sources.size());
EXPECT_EQ(HWAddr::HWADDR_SOURCE_DUID, configured_sources[0]);
EXPECT_EQ(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL, configured_sources[1]);
if (config_pair.first == "hooks-libraries") {
HooksLibrariesParser hook_parser;
- HooksConfig& libraries =
+ HooksConfig& libraries =
CfgMgr::instance().getStagingCfg()->getHooksConfig();
hook_parser.parse(libraries, config_pair.second);
- libraries.verifyLibraries(config_pair.second->getPosition());
- libraries.loadLibraries();
+ libraries.verifyLibraries(config_pair.second->getPosition(), false);
+ libraries.loadLibraries(false);
continue;
}
}
const SimpleDefaults ParseConfigTest::OPTION6_DEFAULTS = {
{ "space", Element::string, "dhcp6"},
{ "csv-format", Element::boolean, "true"},
- { "always-send", Element::boolean,"false"},
- { "never-send", Element::boolean,"false"}
+ { "always-send", Element::boolean, "false"},
+ { "never-send", Element::boolean, "false"}
};
/// This table defines default values for options in DHCPv4
"0C 00 03 01 C0 00 03 02", // spaces
"0C:00:03:01:C0:00:03:02", // colons
"0x0C000301C0000302", // 0x
- "C 0 3 1 C0 0 3 02", // one or two digit octets
+ "C 0 3 1 C0 0 3 02", // one or two digit octets
"0x0c000301C0000302" // upper or lower case digits
};
EXPECT_EQ(D2ClientConfig::RCM_NEVER, subnet->getDdnsReplaceClientNameMode().get());
EXPECT_TRUE(subnet->getDdnsGeneratedPrefix().unspecified());
- EXPECT_EQ("", subnet->getDdnsGeneratedPrefix().get());
+ EXPECT_TRUE(subnet->getDdnsGeneratedPrefix().empty());
EXPECT_TRUE(subnet->getDdnsQualifyingSuffix().unspecified());
EXPECT_TRUE(subnet->getDdnsQualifyingSuffix().empty());
// Parsing config into a queue control should succeed.
DHCPQueueControlParser parser;
try {
- queue_control = parser.parse(config_elems);
+ queue_control = parser.parse(config_elems, false);
} catch (const std::exception& ex) {
ADD_FAILURE() << "parser threw an exception: " << ex.what();
}
// Parsing config into a queue control should succeed.
DHCPQueueControlParser parser;
- EXPECT_THROW(parser.parse(config_elems), DhcpConfigError);
+ EXPECT_THROW(parser.parse(config_elems, false), DhcpConfigError);
}
}
}
// Parse config.
DHCPQueueControlParser parser;
ConstElementPtr queue_control;
- ASSERT_FALSE(MultiThreadingMgr::instance().getMode());
- ASSERT_NO_THROW(queue_control = parser.parse(config_elems))
+ ASSERT_NO_THROW(queue_control = parser.parse(config_elems, false))
<< "parse fails, test is broken";
+
// Verify that queue is enabled.
ASSERT_TRUE(queue_control);
ASSERT_TRUE(queue_control->get("enable-queue"));
EXPECT_EQ("true", queue_control->get("enable-queue")->str());
// Retry with multi-threading.
- MultiThreadingTest mt(true);
- ASSERT_TRUE(MultiThreadingMgr::instance().getMode());
- ASSERT_NO_THROW(queue_control = parser.parse(config_elems));
+ ASSERT_NO_THROW(queue_control = parser.parse(config_elems, true));
ASSERT_TRUE(queue_control);
ASSERT_TRUE(queue_control->get("enable-queue"));
EXPECT_EQ("false", queue_control->get("enable-queue")->str());
CfgMultiThreading::extract(multi_threading_config, enabled,
thread_count, queue_size);
- EXPECT_EQ(MultiThreadingMgr::instance().getMode(), enabled);
-
EXPECT_TRUE(multi_threading_config->equals(*config_elems));
}
}
namespace hooks {
void
-HooksConfig::verifyLibraries(const Element::Position& position) const {
+HooksConfig::verifyLibraries(const Element::Position& position,
+ bool multi_threading_enabled) const {
// The code used to follow this logic:
//
// Check if the list of libraries has changed. If not, nothing is done
// Library list has changed, validate each of the libraries specified.
vector<string> lib_names = isc::hooks::extractNames(libraries_);
- vector<string> error_libs = HooksManager::validateLibraries(lib_names);
+ vector<string> error_libs = HooksManager::validateLibraries(lib_names,
+ multi_threading_enabled);
if (!error_libs.empty()) {
// Construct the list of libraries in error for the message.
}
void
-HooksConfig::loadLibraries() const {
+HooksConfig::loadLibraries(bool multi_threading_enabled) const {
/// Commits the list of libraries to the configuration manager storage if
/// the list of libraries has changed.
/// @todo: Delete any stored CalloutHandles before reloading the
/// libraries
- if (!HooksManager::loadLibraries(libraries_)) {
+ if (!HooksManager::loadLibraries(libraries_, multi_threading_enabled)) {
isc_throw(InvalidHooksLibraries,
"One or more hook libraries failed to load");
}
/// It tries to validate all the libraries stored in libraries_.
///
/// @param position position of the hooks-library map for error reporting
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
+ ///
/// @throw InvalidHooksLibraries if any issue is discovered.
- void verifyLibraries(const isc::data::Element::Position& position) const;
+ void verifyLibraries(const isc::data::Element::Position& position,
+ bool multi_threading_enabled) const;
/// @brief Commits hooks libraries configuration.
///
/// different to those already loaded, this method loads the new set of
/// libraries (and unloads the existing set).
///
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
+ ///
/// @throw InvalidHooksLibraries if the call to HooksManager fails.
- void loadLibraries() const;
+ void loadLibraries(bool multi_threading_enabled) const;
/// @brief Unparse a configuration object
///
isc::hooks::HookLibsCollection libraries_;
};
-};
-};
+} // namespace hooks
+} // namespace isc
#endif // HOOKS_CONFIG_H
// libraries, and get the CalloutManager.
HookLibsCollection libraries;
lm_collection_.reset(new LibraryManagerCollection(libraries));
- lm_collection_->loadLibraries();
+ lm_collection_->loadLibraries(false);
callout_manager_ = lm_collection_->getCalloutManager();
}
// empty list.
bool
-HooksManager::loadLibrariesInternal(const HookLibsCollection& libraries) {
+HooksManager::loadLibrariesInternal(const HookLibsCollection& libraries,
+ bool multi_threading_enabled) {
if (test_mode_) {
return (true);
}
}
// Load the libraries.
- bool status = lm_collection_->loadLibraries();
+ bool status = lm_collection_->loadLibraries(multi_threading_enabled);
if (status) {
// ... and obtain the callout manager for them if successful.
}
bool
-HooksManager::loadLibraries(const HookLibsCollection& libraries) {
- return (getHooksManager().loadLibrariesInternal(libraries));
+HooksManager::loadLibraries(const HookLibsCollection& libraries,
+ bool multi_threading_enabled) {
+ return (getHooksManager().loadLibrariesInternal(libraries,
+ multi_threading_enabled));
}
// Unload the libraries. This just deletes all internal objects (which will
}
// Load the empty set of libraries.
- lm_collection_->loadLibraries();
+ lm_collection_->loadLibraries(false);
// Get the CalloutManager.
callout_manager_ = lm_collection_->getCalloutManager();
// Validate libraries
std::vector<std::string>
-HooksManager::validateLibraries(const std::vector<std::string>& libraries) {
- return (LibraryManagerCollection::validateLibraries(libraries));
+HooksManager::validateLibraries(const std::vector<std::string>& libraries,
+ bool multi_threading_enabled) {
+ return (LibraryManagerCollection::validateLibraries(libraries,
+ multi_threading_enabled));
}
// Test mode
/// @param libraries List of libraries to be loaded. The order is
/// important, as it determines the order that callouts on the same
/// hook will be called.
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
///
/// @return true if all libraries loaded without a problem, false if one or
/// more libraries failed to load. In the latter case, message will
/// be logged that give the reason.
/// @throw LibrariesStillOpened when some libraries are already loaded.
- static bool loadLibraries(const HookLibsCollection& libraries);
+ static bool loadLibraries(const HookLibsCollection& libraries,
+ bool multi_threading_enabled = false);
/// @brief Unload libraries
///
/// change is committed.
///
/// @param libraries List of libraries to be validated.
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
///
/// @return An empty vector if all libraries validated. Otherwise it
/// holds the names of the libraries that failed validation.
- static std::vector<std::string> validateLibraries(
- const std::vector<std::string>& libraries);
+ static std::vector<std::string> validateLibraries(const std::vector<std::string>& libraries,
+ bool multi_threading_enabled = false);
/// Index numbers for pre-defined hooks.
static const int CONTEXT_CREATE = ServerHooks::CONTEXT_CREATE;
/// but actually do the work on the singleton instance of the HooksManager.
/// See the descriptions of the static methods for more details.
- /// @brief Validate library list
- ///
- /// @param List of libraries to be validated.
- ///
- /// @return An empty string if all libraries validated. Otherwise it is
- /// the name of the first library that failed validation. The
- /// configuration code can return this to bindctl as an indication
- /// of the problem.
- std::string validateLibrariesInternal(
- const std::vector<std::string>& libraries) const;
-
/// @brief Load and reload libraries
///
/// @param libraries List of libraries to be loaded. The order is
/// important, as it determines the order that callouts on the same
/// hook will be called.
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
///
/// @return true if all libraries loaded without a problem, false if one or
/// more libraries failed to load. In the latter case, message will
/// be logged that give the reason.
- bool loadLibrariesInternal(const HookLibsCollection& libraries);
+ bool loadLibrariesInternal(const HookLibsCollection& libraries,
+ bool multi_threading_enabled);
/// @brief Unload libraries
///
// Check the multi-threading compatibility of the library
bool
-LibraryManager::checkMultiThreadingCompatible() const {
+LibraryManager::checkMultiThreadingCompatible(bool multi_threading_enabled) const {
// Compatible with single-threaded.
- if (!util::MultiThreadingMgr::instance().getMode()) {
+ if (!multi_threading_enabled) {
return (true);
}
// The main library loading function.
bool
-LibraryManager::loadLibrary() {
+LibraryManager::loadLibrary(bool multi_threading_enabled) {
LOG_DEBUG(hooks_logger, HOOKS_DBG_TRACE, HOOKS_LIBRARY_LOADING)
.arg(library_name_);
// Library opened OK, see if a version function is present and if so,
// check what value it returns. Check multi-threading compatibility.
- if (checkVersion() && checkMultiThreadingCompatible()) {
+ if (checkVersion() && checkMultiThreadingCompatible(multi_threading_enabled)) {
// Version OK, so now register the standard callouts and call the
// library's load() function if present.
registerStandardCallouts();
// method.
bool
-LibraryManager::validateLibrary(const std::string& name) {
+LibraryManager::validateLibrary(const std::string& name, bool multi_threading_enabled) {
// Instantiate a library manager for the validation. We use the private
// constructor as we don't supply a CalloutManager.
LibraryManager manager(name);
// Try to open it and, if we succeed, check the version.
bool validated = manager.openLibrary() && manager.checkVersion() &&
- manager.checkMultiThreadingCompatible();
+ manager.checkMultiThreadingCompatible(multi_threading_enabled);
// Regardless of whether the version checked out, close the library. (This
// is a no-op if the library failed to open.)
/// returns the right number, and the multi-threading compatibility.
///
/// @param name Name of the library to validate
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
///
/// @return true if the library validated, false if not. If the library
/// fails to validate, the reason for the failure is logged.
- static bool validateLibrary(const std::string& name);
+ static bool validateLibrary(const std::string& name,
+ bool multi_threading_enabled = false);
/// @brief Loads a library
///
/// update the global logging dictionary with the log messages
/// registered by the loaded library.
///
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
+ ///
/// @return true if the library loaded successfully, false otherwise.
/// In the latter case, the library will be unloaded if possible.
- bool loadLibrary();
+ bool loadLibrary(bool multi_threading_enabled = false);
/// @brief Prepares library unloading
///
/// @brief Check multi-threading compatibility
///
- /// If the multi-threading mode is false returns true, else with
+ /// If the multi-threading mode is disabled returns true, else with
/// the library open, accesses the "multi_threading_compatible()"
/// function and returns false if not exists or has value 0, returns
/// true otherwise.
///
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
+ ///
/// @return bool true if the check succeeded
- bool checkMultiThreadingCompatible() const;
+ bool checkMultiThreadingCompatible(bool multi_threading_enabled) const;
/// @brief Register standard callouts
///
// Load a set of libraries
bool
-LibraryManagerCollection::loadLibraries() {
+LibraryManagerCollection::loadLibraries(bool multi_threading_enabled) {
// There must be no libraries still in memory.
if (!lib_managers_.empty()) {
// libraries. On failure, unload all currently loaded libraries,
// leaving the object in the state it was in before loadLibraries was
// called.
- if (manager->loadLibrary()) {
+ if (manager->loadLibrary(multi_threading_enabled)) {
lib_managers_.push_back(manager);
} else {
static_cast<void>(unloadLibraries());
// Validate the libraries.
std::vector<std::string>
-LibraryManagerCollection::validateLibraries(
- const std::vector<std::string>& libraries) {
+LibraryManagerCollection::validateLibraries(const std::vector<std::string>& libraries,
+ bool multi_threading_enabled) {
std::vector<std::string> failures;
for (size_t i = 0; i < libraries.size(); ++i) {
- if (!LibraryManager::validateLibrary(libraries[i])) {
+ if (!LibraryManager::validateLibrary(libraries[i], multi_threading_enabled)) {
failures.push_back(libraries[i]);
}
}
/// to load, the loading is abandoned and all libraries loaded so far
/// are unloaded.
///
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
+ ///
/// @return true if all libraries loaded, false if one or more failed t
//// load.
- bool loadLibraries();
+ bool loadLibraries(bool multi_threading_enabled = false);
/// @brief Get callout manager
///
/// exist, can be opened, that a "version" function is present in them, and
/// that it returns the right number. All errors are logged.
///
- /// @param libraries List of libraries to validate
+ /// @param libraries List of libraries to validate.
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled
+ /// (used to check hook libraries compatibility with MT).
///
/// @return Vector of libraries that failed to validate, or an empty vector
/// if all validated.
- static std::vector<std::string>
- validateLibraries(const std::vector<std::string>& libraries);
+ static std::vector<std::string> validateLibraries(const std::vector<std::string>& libraries,
+ bool multi_threading_enabled = false);
/// @brief Prepare libaries unloading
///
EXPECT_TRUE(lib_manager.openLibrary());
// Not multi-threading compatible: does not matter without MT.
- EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+ EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(false));
// Not multi-threading compatible: does matter with MT.
- MultiThreadingMgr::instance().setMode(true);
- EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible());
+ EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible(true));
// Tidy up.
EXPECT_TRUE(lib_manager.closeLibrary());
EXPECT_TRUE(lib_manager.openLibrary());
// Not multi-threading compatible: does not matter without MT.
- EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+ EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(false));
// Not multi-threading compatible: does matter with MT.
- MultiThreadingMgr::instance().setMode(true);
- EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible());
+ EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible(true));
// Tidy up.
EXPECT_TRUE(lib_manager.closeLibrary());
EXPECT_TRUE(lib_manager.openLibrary());
// Multi-threading compatible: does not matter without MT.
- EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+ EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(false));
// Multi-threading compatible: does matter with MT.
- MultiThreadingMgr::instance().setMode(true);
- EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+ EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(true));
// Tidy up.
EXPECT_TRUE(lib_manager.closeLibrary());
EXPECT_TRUE(lib_manager.openLibrary());
// Throw exception: does not matter without MT.
- EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+ EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(false));
// Throw exception: does matter with MT.
- MultiThreadingMgr::instance().setMode(true);
- EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible());
+ EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible(true));
// Tidy up.
EXPECT_TRUE(lib_manager.closeLibrary());
EXPECT_TRUE(LibraryManager::validateLibrary(UNLOAD_CALLOUT_LIBRARY));
EXPECT_TRUE(LibraryManager::validateLibrary(CALLOUT_PARAMS_LIBRARY));
- MultiThreadingMgr::instance().setMode(true);
-
- EXPECT_FALSE(LibraryManager::validateLibrary(BASIC_CALLOUT_LIBRARY));
- EXPECT_TRUE(LibraryManager::validateLibrary(FULL_CALLOUT_LIBRARY));
- EXPECT_FALSE(LibraryManager::validateLibrary(FRAMEWORK_EXCEPTION_LIBRARY));
- EXPECT_FALSE(LibraryManager::validateLibrary(INCORRECT_VERSION_LIBRARY));
- EXPECT_FALSE(LibraryManager::validateLibrary(LOAD_CALLOUT_LIBRARY));
- EXPECT_FALSE(LibraryManager::validateLibrary(LOAD_ERROR_CALLOUT_LIBRARY));
- EXPECT_FALSE(LibraryManager::validateLibrary(NOT_PRESENT_LIBRARY));
- EXPECT_FALSE(LibraryManager::validateLibrary(NO_VERSION_LIBRARY));
- EXPECT_FALSE(LibraryManager::validateLibrary(UNLOAD_CALLOUT_LIBRARY));
- EXPECT_FALSE(LibraryManager::validateLibrary(CALLOUT_PARAMS_LIBRARY));
+ EXPECT_FALSE(LibraryManager::validateLibrary(BASIC_CALLOUT_LIBRARY, true));
+ EXPECT_TRUE(LibraryManager::validateLibrary(FULL_CALLOUT_LIBRARY, true));
+ EXPECT_FALSE(LibraryManager::validateLibrary(FRAMEWORK_EXCEPTION_LIBRARY, true));
+ EXPECT_FALSE(LibraryManager::validateLibrary(INCORRECT_VERSION_LIBRARY, true));
+ EXPECT_FALSE(LibraryManager::validateLibrary(LOAD_CALLOUT_LIBRARY, true));
+ EXPECT_FALSE(LibraryManager::validateLibrary(LOAD_ERROR_CALLOUT_LIBRARY, true));
+ EXPECT_FALSE(LibraryManager::validateLibrary(NOT_PRESENT_LIBRARY, true));
+ EXPECT_FALSE(LibraryManager::validateLibrary(NO_VERSION_LIBRARY, true));
+ EXPECT_FALSE(LibraryManager::validateLibrary(UNLOAD_CALLOUT_LIBRARY, true));
+ EXPECT_FALSE(LibraryManager::validateLibrary(CALLOUT_PARAMS_LIBRARY, true));
}
// Check that log messages are properly registered and unregistered.
HttpClient::HttpClient(IOService& io_service, size_t thread_pool_size,
bool defer_thread_start /* = false */) {
- if (thread_pool_size > 0) {
- if (!MultiThreadingMgr::instance().getMode()) {
- isc_throw(InvalidOperation,
- "HttpClient thread_pool_size must be zero"
- "when Kea core multi-threading is disabled");
- }
- }
-
impl_.reset(new HttpClientImpl(io_service, thread_pool_size,
defer_thread_start));
}
// Make sure destruction doesn't throw.
ASSERT_NO_THROW_LOG(client.reset());
- // Non-zero thread-pool-size means multi-threaded mode, should throw.
- ASSERT_THROW_MSG(client.reset(new HttpClient(io_service_, 1)), InvalidOperation,
- "HttpClient thread_pool_size must be zero"
- "when Kea core multi-threading is disabled");
- ASSERT_FALSE(client);
-
// Enable Kea core multi-threading.
MultiThreadingMgr::instance().setMode(true);