Parcourir la source

[2205] added DataSrcClientsBuilder class, main part of configurator thread

JINMEI Tatuya il y a 12 ans
Parent
commit
26ea6b0e30

+ 1 - 0
src/bin/auth/Makefile.am

@@ -55,6 +55,7 @@ b10_auth_SOURCES += auth_config.cc auth_config.h
 b10_auth_SOURCES += command.cc command.h
 b10_auth_SOURCES += common.h common.cc
 b10_auth_SOURCES += statistics.cc statistics.h
+b10_auth_SOURCES += datasrc_clients_mgr.h
 b10_auth_SOURCES += datasrc_config.h datasrc_config.cc
 b10_auth_SOURCES += main.cc
 

+ 131 - 0
src/bin/auth/datasrc_clients_mgr.h

@@ -0,0 +1,131 @@
+// Copyright (C) 2012  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 DATASRC_CLIENTS_MGR_H
+#define DATASRC_CLIENTS_MGR_H 1
+
+//#include <util/threads/thread.h>
+#include <util/threads/lock.h>
+
+#include <cc/data.h>
+
+#include <list>
+#include <utility>
+
+namespace isc {
+namespace auth {
+
+namespace internal {
+enum CommandID {
+    NOOP,                       ///< Do nothing.  Only useful for tests
+    SHUTDOWN                    ///< Shutdown the builder.
+};
+typedef std::pair<CommandID, data::ConstElementPtr> Command;
+
+template <typename MutexType, typename CondVarType>
+class DataSrcClientsBuilderBase {
+public:
+    DataSrcClientsBuilderBase(std::list<Command>* command_queue,
+                              CondVarType* cond, MutexType* queue_mutex) :
+        command_queue_(command_queue), cond_(cond), queue_mutex_(queue_mutex)
+    {}
+
+    /// Not sure if we need this.  It depends on test details.
+    /// \brief Destructor.
+    ///
+    /// This does nothing, but explicitly defined to silence 'unused variable'
+    /// warnings from some versions of clang++.
+    ///~DataSrcClientsBuilderBase() {}
+
+    void run();
+
+    /// separated from run() and made public for the purpose of tests.
+    ///
+    /// \return true if it the builder should keep running; false otherwise.
+    bool handleCommand(const Command& command);
+
+private:
+    // NOOP command handler.  We use this so tests can override it.
+    void doNoop() {}
+
+    // end-in, front-out queue
+    std::list<Command>* command_queue_;
+    CondVarType* cond_;
+    MutexType* queue_mutex_;
+    //boost::shared_ptr<DataSrcClientListMap>* map;
+    //MutexType* data_mutex_;
+};
+}
+
+template <typename ThreadType, typename MutexType, typename CondVarType>
+class DataSrcClientsMgrBase {
+public:
+    DataSrcClientsMgrBase() : builder_(&command_queue_, &cond_, &queue_mutex_)
+    {}
+    ~DataSrcClientsMgrBase() {}
+
+private:
+    std::list<internal::Command> command_queue_;
+    CondVarType cond_;
+    MutexType queue_mutex_;
+    internal::DataSrcClientsBuilderBase<MutexType, CondVarType> builder_;
+};
+
+namespace internal {
+template <typename MutexType, typename CondVarType>
+void
+DataSrcClientsBuilderBase<MutexType, CondVarType>::run() {
+    bool keep_running = true;
+    while (keep_running) {
+        std::list<Command> current_commands;
+        {
+            // Move all new commands to local queue under the protection of
+            // queue_mutex_.  Note that list::splice() should never throw.
+            typename MutexType::Locker locker(*queue_mutex_);
+            while (command_queue_->empty()) {
+                cond_->wait(*queue_mutex_);
+            }
+            current_commands.splice(current_commands.end(), *command_queue_);
+        } // the lock is release here.
+
+        while (keep_running && !current_commands.empty()) {
+            keep_running = handleCommand(current_commands.front());
+            current_commands.pop_front();
+        }
+    }
+}
+
+template <typename MutexType, typename CondVarType>
+bool
+DataSrcClientsBuilderBase<MutexType, CondVarType>::handleCommand(
+    const Command& command)
+{
+    switch (command.first) {
+    case SHUTDOWN:
+        return (false);
+    case NOOP:
+        doNoop();
+    }
+    return (true);
+}
+}
+
+} // namespace auth
+} // namespace isc
+
+#endif  // DATASRC_CLIENTS_MGR_H
+
+// Local Variables:
+// mode: c++
+// End:

+ 2 - 0
src/bin/auth/tests/Makefile.am

@@ -51,6 +51,8 @@ run_unittests_SOURCES += command_unittest.cc
 run_unittests_SOURCES += common_unittest.cc
 run_unittests_SOURCES += query_unittest.cc
 run_unittests_SOURCES += statistics_unittest.cc
+run_unittests_SOURCES += test_datasrc_clients_mgr.h test_datasrc_clients_mgr.cc
+run_unittests_SOURCES += datasrc_clients_builder_unittest.cc
 run_unittests_SOURCES += datasrc_config_unittest.cc
 run_unittests_SOURCES += run_unittests.cc
 

+ 87 - 0
src/bin/auth/tests/datasrc_clients_builder_unittest.cc

