Browse Source

[2974] CalloutManager now maintains c oncept of "current library"

The responsibility of maintaining this information has been moved
from the LibraryHandle.  As a result, LibraryHandle is now a shell
providing a restricted access to the CalloutManager, ensuring that
callouts can only register/deregister callouts within their own
library.
Stephen Morris 12 years ago
parent
commit
bc6a657a16

+ 17 - 33
src/lib/util/hooks/callout_manager.cc

@@ -28,8 +28,10 @@ namespace util {
 // Register a callout for a particular library.
 // Register a callout for a particular library.
 
 
 void
 void
-CalloutManager::registerCallout(int libindex, const std::string& name,
-                                CalloutPtr callout) {
+CalloutManager::registerCallout(const std::string& name, CalloutPtr callout) {
+    // Sanity check that the current library index is set to a valid value.
+    checkLibraryIndex(current_library_);
+
     // Get the index associated with this hook (validating the name in the
     // Get the index associated with this hook (validating the name in the
     // process).
     // process).
     int hook_index = hooks_->getIndex(name);
     int hook_index = hooks_->getIndex(name);
@@ -39,11 +41,11 @@ CalloutManager::registerCallout(int libindex, const std::string& name,
     // the present index.
     // the present index.
     for (CalloutVector::iterator i = hook_vector_[hook_index].begin();
     for (CalloutVector::iterator i = hook_vector_[hook_index].begin();
          i != hook_vector_[hook_index].end(); ++i) {
          i != hook_vector_[hook_index].end(); ++i) {
-        if (i->first > libindex) {
+        if (i->first > current_library_) {
             // Found an element whose library number is greater than ours,
             // Found an element whose library number is greater than ours,
             // so insert the new element ahead of this one.
             // so insert the new element ahead of this one.
-            hook_vector_[hook_index].insert(i,
-                                            std::make_pair(libindex, callout));
+            hook_vector_[hook_index].insert(i, make_pair(current_library_,
+                                                         callout));
             return;
             return;
         }
         }
     }
     }
@@ -51,7 +53,7 @@ CalloutManager::registerCallout(int libindex, const std::string& name,
     // Reach the end of the vector, so no element in the (possibly empty)
     // Reach the end of the vector, so no element in the (possibly empty)
     // set of callouts with a library index greater that the one related to
     // set of callouts with a library index greater that the one related to
     // this callout, insert at the end.
     // this callout, insert at the end.
-    hook_vector_[hook_index].push_back(std::make_pair(libindex, callout));
+    hook_vector_[hook_index].push_back(make_pair(current_library_, callout));
 }
 }
 
 
 // Check if callouts are present for a given hook index.
 // Check if callouts are present for a given hook index.
@@ -90,16 +92,17 @@ CalloutManager::callCallouts(int hook_index, CalloutHandle& callout_handle) {
 // Deregister a callout registered by a library on a particular hook.
 // Deregister a callout registered by a library on a particular hook.
 
 
 bool
 bool
-CalloutManager::deregisterCallout(int library_index, const std::string& name,
-                                  CalloutPtr callout) {
+CalloutManager::deregisterCallout(const std::string& name, CalloutPtr callout) {
+    // Sanity check that the current library index is set to a valid value.
+    checkLibraryIndex(current_library_);
 
 
     // Get the index associated with this hook (validating the name in the
     // Get the index associated with this hook (validating the name in the
     // process).
     // process).
     int hook_index = hooks_->getIndex(name);
     int hook_index = hooks_->getIndex(name);
 
 
-    /// Construct a CalloutEntry matching the specified library and the callout
+    /// Construct a CalloutEntry matching the current library and the callout
     /// we want to remove.
     /// we want to remove.
-    CalloutEntry target(library_index, callout);
+    CalloutEntry target(current_library_, callout);
 
 
     /// To decide if any entries were removed, we'll record the initial size
     /// To decide if any entries were removed, we'll record the initial size
     /// of the callout vector for the hook, and compare it with the size after
     /// of the callout vector for the hook, and compare it with the size after
@@ -128,16 +131,15 @@ CalloutManager::deregisterCallout(int library_index, const std::string& name,
 // Deregister all callouts on a given hook.
 // Deregister all callouts on a given hook.
 
 
 bool
 bool
-CalloutManager::deregisterAllCallouts(int library_index,
-                                      const std::string& name) {
+CalloutManager::deregisterAllCallouts(const std::string& name) {
 
 
     // Get the index associated with this hook (validating the name in the
     // Get the index associated with this hook (validating the name in the
     // process).
     // process).
     int hook_index = hooks_->getIndex(name);
     int hook_index = hooks_->getIndex(name);
 
 
-    /// Construct a CalloutEntry matching the specified library we want to
-    /// remove (the callout pointer is NULL as we are not checking that).
-    CalloutEntry target(library_index, NULL);
+    /// Construct a CalloutEntry matching the current library (the callout
+    /// pointer is NULL as we are not checking that).
+    CalloutEntry target(current_library_, NULL);
 
 
     /// To decide if any entries were removed, we'll record the initial size
     /// To decide if any entries were removed, we'll record the initial size
     /// of the callout vector for the hook, and compare it with the size after
     /// of the callout vector for the hook, and compare it with the size after
@@ -155,23 +157,5 @@ CalloutManager::deregisterAllCallouts(int library_index,
     return (initial_size != hook_vector_[hook_index].size());
     return (initial_size != hook_vector_[hook_index].size());
 }
 }
 
 
-// CalloutManager methods.
-
-// Return pointer to the current library handle.
-
-boost::shared_ptr<LibraryHandle>
-CalloutManager::createHandle() {
-    // Index is equal to the size of the current collection of handles
-    // (guarantees that every handle has a unique index, and that index
-    // is a pointer to the handle in the collection of handles.)
-    boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(handles_.size(),
-                                                              this));
-
-    // Add to the current collection of handles.
-    handles_.push_back(handle);
-
-    return (handle);
-}
-
 } // namespace util
 } // namespace util
 } // namespace isc
 } // namespace isc

+ 123 - 43
src/lib/util/hooks/callout_manager.h

@@ -27,28 +27,49 @@
 namespace isc {
 namespace isc {
 namespace util {
 namespace util {
 
 
+/// @brief No such library
+///
+/// Thrown if an attempt is made to set the current library index to a value
+/// that is invalid for the number of loaded libraries.
+class NoSuchLibrary : public Exception {
+public:
+    NoSuchLibrary(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
 
 
 /// @brief Callout Manager
 /// @brief Callout Manager
 ///
 ///
 /// This class manages the registration, deregistration and execution of the
 /// This class manages the registration, deregistration and execution of the
 /// library callouts.
 /// library callouts.
 ///
 ///
-/// It is constructed using a @ref isc::util::ServerHooks object that holds the
-/// list of hooks registered for the server, which it uses to create the
-/// hook vector.  This is a vector represting the callouts for each hook. Each
-/// element is itself a vector of callouts registered by the loaded libraries.
+/// In operation, the class need to know two items of data:
 ///
 ///
-/// The class also holds the collection of library handles, used to allow the
-/// libraries to manipulate their callout list.
+/// - The list of server hooks.  This is used in two ways.  Firstly, when a
+///   callout registers or deregisters a hook, it does so by name: the
+///   @ref isc::util::ServerHooks object supplies the names of registered
+///   hooks.  Secondly, when the callouts associated with a hook are called by
+///   the server, it supplies the index of the relevant hook: this is validated
+///   hook vector (which holds the callouts associated with each hook).
+///
+/// - The number of loaded libraries.  Each callout registered by a user
+///   library is associated with that library, the callout manager storing both
+///   a pointer to the callout and the index of the library in the list of
+///   loaded libraries.  Callouts are allowed to dynamically register and
+///   deregister callouts (including themselves), but only callouts in the
+///   same library.  When calling a callout, the callout manager maintains
+///   the idea of a "current library index": if the callout calls one of the
+///   callout registration functions in the callout manager (it can do this
+///   indirectly via the @ref LibraryHandle object), the registration functions
+///   use the "current library index" in their processing.
+///
+/// These two items of data are supplied when the class is constructed.
 
 
 class CalloutManager {
 class CalloutManager {
 private:
 private:
 
 
     // Private typedefs
     // Private typedefs
 
 
-    /// Vector of library handles.
-    typedef std::vector<boost::shared_ptr<LibraryHandle> > HandleVector;
-
     /// Element in the vector of callouts.  The elements in the pair are the
     /// Element in the vector of callouts.  The elements in the pair are the
     /// library index and the pointer to the callout.
     /// library index and the pointer to the callout.
     typedef std::pair<int, CalloutPtr> CalloutEntry;
     typedef std::pair<int, CalloutPtr> CalloutEntry;
@@ -63,33 +84,36 @@ public:
     /// Initializes member variables, in particular sizing the hook vector
     /// Initializes member variables, in particular sizing the hook vector
     /// (the vector of callouts) to the appropriate size.
     /// (the vector of callouts) to the appropriate size.
     ///
     ///
-    /// @param hook Collection of known hook names.
-    CalloutManager(const boost::shared_ptr<ServerHooks>& hooks) :
-        hooks_(hooks), handles_(), hook_vector_(hooks->getCount())
+    /// @param hooks Collection of known hook names.
+    /// @param num_libraries Number of loaded libraries.
+    CalloutManager(const boost::shared_ptr<ServerHooks>& hooks,
+                   int num_libraries)
+        : current_library_(-1), hooks_(hooks), hook_vector_(hooks->getCount()),
+          library_handle_(this), num_libraries_(num_libraries)
     {}
     {}
 
 
     /// @brief Register a callout on a hook
     /// @brief Register a callout on a hook
     ///
     ///
-    /// Registers a callout function for a particular library with a given hook.
-    /// The callout is added to the end of the callouts for this library that
-    /// are associated with that hook.
+    /// Registers a callout function for the current library with a given hook
+    /// (the index of the "current library" being given by the current_library_
+    /// member).  The callout is added to the end of the callouts for this
+    /// library that are associated with that hook.
     ///
     ///
-    /// @param libindex Index of the library registering the callout
     /// @param name Name of the hook to which the callout is added.
     /// @param name Name of the hook to which the callout is added.
     /// @param callout Pointer to the callout function to be registered.
     /// @param callout Pointer to the callout function to be registered.
     ///
     ///
     /// @throw NoSuchHook The hook name is unrecognised.
     /// @throw NoSuchHook The hook name is unrecognised.
     /// @throw Unexpected The hook name is valid but an internal data structure
     /// @throw Unexpected The hook name is valid but an internal data structure
     ///        is of the wrong size.
     ///        is of the wrong size.
-    void registerCallout(int libindex, const std::string& name,
-                         CalloutPtr callout);
+    void registerCallout(const std::string& name, CalloutPtr callout);
 
 
     /// @brief De-Register a callout on a hook
     /// @brief De-Register a callout on a hook
     ///
     ///
-    /// Searches through the functions registered by the specified library with
-    /// the named hook and removes all entries matching the callout.
+    /// Searches through the functions registered by the the current library
+    /// (the index of the "current library" being given by the current_library_
+    /// member) with the named hook and removes all entries matching the
+    /// callout.
     ///
     ///
-    /// @param libindex Index of the library deregistering the callout
     /// @param name Name of the hook from which the callout is removed.
     /// @param name Name of the hook from which the callout is removed.
     /// @param callout Pointer to the callout function to be removed.
     /// @param callout Pointer to the callout function to be removed.
     ///
     ///
@@ -98,54 +122,83 @@ public:
     /// @throw NoSuchHook The hook name is unrecognised.
     /// @throw NoSuchHook The hook name is unrecognised.
     /// @throw Unexpected The hook name is valid but an internal data structure
     /// @throw Unexpected The hook name is valid but an internal data structure
     ///        is of the wrong size.
     ///        is of the wrong size.
-    bool deregisterCallout(int libindex, const std::string& name,
-                           CalloutPtr callout);
+    bool deregisterCallout(const std::string& name, CalloutPtr callout);
 
 
     /// @brief Removes all callouts on a hook
     /// @brief Removes all callouts on a hook
     ///
     ///
     /// Removes all callouts associated with a given hook that were registered
     /// Removes all callouts associated with a given hook that were registered
-    /// by the specified library.
+    /// by the current library (the index of the "current library" being given
+    /// by the current_library_ member).
     ///
     ///
-    /// @param libindex Index of the library deregistering the callouts
     /// @param name Name of the hook from which the callouts are removed.
     /// @param name Name of the hook from which the callouts are removed.
     ///
     ///
     /// @return true if one or more callouts were deregistered.
     /// @return true if one or more callouts were deregistered.
     ///
     ///
     /// @throw NoSuchHook Thrown if the hook name is unrecognised.
     /// @throw NoSuchHook Thrown if the hook name is unrecognised.
-    bool deregisterAllCallouts(int libindex, const std::string& name);
+    bool deregisterAllCallouts(const std::string& name);
 
 
     /// @brief Checks if callouts are present on a hook
     /// @brief Checks if callouts are present on a hook
     ///
     ///
     /// Checks all loaded libraries and returns true if at least one callout
     /// Checks all loaded libraries and returns true if at least one callout
     /// has been registered by any of them for the given hook.
     /// has been registered by any of them for the given hook.
     ///
     ///
-    /// @param index Hook index for which callouts are checked.
+    /// @param hook_index Hook index for which callouts are checked.
     ///
     ///
     /// @return true if callouts are present, false if not.
     /// @return true if callouts are present, false if not.
     ///
     ///
     /// @throw NoSuchHook Given index does not correspond to a valid hook.
     /// @throw NoSuchHook Given index does not correspond to a valid hook.
-    bool calloutsPresent(int index) const;
+    bool calloutsPresent(int hook_index) const;
 
 
     /// @brief Calls the callouts for a given hook
     /// @brief Calls the callouts for a given hook
     ///
     ///
     /// Iterates through the libray handles and calls the callouts associated
     /// Iterates through the libray handles and calls the callouts associated
     /// with the given hook index.
     /// with the given hook index.
     ///
     ///
-    /// @param index Index of the hook to call.
+    /// @param hook_index Index of the hook to call.
     /// @param callout_handle Reference to the CalloutHandle object for the
     /// @param callout_handle Reference to the CalloutHandle object for the
     ///        current object being processed.
     ///        current object being processed.
     ///
     ///
     /// @return Status return.
     /// @return Status return.
-    int callCallouts(int index, CalloutHandle& callout_handle);
+    int callCallouts(int hook_index, CalloutHandle& callout_handle);
 
 
+    /// @brief Get current library index
+    ///
+    /// Returns the index of the "current" library.  This the index associated
+    /// with the currently executing callout when callCallouts is executing.
+    /// When callCallouts() is not executing (as is the case when the load()
+    /// function in a user-library is called during the library load process),
+    /// the index is the value set by setLibraryIndex().
+    ///
+    /// @return Current library index.
+    int getLibraryIndex() const {
+        return (current_library_);
+    }
 
 
-    /// @brief Create library handle
+    /// @brief Set current library index
+    ///
+    /// Sets the current library index.  This must be in the range 0 to
+    /// (numlib - 1), where "numlib" is the number of libraries loaded and is
+    /// passed to this object at construction time.
     ///
     ///
-    /// Creates a library handle.  The handle is used when loading a library in
-    /// that the callouts are associated with the given library and when calling
-    /// a callout: the handle for the library can be obtained to allow dynamic
-    /// registration and de-registration.
-    boost::shared_ptr<LibraryHandle> createHandle();
+    /// @param library_index New library index.
+    ///
+    /// @throw NoSuchLibrary if the index is not valid.
+    void setLibraryIndex(int library_index) {
+        checkLibraryIndex(library_index);
+        current_library_ = library_index;
+    }
+
+    /// @brief Return library handle
+    ///
+    /// The library handle is available to the user callout via the callout
+    /// handle object.  It provides a cut-down view of the CalloutManager,
+    /// allowing the callout to register and deregister callouts in the
+    /// library of which it is part.
+    ///
+    /// @return reference to callout handle for this manager
+    LibraryHandle& getLibraryHandle() {
+        return (library_handle_);
+    }
 
 
 private:
 private:
     /// @brief Check hook index
     /// @brief Check hook index
@@ -154,7 +207,7 @@ private:
     ///
     ///
     /// @param index Hook index to test
     /// @param index Hook index to test
     ///
     ///
-    /// @throw NoSuchHook
+    /// @throw NoSuchHook Hooks does not exist.
     void checkHookIndex(int hook_index) const {
     void checkHookIndex(int hook_index) const {
         if ((hook_index < 0) || (hook_index >= hook_vector_.size())) {
         if ((hook_index < 0) || (hook_index >= hook_vector_.size())) {
             isc_throw(NoSuchHook, "hook index " << hook_index <<
             isc_throw(NoSuchHook, "hook index " << hook_index <<
@@ -162,10 +215,27 @@ private:
         }
         }
     }
     }
 
 
+    /// @brief Check library index
+    ///
+    /// Ensures that the current library index is valid.  This is called by
+    /// the hook registration functions.
+    ///
+    /// @param library_index Value to check for validity as a library index.
+    ///
+    /// @throw NoSuchLibrary Library index is not 
+    void checkLibraryIndex(int library_index) const {
+        if ((library_index < 0) || (library_index >= num_libraries_)) {
+            isc_throw(NoSuchLibrary, "library index " << library_index <<
+                      " is not valid for the number of loaded libraries (" <<
+                      num_libraries_ << ")");
+        }
+    }
+
     /// @brief Compare two callout entries for library equality
     /// @brief Compare two callout entries for library equality
     ///
     ///
-    /// This is used in callout removal code.  It just checks whether two
-    /// entries have the same library element.
+    /// This is used in callout removal code when all callouts on a hook for a
+    /// given library are being removed.  It checks whether two callout entries
+    /// have the same library index.
     ///
     ///
     /// @param ent1 First callout entry to check
     /// @param ent1 First callout entry to check
     /// @param ent2 Second callout entry to check
     /// @param ent2 Second callout entry to check
@@ -179,16 +249,26 @@ private:
         }
         }
     };
     };
 
 
+    /// Current library index.  When a call is made to any of the callout
+    /// registration methods, this variable indicates the index of the user
+    /// library that is calling the methods.
+    int current_library_;
+
     /// List of server hooks.  This is used 
     /// List of server hooks.  This is used 
     boost::shared_ptr<ServerHooks>  hooks_;
     boost::shared_ptr<ServerHooks>  hooks_;
 
 
-    /// Vector of pointers to library handles.
-    HandleVector handles_;
-
     /// Vector of callout vectors.  There is one entry in this outer vector for
     /// Vector of callout vectors.  There is one entry in this outer vector for
-    /// each hook.
+    /// each hook. Each element is itself a vector, with one entry for each
+    /// callout registered for that hook.
     std::vector<CalloutVector>  hook_vector_;
     std::vector<CalloutVector>  hook_vector_;
 
 
+    /// LibraryHandle object user by the callout to access the callout
+    /// registration methods on this CalloutManager object.
+    LibraryHandle library_handle_;
+
+    /// Number of libraries.  libindex_ can vary between 0 and numlib_ - 1.
+    int num_libraries_;
+
 };
 };
 
 
 } // namespace util
 } // namespace util

+ 3 - 3
src/lib/util/hooks/library_handle.cc

@@ -22,17 +22,17 @@ namespace util {
 
 
 void
 void
 LibraryHandle::registerCallout(const std::string& name, CalloutPtr callout) {
 LibraryHandle::registerCallout(const std::string& name, CalloutPtr callout) {
-    callout_manager_->registerCallout(library_index_, name, callout);
+    callout_manager_->registerCallout(name, callout);
 }
 }
 
 
 bool
 bool
 LibraryHandle::deregisterCallout(const std::string& name, CalloutPtr callout) {
 LibraryHandle::deregisterCallout(const std::string& name, CalloutPtr callout) {
-    return (callout_manager_->deregisterCallout(library_index_, name, callout));
+    return (callout_manager_->deregisterCallout(name, callout));
 }
 }
 
 
 bool
 bool
 LibraryHandle::deregisterAllCallouts(const std::string& name) {
 LibraryHandle::deregisterAllCallouts(const std::string& name) {
-    return (callout_manager_->deregisterAllCallouts(library_index_, name));
+    return (callout_manager_->deregisterAllCallouts(name));
 }
 }
 
 
 } // namespace util
 } // namespace util

+ 1 - 18
src/lib/util/hooks/library_handle.h

@@ -45,14 +45,10 @@ public:
 
 
     /// @brief Constructor
     /// @brief Constructor
     ///
     ///
-    /// @param hooks Library index.  A number (starting at 0) that represents
-    ///        the index of the library in the list of libraries loaded by the
-    ///        server.
     /// @param collection Back pointer to the containing CalloutManager.
     /// @param collection Back pointer to the containing CalloutManager.
     ///        This pointer is used to access appropriate methods in that
     ///        This pointer is used to access appropriate methods in that
     ///        object.
     ///        object.
-    LibraryHandle(int library_index, CalloutManager* collection)
-        : library_index_(library_index), callout_manager_(collection)
+    LibraryHandle(CalloutManager* collection) : callout_manager_(collection)
     {}
     {}
 
 
     /// @brief Register a callout on a hook
     /// @brief Register a callout on a hook
@@ -98,20 +94,7 @@ public:
     /// @throw NoSuchHook Thrown if the hook name is unrecognised.
     /// @throw NoSuchHook Thrown if the hook name is unrecognised.
     bool deregisterAllCallouts(const std::string& name);
     bool deregisterAllCallouts(const std::string& name);
 
 
-    /// @brief Return handle index
-    ///
-    /// For test purposes only, this returns the index allocated to this
-    /// LibraryHandle.
-    ///
-    /// @return Handle index
-    int getIndex() const {
-        return (library_index_);
-    }
-
 private:
 private:
-    /// Index of this handle in the library handle list
-    int library_index_;
-
     /// Back pointer to the collection object for the library
     /// Back pointer to the collection object for the library
     CalloutManager* callout_manager_;
     CalloutManager* callout_manager_;
 };
 };

+ 0 - 1
src/lib/util/tests/Makefile.am

@@ -33,7 +33,6 @@ run_unittests_SOURCES += filename_unittest.cc
 run_unittests_SOURCES += hex_unittest.cc
 run_unittests_SOURCES += hex_unittest.cc
 # run_unittests_SOURCES += handles_unittest.cc
 # run_unittests_SOURCES += handles_unittest.cc
 run_unittests_SOURCES += io_utilities_unittest.cc
 run_unittests_SOURCES += io_utilities_unittest.cc
-# run_unittests_SOURCES += library_handle_unittest.cc
 run_unittests_SOURCES += lru_list_unittest.cc
 run_unittests_SOURCES += lru_list_unittest.cc
 run_unittests_SOURCES += memory_segment_local_unittest.cc
 run_unittests_SOURCES += memory_segment_local_unittest.cc
 if USE_SHARED_MEMORY
 if USE_SHARED_MEMORY

+ 231 - 104
src/lib/util/tests/callout_manager_unittest.cc

@@ -24,6 +24,14 @@
 #include <string>
 #include <string>
 #include <vector>
 #include <vector>
 
 
+/// @file
+/// @brief CalloutManager and LibraryHandle tests
+///
+/// These set of tests check the CalloutManager and LibraryHandle.  They are
+/// together in the same file because the LibraryHandle is little more than a
+/// restricted interface to the CalloutManager, and a lot of the support
+/// structure for the tests is common.
+
 using namespace isc;
 using namespace isc;
 using namespace isc::util;
 using namespace isc::util;
 using namespace std;
 using namespace std;
@@ -43,14 +51,9 @@ public:
         gamma_index_ = hooks_->registerHook("gamma");
         gamma_index_ = hooks_->registerHook("gamma");
         delta_index_ = hooks_->registerHook("delta");
         delta_index_ = hooks_->registerHook("delta");
 
 
-        // Set up the callout manager with these hooks
-        callout_manager_.reset(new CalloutManager(hooks_));
-
-        // Set up four library handles.
-        library_handle_.push_back(callout_manager_->createHandle());
-        library_handle_.push_back(callout_manager_->createHandle());
-        library_handle_.push_back(callout_manager_->createHandle());
-        library_handle_.push_back(callout_manager_->createHandle());
+        // Set up the callout manager with these hooks.  Assume a maximum of
+        // four libraries.
+        callout_manager_.reset(new CalloutManager(hooks_, 4));
 
 
         // Set up the callout handle.
         // Set up the callout handle.
         callout_handle_.reset(new CalloutHandle(callout_manager_));
         callout_handle_.reset(new CalloutHandle(callout_manager_));
@@ -83,12 +86,10 @@ private:
     /// Server hooks
     /// Server hooks
     boost::shared_ptr<ServerHooks> hooks_;
     boost::shared_ptr<ServerHooks> hooks_;
 
 
-    /// Set up three library handles.
-    std::vector<boost::shared_ptr<LibraryHandle> > library_handle_;
-
     /// Callout handle used in calls
     /// Callout handle used in calls
     boost::shared_ptr<CalloutHandle> callout_handle_;
     boost::shared_ptr<CalloutHandle> callout_handle_;
 
 
+
 };
 };
 
 
 // Definition of the static variable.
 // Definition of the static variable.
@@ -166,6 +167,29 @@ int manager_four_error(CalloutHandle& handle) {
 
 
 };  // extern "C"
 };  // extern "C"
 
 
+// Check that we can only set the current library index to the correct values.
+
+TEST_F(CalloutManagerTest, CheckLibraryIndex) {
+    // Check valid indexes
+    for (int i = 0; i < 4; ++i) {
+        EXPECT_NO_THROW(getCalloutManager()->setLibraryIndex(i));
+    }
+
+    // Check invalid ones
+    EXPECT_THROW(getCalloutManager()->setLibraryIndex(-1), NoSuchLibrary);
+    EXPECT_THROW(getCalloutManager()->setLibraryIndex(5), NoSuchLibrary);
+}
+
+// Check that we can only register callouts on valid hook names.
+
+TEST_F(CalloutManagerTest, ValidHookNames) {
+    getCalloutManager()->setLibraryIndex(0);
+    EXPECT_NO_THROW(getCalloutManager()->registerCallout("alpha", manager_one));
+    EXPECT_THROW(getCalloutManager()->registerCallout("unknown", manager_one),
+                                                      NoSuchHook);
+}
+
+
 // Check we can register callouts appropriately.
 // Check we can register callouts appropriately.
 
 
 TEST_F(CalloutManagerTest, RegisterCallout) {
 TEST_F(CalloutManagerTest, RegisterCallout) {
@@ -174,9 +198,11 @@ TEST_F(CalloutManagerTest, RegisterCallout) {
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
 
 
     // Set up so that hooks "alpha" and "beta" have callouts attached from a
     // Set up so that hooks "alpha" and "beta" have callouts attached from a
-    // single library.
-    getCalloutManager()->registerCallout(0, "alpha", manager_one);
-    getCalloutManager()->registerCallout(1, "beta", manager_two);
+    // different libraries.
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("beta", manager_two);
 
 
     // Check all is as expected.
     // Check all is as expected.
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
@@ -200,9 +226,11 @@ TEST_F(CalloutManagerTest, RegisterCallout) {
     EXPECT_EQ(2, callout_value_);
     EXPECT_EQ(2, callout_value_);
 
 
     // Register some more callouts from different libraries on hook "alpha".
     // Register some more callouts from different libraries on hook "alpha".
-    getCalloutManager()->registerCallout(2, "alpha", manager_three);
-    getCalloutManager()->registerCallout(2, "alpha", manager_four);
-    getCalloutManager()->registerCallout(3, "alpha", manager_five);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("alpha", manager_four);
+    getCalloutManager()->setLibraryIndex(3);
+    getCalloutManager()->registerCallout("alpha", manager_five);
 
 
     // Check it is as expected.
     // Check it is as expected.
     callout_value_ = 0;
     callout_value_ = 0;
@@ -216,9 +244,10 @@ TEST_F(CalloutManagerTest, RegisterCallout) {
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
     EXPECT_EQ(2, callout_value_);
     EXPECT_EQ(2, callout_value_);
 
 
-    // Add another callout to hook "alpha" from library iindex 2 - this should
+    // Add another callout to hook "alpha" from library index 2 - this should
     // appear at the end of the callout list for that library.
     // appear at the end of the callout list for that library.
-    getCalloutManager()->registerCallout(2, "alpha", manager_six);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", manager_six);
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -227,14 +256,13 @@ TEST_F(CalloutManagerTest, RegisterCallout) {
 
 
     // Add a callout from library index 1 - this should appear between the
     // Add a callout from library index 1 - this should appear between the
     // callouts from library index 0 and linrary index 2.
     // callouts from library index 0 and linrary index 2.
-    getCalloutManager()->registerCallout(1, "alpha", manager_seven);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", manager_seven);
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
     EXPECT_EQ(173465, callout_value_);
     EXPECT_EQ(173465, callout_value_);
-
-
 }
 }
 
 
 // Check the "calloutsPresent()" method.
 // Check the "calloutsPresent()" method.
@@ -252,13 +280,16 @@ TEST_F(CalloutManagerTest, CalloutsPresent) {
     // that some callouts are).  Chose the libraries for which the callouts
     // that some callouts are).  Chose the libraries for which the callouts
     // are registered randomly.
     // are registered randomly.
 
 
-    getCalloutManager()->registerCallout(0, "alpha", manager_one);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", manager_one);
 
 
-    getCalloutManager()->registerCallout(1, "alpha", manager_two);
-    getCalloutManager()->registerCallout(1, "beta", manager_two);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->registerCallout("beta", manager_two);
 
 
-    getCalloutManager()->registerCallout(3, "alpha", manager_three);
-    getCalloutManager()->registerCallout(3, "delta", manager_four);
+    getCalloutManager()->setLibraryIndex(3);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("delta", manager_four);
 
 
     // Check all is as expected.
     // Check all is as expected.
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
@@ -303,10 +334,14 @@ TEST_F(CalloutManagerTest, CallCalloutsSuccess) {
 
 
     // Each library contributes one callout on hook "alpha".
     // Each library contributes one callout on hook "alpha".
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "alpha", manager_one);
-    getCalloutManager()->registerCallout(1, "alpha", manager_two);
-    getCalloutManager()->registerCallout(2, "alpha", manager_three);
-    getCalloutManager()->registerCallout(3, "alpha", manager_four);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->setLibraryIndex(3);
+    getCalloutManager()->registerCallout("alpha", manager_four);
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
@@ -314,10 +349,13 @@ TEST_F(CalloutManagerTest, CallCalloutsSuccess) {
 
 
     // Do a random selection of callouts on hook "beta".
     // Do a random selection of callouts on hook "beta".
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "beta", manager_one);
-    getCalloutManager()->registerCallout(0, "beta", manager_three);
-    getCalloutManager()->registerCallout(1, "beta", manager_two);
-    getCalloutManager()->registerCallout(3, "beta", manager_four);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("beta", manager_one);
+    getCalloutManager()->registerCallout("beta", manager_three);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("beta", manager_two);
+    getCalloutManager()->setLibraryIndex(3);
+    getCalloutManager()->registerCallout("beta", manager_four);
     status = getCalloutManager()->callCallouts(beta_index_,
     status = getCalloutManager()->callCallouts(beta_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
@@ -349,10 +387,14 @@ TEST_F(CalloutManagerTest, CallCalloutsError) {
     // Each library contributing one callout on hook "alpha". The first callout
     // Each library contributing one callout on hook "alpha". The first callout
     // returns an error (after adding its value to the result).
     // returns an error (after adding its value to the result).
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "alpha", manager_one_error);
-    getCalloutManager()->registerCallout(1, "alpha", manager_two);
-    getCalloutManager()->registerCallout(2, "alpha", manager_three);
-    getCalloutManager()->registerCallout(3, "alpha", manager_four);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", manager_one_error);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->setLibraryIndex(3);
+    getCalloutManager()->registerCallout("alpha", manager_four);
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(1, status);
     EXPECT_EQ(1, status);
@@ -361,14 +403,17 @@ TEST_F(CalloutManagerTest, CallCalloutsError) {
     // Each library contributing multiple callouts on hook "beta". The last
     // Each library contributing multiple callouts on hook "beta". The last
     // callout on the first library returns an error.
     // callout on the first library returns an error.
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "beta", manager_one);
-    getCalloutManager()->registerCallout(0, "beta", manager_one_error);
-    getCalloutManager()->registerCallout(1, "beta", manager_two);
-    getCalloutManager()->registerCallout(1, "beta", manager_two);
-    getCalloutManager()->registerCallout(1, "beta", manager_three);
-    getCalloutManager()->registerCallout(1, "beta", manager_three);
-    getCalloutManager()->registerCallout(3, "beta", manager_four);
-    getCalloutManager()->registerCallout(3, "beta", manager_four);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("beta", manager_one);
+    getCalloutManager()->registerCallout("beta", manager_one_error);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("beta", manager_two);
+    getCalloutManager()->registerCallout("beta", manager_two);
+    getCalloutManager()->registerCallout("beta", manager_three);
+    getCalloutManager()->registerCallout("beta", manager_three);
+    getCalloutManager()->setLibraryIndex(3);
+    getCalloutManager()->registerCallout("beta", manager_four);
+    getCalloutManager()->registerCallout("beta", manager_four);
     status = getCalloutManager()->callCallouts(beta_index_,
     status = getCalloutManager()->callCallouts(beta_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(1, status);
     EXPECT_EQ(1, status);
@@ -376,12 +421,15 @@ TEST_F(CalloutManagerTest, CallCalloutsError) {
 
 
     // A callout in a random position in the callout list returns an error.
     // A callout in a random position in the callout list returns an error.
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "gamma", manager_one);
-    getCalloutManager()->registerCallout(0, "gamma", manager_one);
-    getCalloutManager()->registerCallout(1, "gamma", manager_two);
-    getCalloutManager()->registerCallout(1, "gamma", manager_two);
-    getCalloutManager()->registerCallout(3, "gamma", manager_four_error);
-    getCalloutManager()->registerCallout(3, "gamma", manager_four);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("gamma", manager_one);
+    getCalloutManager()->registerCallout("gamma", manager_one);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("gamma", manager_two);
+    getCalloutManager()->registerCallout("gamma", manager_two);
+    getCalloutManager()->setLibraryIndex(3);
+    getCalloutManager()->registerCallout("gamma", manager_four_error);
+    getCalloutManager()->registerCallout("gamma", manager_four);
     status = getCalloutManager()->callCallouts(gamma_index_,
     status = getCalloutManager()->callCallouts(gamma_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(1, status);
     EXPECT_EQ(1, status);
@@ -389,14 +437,18 @@ TEST_F(CalloutManagerTest, CallCalloutsError) {
 
 
     // The last callout on a hook returns an error.
     // The last callout on a hook returns an error.
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "delta", manager_one);
-    getCalloutManager()->registerCallout(0, "delta", manager_one);
-    getCalloutManager()->registerCallout(1, "delta", manager_two);
-    getCalloutManager()->registerCallout(1, "delta", manager_two);
-    getCalloutManager()->registerCallout(2, "delta", manager_three);
-    getCalloutManager()->registerCallout(2, "delta", manager_three);
-    getCalloutManager()->registerCallout(3, "delta", manager_four);
-    getCalloutManager()->registerCallout(3, "delta", manager_four_error);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("delta", manager_one);
+    getCalloutManager()->registerCallout("delta", manager_one);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("delta", manager_two);
+    getCalloutManager()->registerCallout("delta", manager_two);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("delta", manager_three);
+    getCalloutManager()->registerCallout("delta", manager_three);
+    getCalloutManager()->setLibraryIndex(3);
+    getCalloutManager()->registerCallout("delta", manager_four);
+    getCalloutManager()->registerCallout("delta", manager_four_error);
     status = getCalloutManager()->callCallouts(delta_index_,
     status = getCalloutManager()->callCallouts(delta_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(1, status);
     EXPECT_EQ(1, status);
@@ -416,7 +468,8 @@ TEST_F(CalloutManagerTest, DeregisterSingleCallout) {
 
 
     // Add a callout to hook "alpha" and check it is added correctly.
     // Add a callout to hook "alpha" and check it is added correctly.
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "alpha", manager_two);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", manager_two);
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
@@ -424,8 +477,7 @@ TEST_F(CalloutManagerTest, DeregisterSingleCallout) {
 
 
     // Remove it and check that the no callouts are present.
     // Remove it and check that the no callouts are present.
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha",
-                                                       manager_two));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
 }
 }
 
 
@@ -443,18 +495,18 @@ TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) {
 
 
     // Add multiple callouts to hook "alpha".
     // Add multiple callouts to hook "alpha".
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "alpha", manager_one);
-    getCalloutManager()->registerCallout(0, "alpha", manager_two);
-    getCalloutManager()->registerCallout(0, "alpha", manager_three);
-    getCalloutManager()->registerCallout(0, "alpha", manager_four);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("alpha", manager_four);
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
     EXPECT_EQ(1234, callout_value_);
     EXPECT_EQ(1234, callout_value_);
 
 
     // Remove the manager_two callout.
     // Remove the manager_two callout.
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha",
-                                                       manager_two));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -462,8 +514,7 @@ TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) {
     EXPECT_EQ(134, callout_value_);
     EXPECT_EQ(134, callout_value_);
 
 
     // Try removing it again.
     // Try removing it again.
-    EXPECT_FALSE(getCalloutManager()->deregisterCallout(0, "alpha",
-                                                        manager_two));
+    EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", manager_two));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -485,22 +536,22 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) {
 
 
     // Each library contributes one callout on hook "alpha".
     // Each library contributes one callout on hook "alpha".
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "alpha", manager_one);
-    getCalloutManager()->registerCallout(0, "alpha", manager_two);
-    getCalloutManager()->registerCallout(0, "alpha", manager_one);
-    getCalloutManager()->registerCallout(0, "alpha", manager_two);
-    getCalloutManager()->registerCallout(0, "alpha", manager_three);
-    getCalloutManager()->registerCallout(0, "alpha", manager_four);
-    getCalloutManager()->registerCallout(0, "alpha", manager_three);
-    getCalloutManager()->registerCallout(0, "alpha", manager_four);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("alpha", manager_four);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("alpha", manager_four);
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
     EXPECT_EQ(12123434, callout_value_);
     EXPECT_EQ(12123434, callout_value_);
 
 
     // Remove the manager_two callouts.
     // Remove the manager_two callouts.
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha",
-                                                       manager_two));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -509,8 +560,7 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) {
 
 
     // Try removing multiple callouts that includes one at the end of the
     // Try removing multiple callouts that includes one at the end of the
     // list of callouts.
     // list of callouts.
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha",
-                                                       manager_four));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_four));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -518,8 +568,7 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) {
     EXPECT_EQ(1133, callout_value_);
     EXPECT_EQ(1133, callout_value_);
 
 
     // ... and from the start.
     // ... and from the start.
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha",
-                                                       manager_one));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_one));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -527,8 +576,7 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) {
     EXPECT_EQ(33, callout_value_);
     EXPECT_EQ(33, callout_value_);
 
 
     // ... and the remaining callouts.
     // ... and the remaining callouts.
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha",
-                                                       manager_three));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_three));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -551,12 +599,15 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) {
 
 
     // Each library contributes two callouts to hook "alpha".
     // Each library contributes two callouts to hook "alpha".
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "alpha", manager_one);
-    getCalloutManager()->registerCallout(0, "alpha", manager_two);
-    getCalloutManager()->registerCallout(1, "alpha", manager_three);
-    getCalloutManager()->registerCallout(1, "alpha", manager_four);
-    getCalloutManager()->registerCallout(2, "alpha", manager_five);
-    getCalloutManager()->registerCallout(2, "alpha", manager_two);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("alpha", manager_four);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", manager_five);
+    getCalloutManager()->registerCallout("alpha", manager_two);
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
@@ -564,8 +615,8 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) {
 
 
     // Remove the manager_two callout from library 0.  It should not affect
     // Remove the manager_two callout from library 0.  It should not affect
     // the second manager_two callout registered by library 2.
     // the second manager_two callout registered by library 2.
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha",
-                                                       manager_two));
+    getCalloutManager()->setLibraryIndex(0);
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -583,19 +634,23 @@ TEST_F(CalloutManagerTest, DeregisterAllCallouts) {
 
 
     // Each library contributes two callouts to hook "alpha".
     // Each library contributes two callouts to hook "alpha".
     callout_value_ = 0;
     callout_value_ = 0;
-    getCalloutManager()->registerCallout(0, "alpha", manager_one);
-    getCalloutManager()->registerCallout(0, "alpha", manager_two);
-    getCalloutManager()->registerCallout(1, "alpha", manager_three);
-    getCalloutManager()->registerCallout(1, "alpha", manager_four);
-    getCalloutManager()->registerCallout(2, "alpha", manager_five);
-    getCalloutManager()->registerCallout(2, "alpha", manager_six);
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("alpha", manager_four);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", manager_five);
+    getCalloutManager()->registerCallout("alpha", manager_six);
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
     EXPECT_EQ(0, status);
     EXPECT_EQ(0, status);
     EXPECT_EQ(123456, callout_value_);
     EXPECT_EQ(123456, callout_value_);
 
 
     // Remove all callouts from library index 1.
     // Remove all callouts from library index 1.
-    EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts(1, "alpha"));
+    getCalloutManager()->setLibraryIndex(1);
+    EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -603,7 +658,8 @@ TEST_F(CalloutManagerTest, DeregisterAllCallouts) {
     EXPECT_EQ(1256, callout_value_);
     EXPECT_EQ(1256, callout_value_);
 
 
     // Remove all callouts from library index 2.
     // Remove all callouts from library index 2.
-    EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts(2, "alpha"));
+    getCalloutManager()->setLibraryIndex(2);
+    EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
     callout_value_ = 0;
     callout_value_ = 0;
     status = getCalloutManager()->callCallouts(alpha_index_,
     status = getCalloutManager()->callCallouts(alpha_index_,
                                                getCalloutHandle());
                                                getCalloutHandle());
@@ -611,5 +667,76 @@ TEST_F(CalloutManagerTest, DeregisterAllCallouts) {
     EXPECT_EQ(12, callout_value_);
     EXPECT_EQ(12, callout_value_);
 }
 }
 
 
+// Library handle tests.  As by inspection the LibraryHandle can be seen to be
+// little more than shell around CalloutManager, only a basic set of tests
+// is done concerning registration and deregistration of functions.
+//
+// More extensive tests (i.e. checking that when a callout is called it can
+// only register and deregister callouts within its library) require that
+// the CalloutHandle object pass the appropriate LibraryHandle to the
+// callout.  These tests are done in the CalloutHandle tests.
+
+TEST_F(CalloutManagerTest, LibraryHandleRegistration) {
+    // Ensure that no callouts are attached to any of the hooks.
+    EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+
+    // Set up so that hooks "alpha" and "beta" have callouts attached from a
+    // different libraries.
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->getLibraryHandle().registerCallout("alpha",
+                                                            manager_one);
+    getCalloutManager()->getLibraryHandle().registerCallout("alpha",
+                                                            manager_two);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->getLibraryHandle().registerCallout("alpha",
+                                                            manager_three);
+    getCalloutManager()->getLibraryHandle().registerCallout("alpha",
+                                                            manager_four);
+
+    // Check all is as expected.
+    EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
+    EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+    EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+    EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
+                 
+    int status = 0;
+
+    // Check that calling the callouts returns as expected. (This is also a
+    // test of the callCallouts method.)
+    callout_value_ = 0;
+    status = getCalloutManager()->callCallouts(alpha_index_,
+                                               getCalloutHandle());
+    EXPECT_EQ(0, status);
+    EXPECT_EQ(1234, callout_value_);
+
+    // Deregister a callout on library index 0 (after we check we can't
+    // deregister it through library index 1).
+    getCalloutManager()->setLibraryIndex(1);
+    EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+    callout_value_ = 0;
+    status = getCalloutManager()->callCallouts(alpha_index_,
+                                               getCalloutHandle());
+    EXPECT_EQ(0, status);
+    EXPECT_EQ(1234, callout_value_);
+
+    getCalloutManager()->setLibraryIndex(0);
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+    callout_value_ = 0;
+    status = getCalloutManager()->callCallouts(alpha_index_,
+                                               getCalloutHandle());
+    EXPECT_EQ(0, status);
+    EXPECT_EQ(134, callout_value_);
+
+    // Deregister all callouts on library index 1.
+    getCalloutManager()->setLibraryIndex(1);
+    EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
+    callout_value_ = 0;
+    status = getCalloutManager()->callCallouts(alpha_index_,
+                                               getCalloutHandle());
+    EXPECT_EQ(0, status);
+    EXPECT_EQ(1, callout_value_);
+}
+
+
 
 
 } // Anonymous namespace
 } // Anonymous namespace

+ 0 - 303
src/lib/util/tests/library_handle_unittest.cc

@@ -1,303 +0,0 @@
-// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <util/hooks/callout_handle.h>
-#include <util/hooks/library_handle.h>
-#include <util/hooks/server_hooks.h>
-
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-using namespace isc::util;
-using namespace std;
-
-namespace {
-
-class LibraryHandleTest : public ::testing::Test {
-public:
-    /// @brief Constructor
-    ///
-    /// Sets up an appropriate number of server hooks to pass to the
-    /// constructed callout handle objects.
-    LibraryHandleTest() : hooks_(new ServerHooks()) {
-        hooks_->registerHook("alpha");
-        hooks_->registerHook("beta");
-        hooks_->registerHook("gamma");
-        collection_.reset(new LibraryHandleCollection(hooks_));
-
-        // Also initialize the variable used to pass information back from the
-        // callouts to the tests.
-        callout_value = 0;
-    }
-
-    /// Obtain constructed server hooks.
-    boost::shared_ptr<ServerHooks>& getServerHooks() {
-        return (hooks_);
-    }
-
-    /// Obtain constructed hook manager.
-    boost::shared_ptr<LibraryHandleCollection>& getLibraryHandleCollection() {
-        return (collection_);
-    }
-
-    /// Variable for callouts test. This is public and static to allow non-
-    /// member functions to access it.  It is initialized every time a new
-    /// test starts.
-    static int callout_value;
-
-private:
-    boost::shared_ptr<ServerHooks> hooks_;
-    boost::shared_ptr<LibraryHandleCollection> collection_;
-    boost::shared_ptr<LibraryHandle> handle_0_;
-    boost::shared_ptr<LibraryHandle> handle_1_;
-};
-
-// Definition of the static variable.
-int LibraryHandleTest::callout_value = 0;
-
-// The next set of tests check that callouts can be registered.
-
-// The callouts defined here are structured in such a way that it is possible
-// to determine the order in which they are called and whether they are called
-// at all. The method used is simple - after a sequence of callouts, the digits
-// in the value, reading left to right, determines the order of the callouts
-// called.  For example, callout one followed by two followed by three followed
-// by two followed by one results in a value of 12321.
-//
-// Functions return a zero to indicate success.
-
-extern "C" {
-int one(CalloutHandle&) {
-    LibraryHandleTest::callout_value =
-        10 * LibraryHandleTest::callout_value + 1;
-    return (0);
-}
-
-int two(CalloutHandle&) {
-    LibraryHandleTest::callout_value =
-        10 * LibraryHandleTest::callout_value + 2;
-    return (0);
-}
-
-int three(CalloutHandle&) {
-    LibraryHandleTest::callout_value =
-        10 * LibraryHandleTest::callout_value + 3;
-    return (0);
-}
-
-// The next function is a duplicate of "one", but returns an error status.
-
-int one_error(CalloutHandle& handle) {
-    static_cast<void>(one(handle));
-    return (1);
-}
-
-// The next function is a duplicate of "one", but sets the skip flag.
-
-int one_skip(CalloutHandle& handle) {
-    handle.setSkip(true);
-    return (one(handle));
-}
-
-};  // extern "C"
-
-// Check that we can register callouts on a particular hook.
-
-TEST_F(LibraryHandleTest, RegisterSingleCallout) {
-    LibraryHandle handle(getServerHooks());
-
-    // Register callouts for hooks alpha and see that it is registered.
-    EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-    handle.registerCallout("alpha", one);
-    EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-
-    // Do the same for beta (which checks that the hooks are independent).
-    EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("beta")));
-    handle.registerCallout("beta", one);
-    EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("beta")));
-}
-
-// Check that we can call a single callout on a particular hook.  Refer to the
-// above definition of the callouts "one" and "two" to understand the expected
-// return values.
-
-TEST_F(LibraryHandleTest, CallSingleCallout) {
-    LibraryHandle handle(getServerHooks());
-
-    // Register callout for hook alpha...
-    EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-    handle.registerCallout("alpha", one);
-    EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-
-    // Call it.
-    EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
-    int index = getServerHooks()->getIndex("alpha");
-    CalloutHandle callout_handle(getLibraryHandleCollection());
-    int status = handle.callCallouts(index, callout_handle);
-
-    EXPECT_EQ(0, status);
-    EXPECT_EQ(1, LibraryHandleTest::callout_value);
-
-}
-
-// Check that we can register two callouts for a hook and that they are called
-// in order.
-
-TEST_F(LibraryHandleTest, TwoCallouts) {
-    LibraryHandle handle(getServerHooks());
-
-    // Register two callouts for hook alpha.
-    handle.registerCallout("alpha", one);
-    handle.registerCallout("alpha", two);
-
-    // Call them.
-    EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
-    int index = getServerHooks()->getIndex("alpha");
-    CalloutHandle callout_handle(getLibraryHandleCollection());
-    int status = handle.callCallouts(index, callout_handle);
-
-    EXPECT_EQ(0, status);
-    EXPECT_EQ(12, LibraryHandleTest::callout_value);
-}
-
-// Check that we can register two callouts for a hook and that the second is not
-// called if the first returns a non-zero status.
-
-TEST_F(LibraryHandleTest, TwoCalloutsWithError) {
-    LibraryHandle handle(getServerHooks());
-
-    // Register callout for hook alpha...
-    handle.registerCallout("alpha", one_error);
-    handle.registerCallout("alpha", two);
-
-    // Call them.
-    EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
-    int index = getServerHooks()->getIndex("alpha");
-    CalloutHandle callout_handle(getLibraryHandleCollection());
-    int status = handle.callCallouts(index, callout_handle);
-
-    EXPECT_EQ(1, status);
-    EXPECT_EQ(1, LibraryHandleTest::callout_value);
-}
-
-// Check that we can register two callouts for a hook and that the second is not
-// called if the first szets the callout "skip" flag.
-
-TEST_F(LibraryHandleTest, TwoCalloutsWithSkip) {
-    LibraryHandle handle(getServerHooks());
-
-    // Register callout for hook alpha.
-    handle.registerCallout("alpha", one_skip);
-    handle.registerCallout("alpha", two);
-
-    // Call them.
-    EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
-    int index = getServerHooks()->getIndex("alpha");
-    CalloutHandle callout_handle(getLibraryHandleCollection());
-    int status = handle.callCallouts(index, callout_handle);
-
-    EXPECT_EQ(0, status);
-    EXPECT_EQ(1, LibraryHandleTest::callout_value);
-}
-
-// Check that a callout can be registered more than once.
-
-TEST_F(LibraryHandleTest, MultipleRegistration) {
-    LibraryHandle handle(getServerHooks());
-
-    // Register callouts for hook alpha.
-    handle.registerCallout("alpha", one);
-    handle.registerCallout("alpha", two);
-    handle.registerCallout("alpha", one);
-
-    // Call them.
-    EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
-    int index = getServerHooks()->getIndex("alpha");
-    CalloutHandle callout_handle(getLibraryHandleCollection());
-    int status = handle.callCallouts(index, callout_handle);
-
-    EXPECT_EQ(0, status);
-    EXPECT_EQ(121, LibraryHandleTest::callout_value);
-}
-
-// Check that a callout can be deregistered.
-
-TEST_F(LibraryHandleTest, Deregister) {
-    LibraryHandle handle(getServerHooks());
-
-    // Register callouts for hook alpha...
-    handle.registerCallout("alpha", one);
-    handle.registerCallout("alpha", two);
-    handle.registerCallout("alpha", one);
-
-    // Get rid of all the "one" callbacks.
-    handle.deregisterCallout("alpha", one);
-
-    // Call it.
-    EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
-    int index = getServerHooks()->getIndex("alpha");
-    CalloutHandle callout_handle(getLibraryHandleCollection());
-    int status = handle.callCallouts(index, callout_handle);
-
-    EXPECT_EQ(0, status);
-    EXPECT_EQ(2, LibraryHandleTest::callout_value);
-}
-
-// Check that all callouts can be deregistered.
-
-TEST_F(LibraryHandleTest, DeregisterAll) {
-    LibraryHandle handle(getServerHooks());
-
-    // Register callouts for hook alpha...
-    EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-    handle.registerCallout("alpha", one);
-    handle.registerCallout("alpha", two);
-    EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-
-    // ... and remove them.
-    handle.deregisterAll("alpha");
-    EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-}
-
-// Add checks that invalid names etc. all throw.  With the base hooks added
-// by the constructor, there are five valid hooks, with valid indexes 0 to 4.
-
-TEST_F(LibraryHandleTest, InvalidNameAndIndex) {
-    LibraryHandle handle(getServerHooks());
-
-    EXPECT_THROW(handle.registerCallout("omega", one), NoSuchHook);
-    EXPECT_THROW(handle.deregisterCallout("omega", one), NoSuchHook);
-    EXPECT_THROW(handle.deregisterAll("omega"), NoSuchHook);
-
-    EXPECT_THROW(static_cast<void>(handle.calloutsPresent(-1)), NoSuchHook);
-    EXPECT_THROW(static_cast<void>(handle.calloutsPresent(5)), NoSuchHook);
-
-    CalloutHandle callout_handle(getLibraryHandleCollection());
-    EXPECT_THROW(static_cast<void>(handle.callCallouts(-1, callout_handle)),
-                 NoSuchHook);
-    EXPECT_THROW(static_cast<void>(handle.callCallouts(10, callout_handle)),
-                 NoSuchHook);
-}
-
-
-} // Anonymous namespace