Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
b222f7fa
Commit
b222f7fa
authored
Jun 02, 2013
by
Thomas Markwalder
Browse files
[2956] Created the initial, implementation of DHCP-DDNS service controller
class, D2Controller, the base class DControllerBase, and unit tests.
parent
80d16e0d
Changes
17
Hide whitespace changes
Inline
Side-by-side
src/bin/d2/d2_controller.cc
View file @
b222f7fa
// Copyright (C) 201
2
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 201
3
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
());
}
...
...
src/bin/d2/d2_controller.h
View file @
b222f7fa
...
...
@@ -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 D
C
HP-DDNS application process,
/// creates and manages an instance of the DH
C
P-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 applicatio
n
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.
...
...
src/bin/d2/d2_log.cc
View file @
b222f7fa
...
...
@@ -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
...
...
src/bin/d2/d2_log.h
View file @
b222f7fa
...
...
@@ -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
...
...
src/bin/d2/d2_messages.mes
View file @
b222f7fa
...
...
@@ -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.
...
...
src/bin/d2/d2_process.cc
View file @
b222f7fa
...
...
@@ -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
src/bin/d2/d2_process.h
View file @
b222f7fa
...
...
@@ -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
src/bin/d2/d_controller.cc
View file @
b222f7fa
...
...
@@ -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_FAILUR
E
);
return
(
d2
::
INVALID_USAG
E
);
}
#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 init
ialize
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
))
{
//
t
his would be a programmatic err
//
T
his would be a programmatic err
or.
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
// DProcess
Base
Error
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 univer
s
al. 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
);