@@ -0,0 +1,87 @@
+// Copyright (C) 2012  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 <cc/data.h>
+
+#include <auth/datasrc_clients_mgr.h>
+#include "test_datasrc_clients_mgr.h"
+
+#include <gtest/gtest.h>
+
+#include <boost/function.hpp>
+
+using isc::data::ConstElementPtr;
+using namespace isc::auth::internal;
+
+namespace {
+class DataSrcClientsBuilderTest : public ::testing::Test {
+protected:
+    DataSrcClientsBuilderTest() :
+        builder(&command_queue, &cond, &queue_mutex),
+        cond(command_queue, delayed_command_queue),
+        shutdown_cmd(SHUTDOWN, ConstElementPtr()),
+        noop_cmd(NOOP, ConstElementPtr())
+    {}
+
+    TestDataSrcClientsBuilder builder;
+    std::list<Command> command_queue; // test command queue
+    std::list<Command> delayed_command_queue; // commands available after wait
+    TestCondVar cond;
+    TestMutex queue_mutex;
+    const Command shutdown_cmd;
+    const Command noop_cmd;
+};
+
+TEST_F(DataSrcClientsBuilderTest, runSingleCommand) {
+    // A simplest case, just to check the basic behavior.
+    command_queue.push_back(shutdown_cmd);
+    builder.run();
+    EXPECT_TRUE(command_queue.empty());
+    EXPECT_EQ(0, cond.wait_count); // no wait because command queue is not empty
+    EXPECT_EQ(1, queue_mutex.lock_count);
+    EXPECT_EQ(1, queue_mutex.unlock_count);
+}
+
+TEST_F(DataSrcClientsBuilderTest, runMultiCommands) {
+    // Two NOOP commands followed by SHUTDOWN.  We should see two doNoop()
+    // calls.
+    command_queue.push_back(noop_cmd);
+    command_queue.push_back(noop_cmd);
+    command_queue.push_back(shutdown_cmd);
+    builder.run();
+    EXPECT_TRUE(command_queue.empty());
+    EXPECT_EQ(1, queue_mutex.lock_count);
+    EXPECT_EQ(1, queue_mutex.unlock_count);
+    EXPECT_EQ(2, queue_mutex.noop_count);
+}
+
+TEST_F(DataSrcClientsBuilderTest, condWait) {
+    // command_queue is originally empty, so it will require waiting on
+    // condvar.  specialized wait() will make the delayed command available.
+    delayed_command_queue.push_back(shutdown_cmd);
+    builder.run();
+
+    // There should be one call to wait()
+    EXPECT_EQ(1, cond.wait_count);
+    // wait() effectively involves one more set of lock/unlock, so we have
+    // two in total
+    EXPECT_EQ(2, queue_mutex.lock_count);
+    EXPECT_EQ(2, queue_mutex.unlock_count);
+}
+
+TEST_F(DataSrcClientsBuilderTest, shutdown) {
+    EXPECT_FALSE(builder.handleCommand(shutdown_cmd));
+}
+
+} // unnamed namespace

+ 31 - 0
src/bin/auth/tests/test_datasrc_clients_mgr.cc

@@ -0,0 +1,31 @@
+// Copyright (C) 2012  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 "test_datasrc_clients_mgr.h"
+
+namespace isc {
+namespace auth {
+namespace internal {
+template<>
+void
+TestDataSrcClientsBuilder::doNoop() {
+    ++queue_mutex_->noop_count;
+}
+}
+}
+}
+
+// Local Variables:
+// mode: c++
+// End:

+ 95 - 0
src/bin/auth/tests/test_datasrc_clients_mgr.h

@@ -0,0 +1,95 @@
+// Copyright (C) 2012  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 TEST_DATASRC_CLIENTS_MGR_H
+#define TEST_DATASRC_CLIENTS_MGR_H 1
+
+#include <auth/datasrc_clients_mgr.h>
+
+#include <boost/function.hpp>
+
+#include <list>
+
+// Below we extend the isc::auth::internal namespace to specialize
+// the doNoop() method.
+namespace isc {
+namespace auth {
+namespace internal {
+class TestMutex {
+public:
+    TestMutex() : lock_count(0), unlock_count(0), noop_count(0) {}
+    class Locker {
+    public:
+        Locker(TestMutex& mutex) : mutex_(mutex) {
+            ++mutex.lock_count;
+        }
+        ~Locker() {
+            ++mutex_.unlock_count;
+        }
+    private:
+        TestMutex& mutex_;
+    };
+    size_t lock_count;
+    size_t unlock_count;
+    size_t noop_count;          // allow doNoop() to modify this
+};
+
+class TestCondVar {
+public:
+    TestCondVar(std::list<Command>& command_queue,
+                std::list<Command>& delayed_command_queue) :
+        wait_count(0),
+        command_queue_(command_queue),
+        delayed_command_queue_(delayed_command_queue)
+    {
+    }
+    void wait(TestMutex& mutex) {
+        // bookkeeping
+        ++mutex.unlock_count;
+        ++wait_count;
+        ++mutex.lock_count;
+
+        // make the delayed commands available
+        command_queue_.splice(command_queue_.end(), delayed_command_queue_);
+    }
+    size_t wait_count;
+private:
+    std::list<Command>& command_queue_;
+    std::list<Command>& delayed_command_queue_;
+};
+
+class TestThread {
+public:
+    TestThread(const boost::function<void()>& /*main*/);
+};
+
+// Convenient shortcut
+typedef DataSrcClientsBuilderBase<TestMutex, TestCondVar>
+TestDataSrcClientsBuilder;
+
+// We specialize this command handler for the convenience of tests.
+// It abuses our specialized Mutex to count the number of calls of this method.
+template<>
+void
+TestDataSrcClientsBuilder::doNoop();
+
+} // namespace internal
+}
+}
+
+#endif  // TEST_DATASRC_CLIENTS_MGR_H
+
+// Local Variables:
+// mode: c++
+// End: