#include <datasrc/memory/zone_writer.h>
#include <asiolink/io_service.h>
+#include <asiolink/local_socket.h>
#include <auth/auth_log.h>
#include <auth/datasrc_config.h>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/function.hpp>
+#include <boost/foreach.hpp>
#include <exception>
#include <cassert>
///
/// \throw std::bad_alloc internal memory allocation failure.
/// \throw isc::Unexpected general unexpected system errors.
- DataSrcClientsMgrBase(asiolink::IOService&) :
+ DataSrcClientsMgrBase(asiolink::IOService& service) :
clients_map_(new ClientListsMap),
fd_guard_(new FDGuard(this)),
read_fd_(-1), write_fd_(-1),
builder_(&command_queue_, &callback_queue_, &cond_, &queue_mutex_,
&clients_map_, &map_mutex_, createFds()),
- builder_thread_(boost::bind(&BuilderType::run, &builder_))
- {}
+ builder_thread_(boost::bind(&BuilderType::run, &builder_)),
+ wakeup_socket_(service, read_fd_)
+ {
+ // Schedule wakeups when callbacks are pushed.
+ wakeup_socket_.asyncRead(
+ boost::bind(&DataSrcClientsMgrBase::processCallbacks, this, _1),
+ buffer, 1);
+ }
/// \brief The destructor.
///
AUTH_DATASRC_CLIENTS_SHUTDOWN_UNEXPECTED_ERROR);
}
+ processCallbacks(); // Any leftover callbacks
cleanup(); // see below
}
///
/// \param config_arg The new data source configuration. Must not be NULL.
/// \param callback Called once the reconfigure command completes. It is
- /// called in the main thread (not in the work one).
+ /// called in the main thread (not in the work one). It should be
+ /// exceptionless.
void reconfigure(const data::ConstElementPtr& config_arg,
const datasrc_clientmgr_internal::FinishedCallback&
callback = datasrc_clientmgr_internal::FinishedCallback())
/// { "class": "IN", "origin": "example.com" }
/// (but class is optional and will default to IN)
/// \param callback Called once the loadZone command completes. It
- /// is called in the main thread, not in the work thread.
+ /// is called in the main thread, not in the work thread. It should
+ /// be exceptionless.
///
/// \exception CommandError if the args value is null, or not in
/// the expected format, or contains
return write_fd_;
}
+ void processCallbacks(const std::string& error = std::string()) {
+ // Schedule the next read.
+ wakeup_socket_.asyncRead(
+ boost::bind(&DataSrcClientsMgrBase::processCallbacks, this, _1),
+ buffer, 1);
+ if (!error.empty()) {
+ // Generally, there should be no errors (as we are the other end
+ // as well), but check just in case.
+ isc_throw(Unexpected, error);
+ }
+
+ // Steal the callbacks into local copy.
+ std::list<datasrc_clientmgr_internal::FinishedCallback> queue;
+ {
+ typename MutexType::Locker locker(queue_mutex_);
+ queue.swap(callback_queue_);
+ }
+
+ // Execute the callbacks
+ BOOST_FOREACH(const datasrc_clientmgr_internal::FinishedCallback&
+ callback, queue) {
+ callback();
+ }
+ }
+
//
// The following are shared with the builder.
//
BuilderType builder_;
ThreadType builder_thread_; // for safety this should be placed last
+ isc::asiolink::LocalSocket wakeup_socket_; // For integration of read_fd_
+ // to the asio loop
+ char buffer[1]; // Buffer for the wakeup socket.
};
namespace datasrc_clientmgr_internal {