From: JINMEI Tatuya Date: Sat, 13 Oct 2012 02:44:18 +0000 (-0700) Subject: [2205] added DataSrcClientsBuilder class, main part of configurator thread X-Git-Tag: trac2402_base~15^2~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=26ea6b0e3045489e542b95d02052fc7565a4ca87;p=thirdparty%2Fkea.git [2205] added DataSrcClientsBuilder class, main part of configurator thread --- diff --git a/src/bin/auth/Makefile.am b/src/bin/auth/Makefile.am index 9eee9d4d54..6ee6677607 100644 --- a/src/bin/auth/Makefile.am +++ b/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 diff --git a/src/bin/auth/datasrc_clients_mgr.h b/src/bin/auth/datasrc_clients_mgr.h new file mode 100644 index 0000000000..2962f0f9d5 --- /dev/null +++ b/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 +#include + +#include + +#include +#include + +namespace isc { +namespace auth { + +namespace internal { +enum CommandID { + NOOP, ///< Do nothing. Only useful for tests + SHUTDOWN ///< Shutdown the builder. +}; +typedef std::pair Command; + +template +class DataSrcClientsBuilderBase { +public: + DataSrcClientsBuilderBase(std::list* 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_queue_; + CondVarType* cond_; + MutexType* queue_mutex_; + //boost::shared_ptr* map; + //MutexType* data_mutex_; +}; +} + +template +class DataSrcClientsMgrBase { +public: + DataSrcClientsMgrBase() : builder_(&command_queue_, &cond_, &queue_mutex_) + {} + ~DataSrcClientsMgrBase() {} + +private: + std::list command_queue_; + CondVarType cond_; + MutexType queue_mutex_; + internal::DataSrcClientsBuilderBase builder_; +}; + +namespace internal { +template +void +DataSrcClientsBuilderBase::run() { + bool keep_running = true; + while (keep_running) { + std::list 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 +bool +DataSrcClientsBuilderBase::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: diff --git a/src/bin/auth/tests/Makefile.am b/src/bin/auth/tests/Makefile.am index 6b9d385298..7e4257c4e1 100644 --- a/src/bin/auth/tests/Makefile.am +++ b/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 diff --git a/src/bin/auth/tests/datasrc_clients_builder_unittest.cc b/src/bin/auth/tests/datasrc_clients_builder_unittest.cc new file mode 100644 index 0000000000..548621674f --- /dev/null +++ b/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 + +#include +#include "test_datasrc_clients_mgr.h" + +#include + +#include + +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_queue; // test command queue + std::list 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 diff --git a/src/bin/auth/tests/test_datasrc_clients_mgr.cc b/src/bin/auth/tests/test_datasrc_clients_mgr.cc new file mode 100644 index 0000000000..0634487c2a --- /dev/null +++ b/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: diff --git a/src/bin/auth/tests/test_datasrc_clients_mgr.h b/src/bin/auth/tests/test_datasrc_clients_mgr.h new file mode 100644 index 0000000000..dece856a30 --- /dev/null +++ b/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 + +#include + +#include + +// 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_queue, + std::list& 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_queue_; + std::list& delayed_command_queue_; +}; + +class TestThread { +public: + TestThread(const boost::function& /*main*/); +}; + +// Convenient shortcut +typedef DataSrcClientsBuilderBase +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: