Commit b222f7fa authored by Thomas Markwalder's avatar Thomas Markwalder

[2956] Created the initial, implementation of DHCP-DDNS service controller

 class, D2Controller, the base class DControllerBase, and unit tests.
parent 80d16e0d
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013 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
......@@ -19,12 +19,12 @@
namespace isc {
namespace d2 {
DControllerBasePtr&
DControllerBasePtr&
D2Controller::instance() {
// If the instance hasn't been created yet, create it. Note this method
// If the instance hasn't been created yet, create it. Note this method
// must use the base class singleton instance methods. The base class
// must own the singleton in order to use it within BIND10 static function
// callbacks.
// callbacks.
if (!getController()) {
setController(new D2Controller());
}
......
......@@ -22,7 +22,7 @@ namespace d2 {
/// @brief Process Controller for D2 Process
/// This class is the DHCP-DDNS specific derivation of DControllerBase. It
/// creates and manages an instance of the DCHP-DDNS application process,
/// creates and manages an instance of the DHCP-DDNS application process,
/// D2Process.
/// @TODO Currently, this class provides only the minimum required specialized
/// behavior to run the DHCP-DDNS service. It may very well expand as the
......@@ -36,7 +36,7 @@ public:
/// base class singleton instance member. It instantiates the singleton
/// and sets the base class instance member upon first invocation.
///
/// @return returns the a pointer reference to the singleton instance.
/// @return returns the pointer reference to the singleton instance.
static DControllerBasePtr& instance();
/// @brief Destructor.
......@@ -47,7 +47,7 @@ private:
/// process. This method is invoked during the process initialization
/// step of the controller launch.
///
/// @return returns a DProcessBase* to the applicatio process created.
/// @return returns a DProcessBase* to the application process created.
/// Note the caller is responsible for destructing the process. This
/// is handled by the base class, which wraps this pointer with a smart
/// pointer.
......
......@@ -19,7 +19,11 @@
namespace isc {
namespace d2 {
/// @brief Defines the service name which is used in the controller constructor
/// and ultimately defines the BIND10 module name.
const char* const D2_MODULE_NAME = "b10-d2";
/// @brief Defines the logger used within D2.
isc::log::Logger d2_logger(D2_MODULE_NAME);
} // namespace d2
......
......@@ -22,7 +22,8 @@
namespace isc {
namespace d2 {
/// @TODO need brief
/// @brief Defines the executable name, ultimately this is the BIND10 module
/// name.
extern const char* const D2_MODULE_NAME;
/// Define the logger for the "d2" module part of b10-d2. We could define
......
......@@ -26,6 +26,10 @@ following a shut down (normal or otherwise) of the DDHCP-DDNS process.
This is a debug message issued when the service process has been instructed
to shut down by the controller.
% D2PRC_PROCESS_INIT DHCP-DDNS application init invoked
This is a debug message issued when the D2 process enters it's
init method.
% D2PRC_RUN_ENTER process has entered the event loop
This is a debug message issued when the D2 process enters it's
run method.
......
......@@ -21,7 +21,7 @@ using namespace asio;
namespace isc {
namespace d2 {
D2Process::D2Process(const char* name, IOServicePtr io_service)
D2Process::D2Process(const char* name, IOServicePtr io_service)
: DProcessBase(name, io_service) {
};
......@@ -29,12 +29,12 @@ void
D2Process::init() {
};
int
void
D2Process::run() {
// Until shut down or an fatal error occurs, wait for and
// execute a single callback. This is a preliminary implementation
// that is likely to evolve as development progresses.
// To use run(), the "managing" layer must issue an io_service::stop
// To use run(), the "managing" layer must issue an io_service::stop
// or the call to run will continue to block, and shutdown will not
// occur.
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_ENTER);
......@@ -44,39 +44,38 @@ D2Process::run() {
io_service->run_one();
} catch (const std::exception& ex) {
LOG_FATAL(d2_logger, D2PRC_FAILED).arg(ex.what());
return (EXIT_FAILURE);
isc_throw (DProcessBaseError,
std::string("Process run method failed:") + ex.what());
}
}
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_EXIT);
return (EXIT_SUCCESS);
};
int
void
D2Process::shutdown() {
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_SHUTDOWN);
setShutdownFlag(true);
return (0);
}
}
isc::data::ConstElementPtr
isc::data::ConstElementPtr
D2Process::configure(isc::data::ConstElementPtr config_set) {
// @TODO This is the initial implementation which simply accepts
// any content in config_set as valid. This is sufficient to
// any content in config_set as valid. This is sufficient to
// allow participation as a BIND10 module, while D2 configuration support
// is being developed.
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
D2PRC_CONFIGURE).arg(config_set->str());
return (isc::config::createAnswer(0, "Configuration accepted."));
}
isc::data::ConstElementPtr
isc::data::ConstElementPtr
D2Process::command(const std::string& command, isc::data::ConstElementPtr args){
// @TODO This is the initial implementation. If and when D2 is extended
// to support its own commands, this implementation must change. Otherwise
// it should reject all commands as it does now.
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
// it should reject all commands as it does now.
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
D2PRC_COMMAND).arg(command).arg(args->str());
return (isc::config::createAnswer(COMMAND_INVALID, "Unrecognized command:"
......@@ -86,5 +85,5 @@ D2Process::command(const std::string& command, isc::data::ConstElementPtr args){
D2Process::~D2Process() {
};
}; // namespace isc::d2
}; // namespace isc::d2
}; // namespace isc
......@@ -20,79 +20,82 @@
namespace isc {
namespace d2 {
/// @brief @TODO DHCP-DDNS Application Process
/// @brief DHCP-DDNS Application Process
///
/// D2Process provides the top level application logic for DHCP-driven DDNS
/// update processing. It provides the asynchronous event processing required
/// to receive DNS mapping change requests and carry them out.
/// D2Process provides the top level application logic for DHCP-driven DDNS
/// update processing. It provides the asynchronous event processing required
/// to receive DNS mapping change requests and carry them out.
/// It implements the DProcessBase interface, which structures it such that it
/// is a managed "application", controlled by a management layer.
/// is a managed "application", controlled by a management layer.
class D2Process : public DProcessBase {
public:
/// @brief Constructor
///
/// @param name name is a text label for the process. Generally used
/// in log statements, but otherwise arbitrary.
/// in log statements, but otherwise arbitrary.
/// @param io_service is the io_service used by the caller for
/// asynchronous event handling.
///
/// @throw DProcessBaseError is io_service is NULL.
/// @throw DProcessBaseError is io_service is NULL.
D2Process(const char* name, IOServicePtr io_service);
/// @brief Will be used after instantiation to perform initialization
/// unique to D2. This will likely include interactions with QueueMgr and
/// UpdateMgr, to prepare for request receipt and processing.
/// @brief Will be used after instantiation to perform initialization
/// unique to D2. @TODO This will likely include interactions with
/// QueueMgr and UpdateMgr, to prepare for request receipt and processing.
/// Current implementation successfully does nothing.
/// @throw throws a DProcessBaseError if the initialization fails.
virtual void init();
/// @brief Implements the process's event loop.
/// The initial implementation is quite basic, surrounding calls to
/// @brief Implements the process's event loop.
/// The initial implementation is quite basic, surrounding calls to
/// io_service->runOne() with a test of the shutdown flag.
/// Once invoked, the method will continue until the process itself is
/// exiting due to a request to shutdown or some anomaly forces an exit.
/// @return returns 0 upon a successful, "normal" termination, non
/// zero to indicate an abnormal termination.
virtual int run();
/// Once invoked, the method will continue until the process itself is
/// exiting due to a request to shutdown or some anomaly forces an exit.
/// @throw throws a DProcessBaseError if an error is encountered.
virtual void run();
// @TODO need brief
virtual int shutdown();
/// @brief Implements the process's shutdown processing. When invoked, it
/// should ensure that the process gracefully exits the run method.
/// Current implementation simply sets the shutdown flag monitored by the
/// run method. @TODO this may need to expand as the implementation evolves.
/// @throw throws a DProcessBaseError if an error is encountered.
virtual void shutdown();
// @TODO need brief
/// @brief Processes the given configuration.
///
/// @brief Processes the given configuration.
///
/// This method may be called multiple times during the process lifetime.
/// Certainly once during process startup, and possibly later if the user
/// alters configuration. This method must not throw, it should catch any
/// processing errors and return a success or failure answer as described
/// below.
/// below.
///
/// @param config_set a new configuration (JSON) for the process
/// @return an Element that contains the results of configuration composed
/// of an integer status value (0 means successful, non-zero means failure),
/// and a string explanation of the outcome.
/// and a string explanation of the outcome.
virtual isc::data::ConstElementPtr configure(isc::data::ConstElementPtr
config_set);
// @TODO need brief
/// @brief Processes the given command.
///
/// This method is called to execute any custom commands supported by the
/// process. This method must not throw, it should catch any processing
/// @brief Processes the given command.
///
/// This method is called to execute any custom commands supported by the
/// process. This method must not throw, it should catch any processing
/// errors and return a success or failure answer as described below.
///
/// @param command is a string label representing the command to execute.
/// @param args is a set of arguments (if any) required for the given
/// command.
/// command.
/// @return an Element that contains the results of command composed
/// of an integer status value (0 means successful, non-zero means failure),
/// and a string explanation of the outcome.
virtual isc::data::ConstElementPtr command(const std::string& command,
/// and a string explanation of the outcome.
virtual isc::data::ConstElementPtr command(const std::string& command,
isc::data::ConstElementPtr args);
// @TODO need brief
/// @brief Destructor
virtual ~D2Process();
};
}; // namespace isc::d2
}; // namespace isc::d2
}; // namespace isc
#endif
......@@ -26,12 +26,12 @@ namespace d2 {
DControllerBasePtr DControllerBase::controller_;
// Note that the constructor instantiates the controller's primary IOService.
DControllerBase::DControllerBase(const char* name)
: name_(name), stand_alone_(false), verbose_(false),
DControllerBase::DControllerBase(const char* name)
: name_(name), stand_alone_(false), verbose_(false),
spec_file_name_(""), io_service_(new isc::asiolink::IOService()){
}
void
void
DControllerBase::setController(DControllerBase* controller) {
if (controller_) {
// This shouldn't happen, but let's make sure it can't be done.
......@@ -45,61 +45,66 @@ DControllerBase::setController(DControllerBase* controller) {
int
DControllerBase::launch(int argc, char* argv[]) {
int ret = EXIT_SUCCESS;
int ret = d2::NORMAL_EXIT;
// Step 1 is to parse the command line arguments.
try {
parseArgs(argc, argv);
} catch (const InvalidUsage& ex) {
usage(ex.what());
return (EXIT_FAILURE);
return (d2::INVALID_USAGE);
}
#if 1
//@TODO During initial development default to max log, no buffer
isc::log::initLogger(name_, isc::log::DEBUG,
isc::log::initLogger(name_, isc::log::DEBUG,
isc::log::MAX_DEBUG_LEVEL, NULL, false);
#else
// Now that we know what the mode flags are, we can init logging.
// If standalone is enabled, do not buffer initial log messages
isc::log::initLogger(name_,
((verbose_ && stand_alone_)
((verbose_ && stand_alone_)
? isc::log::DEBUG : isc::log::INFO),
isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone_);
#endif
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_STARTING).arg(getpid());
try {
// Step 2 is to create and init the application process.
// Step 2 is to create and initialize the application process.
initProcess();
} catch (const std::exception& ex) {
LOG_ERROR(d2_logger, D2CTL_SESSION_FAIL).arg(ex.what());
return (PROCESS_INIT_ERROR);
}
// Next we connect if we are running integrated.
if (!stand_alone_) {
try {
establishSession();
} catch (const std::exception& ex) {
LOG_ERROR(d2_logger, D2CTL_SESSION_FAIL).arg(ex.what());
return (EXIT_FAILURE);
}
} else {
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_STANDALONE);
// Next we connect if we are running integrated.
if (stand_alone_) {
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_STANDALONE);
} else {
try {
establishSession();
} catch (const std::exception& ex) {
LOG_ERROR(d2_logger, D2CTL_SESSION_FAIL).arg(ex.what());
return (d2::SESSION_START_ERROR);
}
}
// Everything is clear for launch, so start the application's
// event loop.
// Everything is clear for launch, so start the application's
// event loop.
try {
runProcess();
} catch (const std::exception& ex) {
LOG_FATAL(d2_logger, D2CTL_FAILED).arg(ex.what());
ret = EXIT_FAILURE;
ret = d2::RUN_ERROR;
}
// If running integrated, always try to disconnect.
if (!stand_alone_) {
try {
try {
disconnectSession();
} catch (const std::exception& ex) {
LOG_ERROR(d2_logger, D2CTL_DISCONNECT_FAIL).arg(ex.what());
ret = EXIT_FAILURE;
ret = d2::SESSION_END_ERROR;
}
}
......@@ -111,11 +116,11 @@ DControllerBase::launch(int argc, char* argv[]) {
void
DControllerBase::parseArgs(int argc, char* argv[])
{
// Iterate over the given command line options. If its a stock option
// Iterate over the given command line options. If its a stock option
// ("s" or "v") handle it here. If its a valid custom option, then
// invoke customOption.
int ch;
opterr = 0;
opterr = 0;
optind = 1;
std::string opts(":vs" + getCustomOpts());
while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
......@@ -139,13 +144,13 @@ DControllerBase::parseArgs(int argc, char* argv[])
isc_throw(InvalidUsage,tmp.str());
break;
}
default:
// We hit a valid custom option
if (!customOption(ch, optarg)) {
// this would be a programmatic err
// This would be a programmatic error.
std::stringstream tmp;
tmp << " Option listed but implemented?: [" <<
tmp << " Option listed but implemented?: [" <<
(char)ch << "] " << (!optarg ? "" : optarg);
isc_throw(InvalidUsage,tmp.str());
}
......@@ -156,12 +161,12 @@ DControllerBase::parseArgs(int argc, char* argv[])
// There was too much information on the command line.
if (argc > optind) {
std::stringstream tmp;
tmp << "extraneous command line information";
tmp << "extraneous command line information";
isc_throw(InvalidUsage,tmp.str());
}
}
bool
bool
DControllerBase::customOption(int /* option */, char* /*optarg*/)
{
// Default implementation returns false.
......@@ -171,26 +176,26 @@ DControllerBase::customOption(int /* option */, char* /*optarg*/)
void
DControllerBase::initProcess() {
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_INIT_PROCESS);
// Invoke virtual method to instantiate the application process.
// Invoke virtual method to instantiate the application process.
try {
process_.reset(createProcess());
process_.reset(createProcess());
} catch (const std::exception& ex) {
isc_throw (DControllerBaseError, std::string("createProcess failed:")
+ ex.what());
+ ex.what());
}
// This is pretty unlikely, but will test for it just to be safe..
if (!process_) {
isc_throw (DControllerBaseError, "createProcess returned NULL");
}
}
// Invoke application's init method
// @TODO This call may throw DProcessError
// Invoke application's init method (Note this call should throw
// DProcessBaseError if it fails).
process_->init();
}
void
void
DControllerBase::establishSession() {
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_CCSESSION_STARTING)
.arg(spec_file_name_);
......@@ -200,13 +205,13 @@ DControllerBase::establishSession() {
io_service_->get_io_service()));
// Create the BIND10 config session with the stub configuration handler.
// This handler is internally invoked by the constructor and on success
// This handler is internally invoked by the constructor and on success
// the constructor updates the current session with the configuration that
// had been committed in the previous session. If we do not install
// the dummy handler, the previous configuration would be lost.
// the dummy handler, the previous configuration would be lost.
config_session_ = ModuleCCSessionPtr(new isc::config::ModuleCCSession(
spec_file_name_, *cc_session_,
dummyConfigHandler, commandHandler,
dummyConfigHandler, commandHandler,
false));
// Enable configuration even processing.
config_session_->start();
......@@ -224,13 +229,13 @@ DControllerBase::establishSession() {
// Parse the answer returned from the configHandler. Log the error but
// keep running. This provides an opportunity for the user to correct
// the configuration dynamically.
int ret = 0;
isc::data::ConstElementPtr comment = isc::config::parseAnswer(ret, answer);
int ret = 0;
isc::data::ConstElementPtr comment = isc::config::parseAnswer(ret, answer);
if (ret) {
LOG_ERROR(d2_logger, D2CTL_CONFIG_LOAD_FAIL).arg(comment->str());
}
// Lastly, call onConnect. This allows deriving class to execute custom
// Lastly, call onConnect. This allows deriving class to execute custom
// logic predicated by session connect.
onSessionConnect();
}
......@@ -243,14 +248,15 @@ DControllerBase::runProcess() {
isc_throw(DControllerBaseError, "Process not initialized");
}
// Invoke the applicatio process's run method. This may throw DProcessError
// Invoke the application process's run method. This may throw
// DProcessBaseError
process_->run();
}
void DControllerBase::disconnectSession() {
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_CCSESSION_ENDING);
// Call virtual onDisconnect. Allows deriving class to execute custom
// Call virtual onDisconnect. Allows deriving class to execute custom
// logic prior to session loss.
onSessionDisconnect();
......@@ -279,7 +285,7 @@ DControllerBase::configHandler(isc::data::ConstElementPtr new_config) {
.arg(new_config->str());
if (!controller_) {
// This should never happen as we install the handler after we
// This should never happen as we install the handler after we
// instantiate the server.
isc::data::ConstElementPtr answer =
isc::config::createAnswer(1, "Configuration rejected,"
......@@ -293,14 +299,14 @@ DControllerBase::configHandler(isc::data::ConstElementPtr new_config) {
// Static callback which invokes non-static handler on singleton
isc::data::ConstElementPtr
DControllerBase::commandHandler(const std::string& command,
DControllerBase::commandHandler(const std::string& command,
isc::data::ConstElementPtr args) {
LOG_DEBUG(d2_logger, DBGLVL_COMMAND, D2CTL_COMMAND_RECEIVED)
.arg(command).arg(args->str());
if (!controller_ ) {
// This should never happen as we install the handler after we
// This should never happen as we install the handler after we
// instantiate the server.
isc::data::ConstElementPtr answer =
isc::config::createAnswer(1, "Command rejected,"
......@@ -315,14 +321,14 @@ DControllerBase::commandHandler(const std::string& command,
isc::data::ConstElementPtr
DControllerBase::updateConfig(isc::data::ConstElementPtr new_config) {
isc::data::ConstElementPtr full_config;
if (stand_alone_) {
if (stand_alone_) {
// @TODO Until there is a configuration manager to provide retrieval
// we'll just assume the incoming config is the full configuration set.
// It may also make more sense to isolate the controller from the
// configuration manager entirely. We could do something like
// process_->getFullConfig() here for stand-alone mode?
full_config = new_config;
} else {
} else {
if (!config_session_) {
// That should never happen as we install config_handler
// after we instantiate the server.
......@@ -343,13 +349,13 @@ DControllerBase::updateConfig(isc::data::ConstElementPtr new_config) {
// be set if the definition of this option is set. If someone removes
// an existing option definition then the partial configuration that
// removes that definition is triggered while a relevant option value
// may remain configured. This eventually results in the
// may remain configured. This eventually results in the
// configuration being in the inconsistent state.
// In order to work around this problem we need to merge the new
// configuration with the existing (full) configuration.
// Let's create a new object that will hold the merged configuration.
boost::shared_ptr<isc::data::MapElement>
boost::shared_ptr<isc::data::MapElement>
merged_config(new isc::data::MapElement());
// Merge an existing and new configuration.
......@@ -362,9 +368,9 @@ DControllerBase::updateConfig(isc::data::ConstElementPtr new_config) {
isc::data::ConstElementPtr
DControllerBase::executeCommand(const std::string& command,
DControllerBase::executeCommand(const std::string& command,
isc::data::ConstElementPtr args) {
// Shutdown is univeral. If its not that, then try it as
// Shutdown is universal. If its not that, then try it as
// an custom command supported by the derivation. If that
// doesn't pan out either, than send to it the application
// as it may be supported there.
......@@ -375,7 +381,7 @@ DControllerBase::executeCommand(const std::string& command,
// It wasn't shutdown, so may be a custom controller command.
int rcode = 0;
answer = customControllerCommand(command, args);
isc::config::parseAnswer(rcode, answer);
isc::config::parseAnswer(rcode, answer);
if (rcode == COMMAND_INVALID)
{
// It wasn't controller command, so may be an application command.
......@@ -387,7 +393,7 @@ DControllerBase::executeCommand(const std::string& command,
}
isc::data::ConstElementPtr
DControllerBase::customControllerCommand(const std::string& command,
DControllerBase::customControllerCommand(const std::string& command,
isc::data::ConstElementPtr /* args */) {
// Default implementation always returns invalid command.
......@@ -395,14 +401,14 @@ DControllerBase::customControllerCommand(const std::string& command,
"Unrecognized command:" + command));
}
isc::data::ConstElementPtr
isc::data::ConstElementPtr
DControllerBase::shutdown() {
// @TODO TKM - not sure about io_service_->stop here
// @TODO (tmark) - not sure about io_service_->stop here
// IF application is using this service for all of its IO, stopping
// here would mean, no more work by the application.. UNLESS it resets
// it. People have discussed letting the application finish any in-progress
// updates before shutting down. If we don't stop it here, then
// application can't use io_service_->run(), it will never "see" the
// updates before shutting down. If we don't stop it here, then
// application can't use io_service_->run(), it will never "see" the
// shutdown.
io_service_->stop();
if (process_) {
......@@ -425,13 +431,10 @@ DControllerBase::usage(const std::string & text)
std::cerr << "Usage: " << name_ << std::endl;
std::cerr << " -v: verbose output" << std::endl;
std::cerr << " -s: stand-alone mode (don't connect to BIND10)"
std::cerr << " -s: stand-alone mode (don't connect to BIND10)"
<< std::endl;
std::cerr << getUsageText() << std::endl;
exit(EXIT_FAILURE);
std::cerr << getUsageText() << std::endl;
}
DControllerBase::~DControllerBase() {
......
......@@ -31,6 +31,23 @@
namespace isc {
namespace d2 {
/// @brief DControllerBase launch exit status values. Upon service shutdown
/// normal or otherwise, the Controller's launch method will return one of
/// these values.
/// @brief Indicates normal shutdown.
static const int NORMAL_EXIT = 0;
/// @brief Indicates invalid command line.
static const int INVALID_USAGE = 1;
/// @brief Failed to create and initialize application process.
static const int PROCESS_INIT_ERROR = 2;
/// @brief Could not connect to BIND10 (integrated mode only).
static const int SESSION_START_ERROR = 3;
/// @brief A fatal error occurred in the application process.
static const int RUN_ERROR = 4;
/// @brief Error occurred disconnecting from BIND10 (integrated mode only).
static const int SESSION_END_ERROR = 5;
/// @brief Exception thrown when the command line is invalid.
class InvalidUsage : public isc::Exception {
public:
......@@ -46,7 +63,7 @@ public:
};
/// @brief Defines a shared pointer to DControllerBaseBase.
/// @brief Defines a shared pointer to DControllerBase.
class DControllerBase;
typedef boost::shared_ptr<DControllerBase> DControllerBasePtr;
......@@ -60,25 +77,25 @@ typedef boost::shared_ptr<isc::config::ModuleCCSession> ModuleCCSessionPtr;
/// @brief Application Controller
///
/// DControllerBase is an abstract singleton which provides the framework and
/// services for managing an application process that implements the
/// DProcessBase interface. It allows the process to run either in
/// services for managing an application process that implements the
/// DProcessBase interface. It allows the process to run either in
/// integrated mode as a BIND10 module or stand-alone. It coordinates command
/// line argument parsing, process instantiation and intialization, and runtime
/// control through external command and configuration event handling.
/// It creates the io_service_ instance which is used for runtime control
/// events and passes the io_service into the application process at process
/// creation. In integrated mode it is responsible for establishing BIND10
/// line argument parsing, process instantiation and initialization, and runtime
/// control through external command and configuration event handling.
/// It creates the io_service_ instance which is used for runtime control
/// events and passes the io_service into the application process at process
/// creation. In integrated mode it is responsible for establishing BIND10
/// session(s) and passes this io_service_ into the session creation method(s).
/// It also provides the callback handlers for command and configuration events.
/// NOTE: Derivations must supply their own static singleton instance method(s)
/// for creating and fetching the instance. The base class declares the instance
/// member in order for it to be available for BIND10 callback functions. This
/// would not be required if BIND10 supported instance method callbacks.
class DControllerBase : public boost::noncopyable {
class DControllerBase : public boost::noncopyable {
public:
/// @brief Constructor
/// @brief Constructor
///
/// @param name name is a text label for the controller. Typically this
/// @param name name is a text label for the controller. Typically this
/// would be the BIND10 module name.
DControllerBase(const char* name);