Commit f9db8f64 authored by Francis Dupont's avatar Francis Dupont

[30-implement-control-socket-for-ddns-2] Added channel management - todo finish new unit tests

parent 96414103
......@@ -55,22 +55,22 @@ D2Controller::registerCommands() {
// These are the commands always supported by the D2 server.
// Please keep the list in alphabetic order.
CommandMgr::instance().registerCommand("build-report",
CommandMgr::instance().registerCommand(BUILD_REPORT_COMMAND,
boost::bind(&D2Controller::buildReportHandler, this, _1, _2));
CommandMgr::instance().registerCommand("config-get",
CommandMgr::instance().registerCommand(CONFIG_GET_COMMAND,
boost::bind(&D2Controller::configGetHandler, this, _1, _2));
CommandMgr::instance().registerCommand("config-test",
CommandMgr::instance().registerCommand(CONFIG_TEST_COMMAND,
boost::bind(&D2Controller::configTestHandler, this, _1, _2));
CommandMgr::instance().registerCommand("config-write",
CommandMgr::instance().registerCommand(CONFIG_WRITE_COMMAND,
boost::bind(&D2Controller::configWriteHandler, this, _1, _2));
CommandMgr::instance().registerCommand("shutdown",
CommandMgr::instance().registerCommand(SHUT_DOWN_COMMAND,
boost::bind(&D2Controller::shutdownHandler, this, _1, _2));
CommandMgr::instance().registerCommand("version-get",
CommandMgr::instance().registerCommand(VERSION_GET_COMMAND,
boost::bind(&D2Controller::versionGetHandler, this, _1, _2));
}
......@@ -81,12 +81,12 @@ D2Controller::deregisterCommands() {
CommandMgr::instance().closeCommandSocket();
// Deregister any registered commands (please keep in alphabetic order)
CommandMgr::instance().deregisterCommand("build-report");
CommandMgr::instance().deregisterCommand("config-get");
CommandMgr::instance().deregisterCommand("config-test");
CommandMgr::instance().deregisterCommand("config-write");
CommandMgr::instance().deregisterCommand("shutdown");
CommandMgr::instance().deregisterCommand("version-get");
CommandMgr::instance().deregisterCommand(BUILD_REPORT_COMMAND);
CommandMgr::instance().deregisterCommand(CONFIG_GET_COMMAND);
CommandMgr::instance().deregisterCommand(CONFIG_TEST_COMMAND);
CommandMgr::instance().deregisterCommand(CONFIG_WRITE_COMMAND);
CommandMgr::instance().deregisterCommand(SHUT_DOWN_COMMAND);
CommandMgr::instance().deregisterCommand(VERSION_GET_COMMAND);
} catch (...) {
// What to do? Simply ignore...
......@@ -110,7 +110,6 @@ D2Controller::parseFile(const std::string& file_name) {
}
D2Controller::~D2Controller() {
deregisterCommands();
}
std::string
......
......@@ -12,6 +12,10 @@
namespace isc {
namespace d2 {
class D2Controller;
/// @brief Pointer to a process controller.
typedef boost::shared_ptr<D2Controller> D2ControllerPtr;
/// @brief Process Controller for D2 Process
/// This class is the DHCP-DDNS specific derivation of DControllerBase. It
/// creates and manages an instance of the DHCP-DDNS application process,
......@@ -46,6 +50,7 @@ public:
void registerCommands();
/// @brief Deregister commands.
/// @note Does not throw.
void deregisterCommands();
protected:
......@@ -77,6 +82,9 @@ private:
/// @brief Constructor is declared private to maintain the integrity of
/// the singleton instance.
D2Controller();
/// To facilitate unit testing.
friend class NakedD2Controller;
};
}; // namespace isc::d2
......
......@@ -7,6 +7,7 @@
#include <config.h>
#include <asiolink/asio_wrapper.h>
#include <cc/command_interpreter.h>
#include <config/command_mgr.h>
#include <d2/d2_log.h>
#include <d2/d2_cfg_mgr.h>
#include <d2/d2_controller.h>
......@@ -23,7 +24,8 @@ const unsigned int D2Process::QUEUE_RESTART_PERCENT = 80;
D2Process::D2Process(const char* name, const asiolink::IOServicePtr& io_service)
: DProcessBase(name, io_service, DCfgMgrBasePtr(new D2CfgMgr())),
reconf_queue_flag_(false), shutdown_type_(SD_NORMAL) {
reconf_queue_flag_(false), reconf_control_socket_flag_(false),
shutdown_type_(SD_NORMAL) {
// Instantiate queue manager. Note that queue manager does not start
// listening at this point. That can only occur after configuration has
......@@ -46,12 +48,19 @@ D2Process::init() {
void
D2Process::run() {
LOG_INFO(d2_logger, DHCP_DDNS_STARTED).arg(VERSION);
D2ControllerPtr controller =
boost::dynamic_pointer_cast<D2Controller>(D2Controller::instance());
try {
// Now logging was initialized so commands can be registered.
boost::dynamic_pointer_cast<D2Controller>(D2Controller::instance())->registerCommands();
controller->registerCommands();
// Loop forever until we are allowed to shutdown.
while (!canShutdown()) {
// Check if the command channel should be (re-)configured.
if (getReconfControlSocketFlag()) {
reconfigureCommandChannel();
}
// Check on the state of the request queue. Take any
// actions necessary regarding it.
checkQueueStatus();
......@@ -65,7 +74,8 @@ D2Process::run() {
// a. NCR message has been received
// b. Transaction IO has completed
// c. Interval timer expired
// d. Something stopped IO service (runIO returns 0)
// d. Control channel event
// e. Something stopped IO service (runIO returns 0)
if (runIO() == 0) {
// Pretty sure this amounts to an unexpected stop and we
// should bail out now. Normal shutdowns do not utilize
......@@ -76,7 +86,7 @@ D2Process::run() {
}
} catch (const std::exception& ex) {
LOG_FATAL(d2_logger, DHCP_DDNS_FAILED).arg(ex.what());
boost::dynamic_pointer_cast<D2Controller>(D2Controller::instance())->deregisterCommands();
controller->deregisterCommands();
isc_throw (DProcessBaseError,
"Process run method failed: " << ex.what());
}
......@@ -85,7 +95,7 @@ D2Process::run() {
// this might be the place to do it, once there is a persistence mgr.
// This may also be better in checkQueueStatus.
boost::dynamic_pointer_cast<D2Controller>(D2Controller::instance())->deregisterCommands();
controller->deregisterCommands();
LOG_DEBUG(d2_logger, isc::log::DBGLVL_START_SHUT, DHCP_DDNS_RUN_EXIT);
......@@ -219,6 +229,7 @@ D2Process::configure(isc::data::ConstElementPtr config_set, bool check_only) {
// action. In integrated mode, this will send a failed response back
// to the configuration backend.
reconf_queue_flag_ = false;
reconf_control_socket_flag_ = false;
return (answer);
}
......@@ -234,6 +245,7 @@ D2Process::configure(isc::data::ConstElementPtr config_set, bool check_only) {
// things that need reconfiguration. It might also be useful if we
// did some analysis to decide what if anything we need to do.)
reconf_queue_flag_ = true;
reconf_control_socket_flag_ = true;
// If we are here, configuration was valid, at least it parsed correctly
// and therefore contained no invalid values.
......@@ -399,5 +411,39 @@ const char* D2Process::getShutdownTypeStr(const ShutdownType& type) {
return (str);
}
void
D2Process::reconfigureCommandChannel() {
reconf_control_socket_flag_ = false;
// Current socket configuration.
static isc::data::ConstElementPtr current_sock_cfg;
// Get new socket configuration.
isc::data::ConstElementPtr sock_cfg = getD2CfgMgr()->getControlSocketInfo();
// Determine if the socket configuration has changed. It has if
// both old and new configuration is specified but respective
// data elements aren't equal.
bool sock_changed = (sock_cfg && current_sock_cfg &&
!sock_cfg->equals(*current_sock_cfg));
// If the previous or new socket configuration doesn't exist or
// the new configuration differs from the old configuration we
// close the existing socket and open a new socket as appropriate.
// Note that closing an existing socket means the client will not
// receive the configuration result.
if (!sock_cfg || !current_sock_cfg || sock_changed) {
// Close the existing socket (if any).
isc::config::CommandMgr::instance().closeCommandSocket();
if (sock_cfg) {
isc::config::CommandMgr::instance().openCommandSocket(sock_cfg);
}
}
// Commit the new socket configuration.
current_sock_cfg = sock_cfg;
}
}; // namespace isc::d2
}; // namespace isc
// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -254,6 +254,15 @@ protected:
shutdown_type_ = value;
}
/// @brief (Re-)Configure the command channel.
///
/// Only close the current channel, if the new channel configuration is
/// different. This avoids disconnecting a client and hence not sending
/// them a command result, unless they specifically alter the channel
/// configuration. In that case the user simply has to accept they'll
/// be disconnected.
void reconfigureCommandChannel();
public:
/// @brief Returns a pointer to the configuration manager.
/// Note, this method cannot return a reference as it uses dynamic
......@@ -275,6 +284,11 @@ public:
return (reconf_queue_flag_);
}
/// @brief Returns true if the control socket should be reconfigured.
bool getReconfControlSocketFlag() const {
return (reconf_control_socket_flag_);
}
/// @brief Returns the type of shutdown requested.
///
/// Note, this value is meaningless unless shouldShutdown() returns true.
......@@ -300,6 +314,9 @@ private:
/// @brief Indicates if the queue manager should be reconfigured.
bool reconf_queue_flag_;
/// @brief Indicates if the control socket should be reconfigured.
bool reconf_control_socket_flag_;
/// @brief Indicates the type of shutdown requested.
ShutdownType shutdown_type_;
};
......
......@@ -58,6 +58,7 @@ d2_unittests_SOURCES += d2_controller_unittests.cc
d2_unittests_SOURCES += d2_simple_parser_unittest.cc
d2_unittests_SOURCES += parser_unittest.cc parser_unittest.h
d2_unittests_SOURCES += get_config_unittest.cc
d2_unittests_SOURCES += d2_command_unittest.cc
d2_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
d2_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS)
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment