HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_decline");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("host4_identifier");
- HooksManager::getSharedCalloutManager().reset();
+ HooksManager::getHooksManager().setSharedCalloutManager();
delete srv_;
}
IfaceMgr::instance().openSockets4();
// Libraries will be reloaded later
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Install a callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
IfaceMgr::instance().openSockets4();
// Libraries will be reloaded later
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Install a callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
IfaceMgr::instance().openSockets4();
// Libraries will be reloaded later
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Install a callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
~HooksDhcpv6SrvTest() {
// Clear shared manager
- HooksManager::getSharedCalloutManager().reset();
+ HooksManager::getHooksManager().setSharedCalloutManager();
}
IfaceMgrTestConfig test_config(true);
// Libraries will be reloaded later
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Install lease6_decline callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
IfaceMgrTestConfig test_config(true);
// Libraries will be reloaded later
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Install lease6_decline_skip callout. It will set the status to skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
IfaceMgrTestConfig test_config(true);
// Libraries will be reloaded later
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Install lease6_decline_drop callout. It will set the status to drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
// Constructor
-HooksManager::HooksManager() {
+HooksManager::HooksManager() : loaded_(false) {
+ init();
}
// Return reference to singleton hooks manager.
bool
HooksManager::calloutsPresentInternal(int index) {
- conditionallyInitialize();
return (callout_manager_->calloutsPresent(index));
}
bool
HooksManager::commandHandlersPresentInternal(const std::string& command_name) {
- conditionallyInitialize();
return (callout_manager_->commandHandlersPresent(command_name));
}
void
HooksManager::callCalloutsInternal(int index, CalloutHandle& handle) {
- conditionallyInitialize();
callout_manager_->callCallouts(index, handle);
}
void
HooksManager::callCommandHandlersInternal(const std::string& command_name,
CalloutHandle& handle) {
- conditionallyInitialize();
callout_manager_->callCommandHandlers(command_name, handle);
}
getHooksManager().callCommandHandlersInternal(command_name, handle);
}
-
// Load the libraries. This will delete the previously-loaded libraries
-// (if present) and load new ones.
+// (if present) and load new ones. If loading libraries fails, initialize with
+// empty list.
bool
HooksManager::loadLibrariesInternal(const HookLibsCollection& libraries) {
// Unload current set of libraries (if any are loaded).
- unloadLibrariesInternal();
+ unloadLibrariesInternal(false);
// Create the library manager and load the libraries.
- lm_collection_.reset(new LibraryManagerCollection(libraries));
+ lm_collection_.reset(new LibraryManagerCollection(libraries, shared_callout_manager_));
bool status = lm_collection_->loadLibraries();
if (status) {
} else {
// Unable to load libraries, reset to state before this function was
// called.
- lm_collection_.reset();
- callout_manager_.reset();
+ init();
}
+ loaded_ = true;
+
return (status);
}
return (getHooksManager().loadLibrariesInternal(libraries));
}
-// Unload the libraries. This just deletes all internal objects which will
-// cause the libraries to be unloaded.
+// Unload the libraries. This just deletes all internal objects (which will
+// cause the libraries to be unloaded) and initializes them with empty list if
+// requested.
void
-HooksManager::unloadLibrariesInternal() {
- // The order of deletion does not matter here, as each library manager
- // holds its own pointer to the callout manager. However, we may as
- // well delete the library managers first: if there are no other references
- // to the callout manager, the second statement will delete it, which may
- // ease debugging.
- lm_collection_.reset();
- callout_manager_.reset();
+HooksManager::unloadLibrariesInternal(bool initialize) {
ServerHooks::getServerHooks().getParkingLotsPtr()->clear();
+ if (initialize) {
+ init();
+ } else {
+ lm_collection_.reset();
+ callout_manager_.reset();
+ }
+
+ loaded_ = false;
}
void HooksManager::unloadLibraries() {
boost::shared_ptr<CalloutHandle>
HooksManager::createCalloutHandleInternal() {
- conditionallyInitialize();
- return (boost::shared_ptr<CalloutHandle>(
- new CalloutHandle(callout_manager_, lm_collection_)));
+ return (boost::make_shared<CalloutHandle>(callout_manager_, lm_collection_));
}
boost::shared_ptr<CalloutHandle>
std::vector<std::string>
HooksManager::getLibraryNamesInternal() const {
- return (lm_collection_ ? lm_collection_->getLibraryNames()
- : std::vector<std::string>());
+ return (lm_collection_->getLibraryNames());
}
HookLibsCollection
HooksManager::getLibraryInfoInternal() const {
- return (lm_collection_ ? lm_collection_->getLibraryInfo()
- : HookLibsCollection());
+ return (lm_collection_->getLibraryInfo());
}
std::vector<std::string>
return (getHooksManager().getLibraryInfoInternal());
}
-// Perform conditional initialization if nothing is loaded.
+// Perform initialization
void
-HooksManager::performConditionalInitialization() {
-
+HooksManager::init() {
// Nothing present, so create the collection with any empty set of
// libraries, and get the CalloutManager.
HookLibsCollection libraries;
- lm_collection_.reset(new LibraryManagerCollection(libraries));
+ lm_collection_.reset(new LibraryManagerCollection(libraries, shared_callout_manager_));
lm_collection_->loadLibraries();
-
callout_manager_ = lm_collection_->getCalloutManager();
}
isc::hooks::LibraryHandle&
HooksManager::preCalloutsLibraryHandleInternal() {
- conditionallyInitialize();
return (callout_manager_->getPreLibraryHandle());
}
isc::hooks::LibraryHandle&
HooksManager::postCalloutsLibraryHandleInternal() {
- conditionallyInitialize();
return (callout_manager_->getPostLibraryHandle());
}
return (LibraryManagerCollection::validateLibraries(libraries));
}
-// Shared callout manager
-boost::shared_ptr<CalloutManager>&
+boost::shared_ptr<CalloutManager>
HooksManager::getSharedCalloutManager() {
- return (getHooksManager().shared_callout_manager_);
+ return (shared_callout_manager_);
+}
+
+void
+HooksManager::setSharedCalloutManager(boost::shared_ptr<CalloutManager> manager) {
+ shared_callout_manager_ = manager;
+ if (!loaded_) {
+ init();
+ }
}
} // namespace util
static const int CONTEXT_CREATE = ServerHooks::CONTEXT_CREATE;
static const int CONTEXT_DESTROY = ServerHooks::CONTEXT_DESTROY;
- /// @brief Return the shared callout manager
- ///
- /// Declared as static as other methods but only one for the
- /// singleton will be created.
+ /// @brief Get the shared callout manager
///
/// @return A reference to the shared callout manager
- static boost::shared_ptr<CalloutManager>& getSharedCalloutManager();
+ boost::shared_ptr<CalloutManager> getSharedCalloutManager();
+
+ /// @brief Set the shared callout manager
+ ///
+ /// This function sets the shared callout manager and explicitly updates
+ /// @ref callout_manager_ (by calling @ref init) if @ref loadLibraries has
+ /// not yet been called.
+ ///
+ /// @param manager The shared callout manager
+ void setSharedCalloutManager(boost::shared_ptr<CalloutManager> manager =
+ boost::shared_ptr<CalloutManager>());
/// @brief Park an object (packet).
///
bool loadLibrariesInternal(const HookLibsCollection& libraries);
/// @brief Unload libraries
- void unloadLibrariesInternal();
+ ///
+ /// @param initialize flag to indicate if intializing or just resetting the
+ /// @ref lm_collection_ and @ref callout_manager_
+ void unloadLibrariesInternal(bool initialize = true);
/// @brief Are callouts present?
///
/// @brief Initialization to No Libraries
///
- /// Initializes the hooks manager with an "empty set" of libraries. This
- /// method is called if conditionallyInitialize() determines that such
- /// initialization is needed.
- void performConditionalInitialization();
-
- /// @brief Conditional initialization of the hooks manager
- ///
- /// loadLibraries() performs the initialization of the HooksManager,
- /// setting up the internal structures and loading libraries. However,
- /// in some cases, server authors may not do that. This method is called
- /// whenever any hooks execution function is invoked (checking callouts,
- /// calling callouts or returning a callout handle). If the HooksManager
- /// is uninitialized, it will initialize it with an "empty set"
- /// of libraries.
- ///
- /// For speed, the test of whether initialization is required is done
- /// in-line here. The actual initialization is performed in
- /// performConditionalInitialization().
- void conditionallyInitialize() {
- if (!lm_collection_) {
- performConditionalInitialization();
- }
- }
+ /// Initializes the hooks manager with an "empty set" of libraries.
+ void init();
// Members
/// Shared callout manager to survive library reloads.
boost::shared_ptr<CalloutManager> shared_callout_manager_;
+ /// Loaded flag to indicate if @ref loadLibraries has been called
+ bool loaded_;
};
} // namespace util
#include <config.h>
#include <hooks/callout_manager.h>
-#include <hooks/hooks_manager.h>
#include <hooks/library_manager.h>
#include <hooks/library_manager_collection.h>
LibraryManagerCollection::getCalloutManager() const {
// Only return a pointer if we have a CalloutManager created.
- if (! callout_manager_) {
+ if (!callout_manager_) {
isc_throw(LoadLibrariesNotCalled, "must load hooks libraries before "
"attempting to retrieve a CalloutManager for them");
}
return (callout_manager_);
}
-LibraryManagerCollection::LibraryManagerCollection(const HookLibsCollection& libraries)
- :library_info_(libraries) {
+LibraryManagerCollection::LibraryManagerCollection(const HookLibsCollection& libraries,
+ const boost::shared_ptr<CalloutManager>& manager)
+ : shared_callout_manager_(manager), library_info_(libraries) {
// We need to split hook libs into library names and library parameters.
for (HookLibsCollection::const_iterator it = libraries.begin();
// to re-use the existing callout manager (so retaining registered pre-
// and post-library callouts).
if (library_names_.empty()) {
- callout_manager_ = HooksManager::getSharedCalloutManager();
+ callout_manager_ = shared_callout_manager_;
}
if (!library_names_.empty() || !callout_manager_) {
callout_manager_.reset(new CalloutManager(library_names_.size()));
#define LIBRARY_MANAGER_COLLECTION_H
#include <exceptions/exceptions.h>
+#include <hooks/hooks_manager.h>
#include <boost/shared_ptr.hpp>
#include <hooks/libinfo.h>
/// @param libraries List of libraries that this collection will manage.
/// The order of the libraries is important. It holds the library
/// names and its configuration parameters.
- LibraryManagerCollection(const HookLibsCollection& libraries);
+ LibraryManagerCollection(const HookLibsCollection& libraries,
+ const boost::shared_ptr<CalloutManager>& manager =
+ HooksManager::getHooksManager().getSharedCalloutManager());
/// @brief Destructor
///
void unloadLibraries();
private:
+ /// Shared Callout manager to be associated with the libraries
+ boost::shared_ptr<CalloutManager> shared_callout_manager_;
/// Vector of library names
std::vector<std::string> library_names_;
/// Unload all libraries and reset the shared manager.
~HooksManagerTest() {
HooksManager::unloadLibraries();
- HooksManager::getSharedCalloutManager().reset();
+ HooksManager::getHooksManager().setSharedCalloutManager();
}
HookLibsCollection library_names;
// Initialize the shared manager.
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Load the pre- and post- callouts.
HooksManager::preCalloutsLibraryHandle().registerCallout("hookpt_two",
data::ConstElementPtr()));
// Initialize the shared manager.
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Load the pre- and post- callouts.
HooksManager::preCalloutsLibraryHandle().registerCallout("hookpt_two",
EXPECT_TRUE(HooksManager::loadLibraries(library_names));
// Initialize the shared manager (after loadLibraries so too late)
- HooksManager::getSharedCalloutManager().reset(new CalloutManager(0));
+ HooksManager::getHooksManager().setSharedCalloutManager(
+ boost::shared_ptr<CalloutManager>(new CalloutManager(0)));
// Load the pre- and post- callouts.
HooksManager::preCalloutsLibraryHandle().registerCallout("hookpt_two",
#include <hooks/callout_handle.h>
#include <hooks/callout_manager.h>
+#include <hooks/hooks_manager.h>
#include <hooks/library_manager.h>
#include <hooks/library_manager_collection.h>
#include <hooks/libinfo.h>
}
};
+} // namespace
+
+namespace isc {
+namespace hooks {
/// @brief Public library manager collection class
///
/// This is an instance of the LibraryManagerCollection class but with the
/// protected methods made public for test purposes.
-class PublicLibraryManagerCollection
- : public isc::hooks::LibraryManagerCollection {
+class PublicLibraryManagerCollection : public LibraryManagerCollection {
public:
/// @brief Constructor
///
/// @param List of libraries that this collection will manage. The order
/// of the libraries is important.
PublicLibraryManagerCollection(const HookLibsCollection& libraries)
- : LibraryManagerCollection(libraries)
- {}
+ : LibraryManagerCollection(libraries) {
+ }
/// Public methods that call protected methods on the superclass.
using LibraryManagerCollection::unloadLibraries;
};
+} // namespace hooks
+} // namespace isc
+namespace {
// This is effectively the same test as for LibraryManager, but using the
// LibraryManagerCollection object.