123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- // 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 <log/logger_support.h>
- #include <log/log_dbglevels.h>
- #include <cc/data.h>
- #include <auth/auth_log.h>
- #include <boost/bind.hpp>
- #include <list>
- #include <utility>
- namespace isc {
- namespace auth {
- namespace datasrc_clientmgr_internal {
- enum CommandID {
- NOOP, ///< Do nothing. Only useful for tests
- SHUTDOWN ///< Shutdown the builder.
- };
- typedef std::pair<CommandID, data::ConstElementPtr> Command;
- } // namespace datasrc_clientmgr_internal
- template <typename ThreadType, typename BuilderType, typename MutexType,
- typename CondVarType>
- class DataSrcClientsMgrBase {
- public:
- DataSrcClientsMgrBase() :
- builder_(&command_queue_, &cond_, &queue_mutex_),
- builder_thread_(boost::bind(&BuilderType::run, &builder_))
- {}
- ~DataSrcClientsMgrBase() {
- // We share class member variables with the builder, which will be
- // invalidated after the call to the destructor, so we need to make
- // sure the builder thread is terminated. Depending on the timing
- // this could time; if we don't want that to happen in this context,
- // we may want to introduce a separate 'shutdown()' method.
- // Also, since we don't want to propagate exceptions from a destructor,
- // we catch any possible ones. In fact the only really expected one
- // is Thread::UncaughtException when the builder thread died due to
- // an exception. We specifically log it and just ignore others.
- try {
- sendCommand(datasrc_clientmgr_internal::SHUTDOWN,
- data::ConstElementPtr());
- builder_thread_.wait();
- } catch (const util::thread::Thread::UncaughtException& ex) {
- LOG_ERROR(auth_logger, AUTH_DATASRC_CLIENTS_SHUTDOWN_ERROR).
- arg(ex.what());
- } catch (...) {}
- }
- private:
- void sendCommand(datasrc_clientmgr_internal::CommandID command,
- data::ConstElementPtr arg) {
- {
- typename MutexType::Locker locker(queue_mutex_);
- command_queue_.push_back(
- datasrc_clientmgr_internal::Command(command, arg));
- }
- cond_.signal();
- }
- std::list<datasrc_clientmgr_internal::Command> command_queue_;
- CondVarType cond_;
- MutexType queue_mutex_;
- BuilderType builder_;
- ThreadType builder_thread_;
- };
- namespace datasrc_clientmgr_internal {
- 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_;
- };
- // Shortcut typedef for normal use
- typedef DataSrcClientsBuilderBase<util::thread::Mutex, util::thread::CondVar>
- DataSrcClientsBuilder;
- template <typename MutexType, typename CondVarType>
- void
- DataSrcClientsBuilderBase<MutexType, CondVarType>::run() {
- LOG_INFO(auth_logger, AUTH_DATASRC_CLIENTS_BUILDER_STARTED);
- try {
- 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();
- }
- }
- LOG_INFO(auth_logger, AUTH_DATASRC_CLIENTS_BUILDER_STOPPED);
- } catch (const std::exception& ex) {
- // We explicitly catch exceptions so we can log it as soon as possible.
- LOG_ERROR(auth_logger, AUTH_DATASRC_CLIENTS_BUILDER_FAILED).
- arg(ex.what());
- throw;
- } catch (...) {
- LOG_ERROR(auth_logger, AUTH_DATASRC_CLIENTS_BUILDER_FAILED_UNEXPECTED);
- throw;
- }
- }
- template <typename MutexType, typename CondVarType>
- bool
- DataSrcClientsBuilderBase<MutexType, CondVarType>::handleCommand(
- const Command& command)
- {
- LOG_DEBUG(auth_logger, DBGLVL_TRACE_BASIC,
- AUTH_DATASRC_CLIENTS_BUILDER_COMMAND).arg(command.first);
- switch (command.first) {
- case SHUTDOWN:
- return (false);
- case NOOP:
- doNoop();
- }
- return (true);
- }
- } // namespace datasrc_clientmgr_internal
- /// \brief Shortcut type for normal data source clients manager.
- ///
- /// In fact, for non test applications this is the only type of this kind
- /// to be considered.
- typedef DataSrcClientsMgrBase<
- util::thread::Thread,
- datasrc_clientmgr_internal::DataSrcClientsBuilder,
- util::thread::Mutex, util::thread::CondVar> DataSrcClientsMgr;
- } // namespace auth
- } // namespace isc
- #endif // DATASRC_CLIENTS_MGR_H
- // Local Variables:
- // mode: c++
- // End:
|