Browse Source

[2974] Added ServerHooks class

This is the first part of the hooks implementation, a class that
carries the list of hooks.
Stephen Morris 12 years ago
parent
commit
82679565ad

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

@@ -37,6 +37,7 @@ libb10_util_la_SOURCES += encode/base32hex_from_binary.h
 libb10_util_la_SOURCES += encode/base_n.cc encode/hex.h
 libb10_util_la_SOURCES += encode/binary_from_base32hex.h
 libb10_util_la_SOURCES += encode/binary_from_base16.h
+libb10_util_la_SOURCES += hooks/server_hooks.h hooks/server_hooks.cc
 libb10_util_la_SOURCES += random/qid_gen.h random/qid_gen.cc
 libb10_util_la_SOURCES += random/random_number_generator.h
 

+ 94 - 0
src/lib/util/hooks/server_hooks.cc

@@ -0,0 +1,94 @@
+// 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 <exceptions/exceptions.h>
+#include <util/hooks/server_hooks.h>
+
+#include <utility>
+
+using namespace std;
+using namespace isc;
+
+namespace isc {
+namespace util {
+
+// Constructor - register the pre-defined hooks and check that the indexes
+// assigned to them are as expected.
+
+ServerHooks::ServerHooks() {
+    int create = registerHook("context_create");
+    int destroy = registerHook("context_destroy");
+
+    if ((create != CONTEXT_CREATE) || (destroy != CONTEXT_DESTROY)) {
+        isc_throw(Unexpected, "pre-defined hook indexes are not as expected. "
+                  "context_create: expected = " << CONTEXT_CREATE <<
+                  ", actual = " << create <<
+                  ". context_destroy: expected = " << CONTEXT_DESTROY <<
+                  ", actual = " << destroy);
+    }
+}
+
+// Register a hook.  The index assigned to the hook is the current number
+// of entries in the collection.
+
+int
+ServerHooks::registerHook(const string& name) {
+
+    // Determine index for the new element and insert.
+    int index = hooks_.size();
+    pair<HookCollection::iterator, bool> result =
+        hooks_.insert(make_pair(name, index));
+
+    if (!result.second) {
+        // New element was not inserted because an element with the same name
+        // already existed.
+        isc_throw(DuplicateHook, "hook with name " << name <<
+                  " is already registered");
+    }
+
+    // New element inserted, return numeric index.
+    return (index);
+}
+
+// Find the index associated with a hook name or return -1 if not found
+
+int
+ServerHooks::getIndex(const string& name) const {
+
+    // Return pair of <hook name, index>.
+    HookCollection::const_iterator i = hooks_.find(name);
+    if (i == hooks_.end()) {
+        return (-1);
+    }
+
+    return (i->second);
+}
+
+// Return list of hooks
+
+std::vector<std::string>
+ServerHooks::getHookNames() const {
+
+    std::vector<std::string> names;
+    HookCollection::const_iterator i;
+    for (i = hooks_.begin(); i != hooks_.end(); ++i) {
+        names.push_back(i->first);
+    }
+
+    return (names);
+}
+
+
+} // namespace util
+} // namespace isc

+ 116 - 0
src/lib/util/hooks/server_hooks.h

@@ -0,0 +1,116 @@
+// 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.
+
+#ifndef SERVER_HOOKS_H
+#define SERVER_HOOKS_H
+
+#include <exceptions/exceptions.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace isc {
+namespace util {
+
+/// @brief Duplicate Hook
+///
+/// Thrown if an attempt is made to register a hook with the same name as a
+/// previously-registered hook.
+
+class DuplicateHook : public Exception {
+public:
+    DuplicateHook(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+
+/// @brief Server Hook List
+///
+/// This class is used by the server-side code to register hooks - points at
+/// in the server processing at which libraries can register functions
+/// (callouts) that the server will call.  These functions can modify data and
+/// so affect the processing of the server.
+///
+/// The ServerHooks class is little more than a wrapper around the std::map
+/// class.  It stores a hook, assigning to it a unique index number.  This
+/// number is then used by the server code to identify the hook being called.
+
+class ServerHooks {
+public:
+
+    /// Pre-Defined Hooks
+    static const int CONTEXT_CREATE = 0;
+    static const int CONTEXT_DESTROY = 1;
+
+    /// @brief Constructor
+    ///
+    /// This pre-registers two hooks, context_create and context_destroy.  These
+    /// are called by the server before processing a packet and after processing
+    /// for the packet has completed.  They allow the server code to allocate
+    /// and destroy per-packet context.
+    ///
+    /// @throws isc::Unexpected if the registration of the pre-defined hooks
+    ///         fails in some way.
+    ServerHooks();
+
+    /// @brief Register a Hook
+    ///
+    /// Registers a hook and returns the hook index.
+    ///
+    /// @param name Name of the hook
+    ///
+    /// @return Index of the hook, to be used in subsequent calls.  This will
+    ///         be greater than or equal to zero.
+    ///
+    /// @throws DuplicateHook A hook with the same name has already been
+    ///         registered.
+    int registerHook(const std::string& name);
+
+    /// @brief Get Hook Index
+    ///
+    /// Returns the index of a hook.
+    ///
+    /// @param name Name of the hook
+    ///
+    /// @return Index of the hook, to be used in subsequent calls. A value of
+    ///         -1 is returned if no hook of the given name is found.
+    int getIndex(const std::string& name) const;
+
+    /// @brief Return Number of Hooks
+    ///
+    /// Returns the total number of hooks registered.
+    ///
+    /// @return Number of hooks registered.
+    int getCount() const {
+        return (hooks_.size());
+    }
+
+    /// @brief Hook Names
+    ///
+    /// Return list of hooks registered in the object.
+    ///
+    /// @return Vector of strings holding hook names.
+    std::vector<std::string> getHookNames() const;
+
+private:
+    typedef std::map<std::string, int> HookCollection;
+
+    HookCollection  hooks_;     ///< Hook name/index collection
+};
+
+} // namespace util
+} // namespace isc
+
+#endif  // SERVER_HOOKS_H

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

@@ -39,6 +39,7 @@ run_unittests_SOURCES += memory_segment_common_unittest.h
 run_unittests_SOURCES += memory_segment_common_unittest.cc
 run_unittests_SOURCES += qid_gen_unittest.cc
 run_unittests_SOURCES += random_number_generator_unittest.cc
+run_unittests_SOURCES += server_hooks_unittest.cc
 run_unittests_SOURCES += sha1_unittest.cc
 run_unittests_SOURCES += socketsession_unittest.cc
 run_unittests_SOURCES += strutil_unittest.cc

+ 97 - 0
src/lib/util/tests/server_hooks_unittest.cc

@@ -0,0 +1,97 @@
+// 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/server_hooks.h>
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+using namespace isc;
+using namespace isc::util;
+using namespace std;
+
+// Checks the registration of hooks and the interrogation methods.  As the
+// constructor registers two hooks, this is also a test of the construction.
+
+namespace {
+
+TEST(ServerHooksTest, RegisterHooks) {
+    ServerHooks hooks;
+
+    // Should be two hooks already registered, with indexes 0 and 1.
+    EXPECT_EQ(2, hooks.getCount());
+    EXPECT_EQ(0, hooks.getIndex("context_create"));
+    EXPECT_EQ(1, hooks.getIndex("context_destroy"));
+
+    // Register another couple of hooks.  The test on returned index is based
+    // on knowledge that the hook indexes are assigned in ascending order.
+    int alpha = hooks.registerHook("alpha");
+    EXPECT_EQ(2, alpha);
+    EXPECT_EQ(2, hooks.getIndex("alpha"));
+
+    int beta = hooks.registerHook("beta");
+    EXPECT_EQ(3, beta);
+    EXPECT_EQ(3, hooks.getIndex("beta"));
+
+    // Should be four hooks now
+    EXPECT_EQ(4, hooks.getCount());
+}
+
+// Checks that duplcate names cannot be registered.
+
+TEST(ServerHooksTest, DuplicateHooks) {
+    ServerHooks hooks;
+
+    // Ensure we can duplicate one of the existing names.
+    EXPECT_THROW(hooks.registerHook("context_create"), DuplicateHook);
+
+    int gamma = hooks.registerHook("gamma");
+    EXPECT_EQ(2, gamma);
+    EXPECT_THROW(hooks.registerHook("gamma"), DuplicateHook);
+}
+
+// Checks that we can get the name of the hooks
+
+TEST(ServerHooksTest, GetHookNames) {
+    vector<string> expected_names;
+    ServerHooks hooks;
+
+    // Insert the names into the hooks object
+    expected_names.push_back("alpha");
+    expected_names.push_back("beta");
+    expected_names.push_back("gamma");
+    expected_names.push_back("delta");
+    for (int i = 0; i < expected_names.size(); ++i) {
+        hooks.registerHook(expected_names[i].c_str());
+    };
+
+    // Update the expected names to include the pre-defined hook names.
+    expected_names.push_back("context_create");
+    expected_names.push_back("context_destroy");
+
+    // Get the actual hook names
+    vector<string> actual_names = hooks.getHookNames();
+
+    // For comparison, sort the name sinto alphabetical order and do a straight
+    // vector comparison.
+    sort(expected_names.begin(), expected_names.end());
+    sort(actual_names.begin(), actual_names.end());
+
+    EXPECT_TRUE(expected_names == actual_names);
+}
+
+} // Anonymous namespace