BIND 10 master, updated. 270d14dcd9c376ec207f61bb736eb6ef8e9b1a2d [master] Merge of 2956, missed module rename in spec file.

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Jun 7 12:39:07 UTC 2013


The branch, master has been updated
       via  270d14dcd9c376ec207f61bb736eb6ef8e9b1a2d (commit)
       via  a41cac582e46213c120b19928e4162535ba5fe76 (commit)
       via  3511d115d6565b995ec092037359933eecb7c704 (commit)
       via  031ae7d0a205b4a82593ba4767e8e4741b3f8081 (commit)
       via  21f3ea90672b5bf84886e58f08f97bbcc63dfd6d (commit)
       via  b222f7faadc7ed7898a936a2b97b2a385c6a2a1b (commit)
       via  80d16e0dfbaeb8053cbd29d6b0512d75351a2c25 (commit)
       via  fd911f4775865a204a9a67dfcf290d8395e0734d (commit)
      from  31a77cdd4fb12c30e9222e9e045fb998487b0844 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 270d14dcd9c376ec207f61bb736eb6ef8e9b1a2d
Author: Thomas Markwalder <tmark at isc.org>
Date:   Fri Jun 7 08:36:25 2013 -0400

    [master] Merge of 2956, missed module rename in spec file.

commit a41cac582e46213c120b19928e4162535ba5fe76
Merge: 31a77cd 3511d11
Author: Thomas Markwalder <tmark at isc.org>
Date:   Fri Jun 7 06:30:27 2013 -0400

    [master] Merge branch 2956 which adds DControllerBase and D2Controller
    classes to bin/src/D2.

-----------------------------------------------------------------------

Summary of changes:
 src/bin/d2/Makefile.am                       |   36 +-
 src/bin/d2/{b10-d2.xml => b10-dhcp-ddns.xml} |   22 +-
 src/bin/d2/d2.spec                           |   21 --
 src/bin/d2/d2_controller.cc                  |   58 +++
 src/bin/d2/d2_controller.h                   |   64 ++++
 src/bin/d2/d2_log.cc                         |    7 +-
 src/bin/d2/d2_log.h                          |    5 +
 src/bin/d2/d2_messages.mes                   |   68 +++-
 src/bin/d2/d2_process.cc                     |   32 +-
 src/bin/d2/d2_process.h                      |   71 ++--
 src/bin/d2/d_controller.cc                   |  427 +++++++++++++++++++++
 src/bin/d2/d_controller.h                    |  524 ++++++++++++++++++++++++++
 src/bin/d2/d_process.h                       |  130 ++++---
 src/bin/d2/dhcp-ddns.spec                    |   21 ++
 src/bin/d2/main.cc                           |   89 ++---
 src/bin/d2/spec_config.h.pre.in              |    2 +-
 src/bin/d2/tests/Makefile.am                 |    7 +-
 src/bin/d2/tests/d2_controller_unittests.cc  |  216 +++++++++++
 src/bin/d2/tests/d2_process_unittests.cc     |   48 ++-
 src/bin/d2/tests/d2_test.py                  |    3 +-
 src/bin/d2/tests/d_controller_unittests.cc   |  361 ++++++++++++++++++
 src/bin/d2/tests/d_test_stubs.cc             |  202 ++++++++++
 src/bin/d2/tests/d_test_stubs.h              |  422 +++++++++++++++++++++
 23 files changed, 2586 insertions(+), 250 deletions(-)
 rename src/bin/d2/{b10-d2.xml => b10-dhcp-ddns.xml} (76%)
 delete mode 100644 src/bin/d2/d2.spec
 create mode 100644 src/bin/d2/d2_controller.cc
 create mode 100644 src/bin/d2/d2_controller.h
 create mode 100644 src/bin/d2/d_controller.cc
 create mode 100644 src/bin/d2/d_controller.h
 create mode 100644 src/bin/d2/dhcp-ddns.spec
 create mode 100644 src/bin/d2/tests/d2_controller_unittests.cc
 create mode 100644 src/bin/d2/tests/d_controller_unittests.cc
 create mode 100644 src/bin/d2/tests/d_test_stubs.cc
 create mode 100644 src/bin/d2/tests/d_test_stubs.h

-----------------------------------------------------------------------
diff --git a/src/bin/d2/Makefile.am b/src/bin/d2/Makefile.am
index 8829764..7cf3019 100644
--- a/src/bin/d2/Makefile.am
+++ b/src/bin/d2/Makefile.am
@@ -18,15 +18,15 @@ pkglibexecdir = $(libexecdir)/@PACKAGE@
 
 CLEANFILES  = *.gcno *.gcda spec_config.h d2_messages.h d2_messages.cc
 
-man_MANS = b10-d2.8
+man_MANS = b10-dhcp-ddns.8
 DISTCLEANFILES = $(man_MANS)
-EXTRA_DIST = $(man_MANS) b10-d2.xml d2.spec
+EXTRA_DIST = $(man_MANS) b10-dhcp-ddns.xml dhcp-ddns.spec
 
 if GENERATE_DOCS
-b10-d2.8: b10-d2.xml
+b10-dhcp-ddns.8: b10-dhcp-ddns.xml
 	@XSLTPROC@ --novalid --xinclude --nonet -o $@ \
         http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl \
-	$(srcdir)/b10-d2.xml
+	$(srcdir)/b10-dhcp-ddns.xml
 
 else
 
@@ -44,21 +44,23 @@ d2_messages.h d2_messages.cc: d2_messages.mes
 
 BUILT_SOURCES = spec_config.h d2_messages.h d2_messages.cc
 
-pkglibexec_PROGRAMS = b10-d2
+pkglibexec_PROGRAMS = b10-dhcp-ddns
 
-b10_d2_SOURCES  = main.cc
-b10_d2_SOURCES += d2_log.cc d2_log.h
-b10_d2_SOURCES += d_process.h 
-b10_d2_SOURCES += d2_process.cc d2_process.h
+b10_dhcp_ddns_SOURCES  = main.cc
+b10_dhcp_ddns_SOURCES += d2_log.cc d2_log.h
+b10_dhcp_ddns_SOURCES += d_process.h
+b10_dhcp_ddns_SOURCES += d2_process.cc d2_process.h
+b10_dhcp_ddns_SOURCES += d_controller.cc d_controller.h
+b10_dhcp_ddns_SOURCES += d2_controller.cc d2_controller.h
 
-nodist_b10_d2_SOURCES = d2_messages.h d2_messages.cc
+nodist_b10_dhcp_ddns_SOURCES = d2_messages.h d2_messages.cc
 EXTRA_DIST += d2_messages.mes
 
-b10_d2_LDADD = $(top_builddir)/src/lib/log/libb10-log.la
-b10_d2_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
-b10_d2_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
-b10_d2_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
-b10_d2_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
+b10_dhcp_ddns_LDADD = $(top_builddir)/src/lib/log/libb10-log.la
+b10_dhcp_ddns_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
+b10_dhcp_ddns_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
+b10_dhcp_ddns_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
+b10_dhcp_ddns_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
 
-b10_d2dir = $(pkgdatadir)
-b10_d2_DATA = d2.spec
+b10_dhcp_ddnsdir = $(pkgdatadir)
+b10_dhcp_ddns_DATA = dhcp-ddns.spec
diff --git a/src/bin/d2/b10-d2.xml b/src/bin/d2/b10-d2.xml
deleted file mode 100644
index 2202685..0000000
--- a/src/bin/d2/b10-d2.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	       [<!ENTITY mdash "—">]>
-<!--
- - 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
- - 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.
--->
-
-<refentry>
-
-  <refentryinfo>
-    <date>May 15, 2013</date>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>b10-d2</refentrytitle>
-    <manvolnum>8</manvolnum>
-    <refmiscinfo>BIND10</refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>b10-d2</refname>
-    <refpurpose>D2 process in BIND 10 architecture</refpurpose>
-  </refnamediv>
-
-  <docinfo>
-    <copyright>
-      <year>2013</year>
-      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
-    </copyright>
-  </docinfo>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>b10-d2</command>
-      <arg><option>-v</option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>b10-d2</command>
-      <arg><option>-s</option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-
-  <refsect1>
-    <title>DESCRIPTION</title>
-    <para>
-      The <command>b10-d2</command> daemon processes requests to
-      to update DNS mapping based on DHCP lease change events.
-    </para>
-
-  </refsect1>
-
-  <refsect1>
-    <title>ARGUMENTS</title>
-
-    <para>The arguments are as follows:</para>
-
-    <variablelist>
-
-      <varlistentry>
-        <term><option>-v</option></term>
-        <listitem><para>
-          Verbose mode sets the logging level to debug. This is primarily
-          for development purposes in stand-alone mode.
-        </para></listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-s</option></term>
-        <listitem><para>
-          Causes the process to run without attempting to connect to the
-          BIND10 message queue.  This is for development purposes.
-        </para></listitem>
-      </varlistentry>
-
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>b10-d2</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>HISTORY</title>
-    <para>
-      The <command>b10-d2</command> process was first coded in
-      May 2013 by the ISC Kea/Dhcp team.
-    </para>
-  </refsect1>
-</refentry><!--
- - Local variables:
- - mode: sgml
- - End:
--->
diff --git a/src/bin/d2/b10-dhcp-ddns.xml b/src/bin/d2/b10-dhcp-ddns.xml
new file mode 100644
index 0000000..b77ff17
--- /dev/null
+++ b/src/bin/d2/b10-dhcp-ddns.xml
@@ -0,0 +1,121 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+	       [<!ENTITY mdash "—">]>
+<!--
+ - 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
+ - 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.
+-->
+
+<refentry>
+
+  <refentryinfo>
+    <date>May 15, 2013</date>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>b10-dhcp-ddns</refentrytitle>
+    <manvolnum>8</manvolnum>
+    <refmiscinfo>BIND10</refmiscinfo>
+  </refmeta>
+
+  <refnamediv>
+    <refname>b10-dhcp-ddns</refname>
+    <refpurpose>DHCP-DDNS process in BIND 10 architecture</refpurpose>
+  </refnamediv>
+
+  <docinfo>
+    <copyright>
+      <year>2013</year>
+      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+    </copyright>
+  </docinfo>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>b10-dhcp-ddns</command>
+      <arg><option>-v</option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>b10-dhcp-ddns</command>
+      <arg><option>-s</option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+
+  <refsect1>
+    <title>DESCRIPTION</title>
+    <para>
+      The <command>b10-dhcp-ddns</command> service processes requests to
+      to update DNS mapping based on DHCP lease change events. The service
+      may run either as a BIND10 module (integrated mode) or as a individual
+      process (stand-alone mode) dependent upon command line arguments. The
+      default is integrated mode.  Stand alone operation is strictly for
+      development purposes and is not suited for production.
+    </para>
+
+  </refsect1>
+
+  <refsect1>
+    <title>ARGUMENTS</title>
+
+    <para>The arguments are as follows:</para>
+
+    <variablelist>
+
+      <varlistentry>
+        <term><option>-v</option></term>
+        <listitem><para>
+          Verbose mode sets the logging level to debug. This is primarily
+          for development purposes in stand-alone mode.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-s</option></term>
+        <listitem><para>
+          Causes the process to run without attempting to connect to the
+          BIND10 message queue.  This is for development purposes.
+        </para></listitem>
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>SEE ALSO</title>
+    <para>
+      <citerefentry>
+        <refentrytitle>b10-dhcp-ddns</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
+        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>HISTORY</title>
+    <para>
+      The <command>b10-dhcp-ddns</command> process was first coded in
+      May 2013 by the ISC Kea/Dhcp team.
+    </para>
+  </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/src/bin/d2/d2.spec b/src/bin/d2/d2.spec
deleted file mode 100644
index 63afb7a..0000000
--- a/src/bin/d2/d2.spec
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "module_spec": {
-    "module_name": "D2",
-    "module_description": "DHCP-DDNS process",
-    "config_data": [
-    ],
-    "commands": [
-        {
-            "command_name": "shutdown",
-            "command_description": "Shuts down the D2 process.",
-            "command_args": [
-                {
-                    "item_name": "pid",
-                    "item_type": "integer",
-                    "item_optional": true
-                }
-            ]
-        }
-    ]
-  }
-}
diff --git a/src/bin/d2/d2_controller.cc b/src/bin/d2/d2_controller.cc
new file mode 100644
index 0000000..0200b64
--- /dev/null
+++ b/src/bin/d2/d2_controller.cc
@@ -0,0 +1,58 @@
+// 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
+// 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.
+
+#include <d2/d2_controller.h>
+#include <d2/d2_process.h>
+#include <d2/spec_config.h>
+
+namespace isc {
+namespace d2 {
+
+DControllerBasePtr&
+D2Controller::instance() {
+    // 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 have access to the singleton in order to use it within BIND10 
+    // static function callbacks.
+    if (!getController()) {
+        DControllerBasePtr controller_ptr(new D2Controller());
+        setController(controller_ptr);
+    }
+
+    return (getController());
+}
+
+DProcessBase* D2Controller::createProcess() {
+    // Instantiate and return an instance of the D2 application process. Note
+    // that the process is passed the controller's io_service.
+    return (new D2Process(getName().c_str(), getIOService()));
+}
+
+D2Controller::D2Controller()
+    : DControllerBase(D2_MODULE_NAME) {
+    // set the BIND10 spec file either from the environment or
+    // use the production value.
+    if (getenv("B10_FROM_BUILD")) {
+        setSpecFileName(std::string(getenv("B10_FROM_BUILD")) +
+            "/src/bin/d2/dhcp-ddns.spec");
+    } else {
+        setSpecFileName(D2_SPECFILE_LOCATION);
+    }
+}
+
+D2Controller::~D2Controller() {
+}
+
+}; // end namespace isc::d2
+}; // end namespace isc
diff --git a/src/bin/d2/d2_controller.h b/src/bin/d2/d2_controller.h
new file mode 100644
index 0000000..46a24ef
--- /dev/null
+++ b/src/bin/d2/d2_controller.h
@@ -0,0 +1,64 @@
+// 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
+// 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 D2_CONTROLLER_H
+#define D2_CONTROLLER_H
+
+#include <d2/d_controller.h>
+
+namespace isc {
+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 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 
+/// service implementation evolves.  Some thought was given to making 
+/// DControllerBase a templated class but the labor savings versus the
+/// potential number of virtual methods which may be overridden didn't seem
+/// worth the clutter at this point. 
+class D2Controller : public DControllerBase {
+public:
+    /// @brief Static singleton instance method. This method returns the
+    /// base class singleton instance member.  It instantiates the singleton 
+    /// and sets the base class instance member upon first invocation. 
+    ///
+    /// @return returns the pointer reference to the singleton instance.
+    static DControllerBasePtr& instance();
+
+    /// @brief Destructor.
+    virtual ~D2Controller();
+
+private:
+    /// @brief Creates an instance of the DHCP-DDNS specific application 
+    /// process.  This method is invoked during the process initialization
+    /// step of the controller launch.
+    ///  
+    /// @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.
+    virtual DProcessBase* createProcess();
+
+    /// @brief Constructor is declared private to maintain the integrity of
+    /// the singleton instance.
+    D2Controller();
+};
+
+}; // namespace isc::d2
+}; // namespace isc
+
+#endif
diff --git a/src/bin/d2/d2_log.cc b/src/bin/d2/d2_log.cc
index 37289e1..96803d8 100644
--- a/src/bin/d2/d2_log.cc
+++ b/src/bin/d2/d2_log.cc
@@ -19,7 +19,12 @@
 namespace isc {
 namespace d2 {
 
-isc::log::Logger d2_logger("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-dhpc-ddns";
+
+/// @brief Defines the logger used within D2.
+isc::log::Logger d2_logger(D2_MODULE_NAME);
 
 } // namespace d2
 } // namespace isc
diff --git a/src/bin/d2/d2_log.h b/src/bin/d2/d2_log.h
index 2ddfe5c..bb95a2b 100644
--- a/src/bin/d2/d2_log.h
+++ b/src/bin/d2/d2_log.h
@@ -22,12 +22,17 @@
 namespace isc {
 namespace d2 {
 
+/// @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
 /// a logger in each file, but we would want to define a common name to avoid
 /// spelling mistakes, so it is just one small step from there to define a
 /// module-common logger.
 extern isc::log::Logger d2_logger;
 
+
 } // namespace d2
 } // namespace isc
 
diff --git a/src/bin/d2/d2_messages.mes b/src/bin/d2/d2_messages.mes
index 804b2cb..82430a5 100644
--- a/src/bin/d2/d2_messages.mes
+++ b/src/bin/d2/d2_messages.mes
@@ -15,19 +15,23 @@
 $NAMESPACE isc::d2
 
 % D2CTL_STARTING DHCP-DDNS controller starting, pid: %1
-This is an informational message issued when controller for DHCP-DDNS 
+This is an informational message issued when controller for DHCP-DDNS
 service first starts.
 
 % D2CTL_STOPPING DHCP-DDNS controller is exiting
-This is an informational message issued when the controller is exiting 
+This is an informational message issued when the controller is exiting
 following a shut down (normal or otherwise) of the DDHCP-DDNS process.
 
 % D2PRC_SHUTDOWN DHCP-DDNS process is performing a normal shut down
 This is a debug message issued when the service process has been instructed
 to shut down by the controller.
 
-% D2PRC_RUN_ENTER process has entered the event loop
-This is a debug message issued when the D2 process enters it's
+% D2PRC_PROCESS_INIT DHCP-DDNS application init invoked
+This is a debug message issued when the D2 process enters its
+init method. 
+
+% D2PRC_RUN_ENTER process has entered the event loop 
+This is a debug message issued when the D2 process enters its
 run method. 
 
 % D2PRC_RUN_EXIT process is exiting the event loop
@@ -46,3 +50,59 @@ has been invoked.
 This is a debug message issued when the D2 process command method
 has been invoked.
 
+% D2CTL_INIT_PROCESS initializing application proces 
+This debug message is issued just before the controller attempts
+to create and initialize its process instance.
+
+% D2CTL_SESSION_FAIL failed to establish BIND 10 session: %1
+The controller has failed to establish communication with the rest of BIND
+10 and will exit. 
+
+% D2CTL_DISCONNECT_FAIL failed to disconnect from BIND 10 session: %1
+This message indicates that while shutting down, the DHCP-DDNS controller 
+encountered an error terminating communication with the BIND10. The service 
+will still exit.  While theoretically possible, this situation is rather 
+unlikely. 
+
+% D2CTL_STANDALONE skipping message queue, running standalone
+This is a debug message indicating that the controller is running in the
+process in standalone mode. This means it will not connected to the BIND10 
+message queue. Standalone mode is only useful during program development, 
+and should not be used in a production environment.
+
+% D2CTL_RUN_PROCESS starting application proces event loop 
+This debug message is issued just before the controller invokes 
+the application process run method.
+
+% D2CTL_FAILED process failed: %1
+The controller has encountered a fatal error and is terminating.
+The reason for the failure is included in the message.
+
+% D2CTL_CCSESSION_STARTING starting control channel session, specfile: %1
+This debug message is issued just before the controller attempts
+to establish a session with the BIND 10 control channel.
+
+% D2CTL_CCSESSION_ENDING ending control channel session
+This debug message is issued just before the controller attempts
+to disconnect from its session with the BIND 10 control channel.
+
+% D2CTL_CONFIG_STUB configuration stub handler called 
+This debug message is issued when the dummy handler for configuration
+events is called.  This only happens during intial startup.
+
+% D2CTL_CONFIG_LOAD_FAIL failed to load configuration: %1
+This critical error message indicates that the initial process 
+configuration has failed. The service will start, but will not
+process requests until the configuration has been corrected.
+
+% D2CTL_COMMAND_RECEIVED received command %1, arguments: %2
+A debug message listing the command (and possible arguments) received
+from the BIND 10 control system by the controller.
+
+% D2CTL_NOT_RUNNING The application process instance is not running
+A warning message is issued when an attempt is made to shut down the
+the process when it is not running.
+
+% D2CTL_CONFIG_UPDATE updated configuration received: %1
+A debug message indicating that the controller has received an
+updated configuration from the BIND 10 configuration system.
diff --git a/src/bin/d2/d2_process.cc b/src/bin/d2/d2_process.cc
index 4fd420b..64eea72 100644
--- a/src/bin/d2/d2_process.cc
+++ b/src/bin/d2/d2_process.cc
@@ -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,46 +44,46 @@ 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,
+                       "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(1, "Unrecognized command:" + command));
+    return (isc::config::createAnswer(COMMAND_INVALID, "Unrecognized command: "
+                                      + command));
 }
 
 D2Process::~D2Process() {
 };
 
-}; // namespace isc::d2 
+}; // namespace isc::d2
 }; // namespace isc
diff --git a/src/bin/d2/d2_process.h b/src/bin/d2/d2_process.h
index 4d6d36b..4ddf8be 100644
--- a/src/bin/d2/d2_process.h
+++ b/src/bin/d2/d2_process.h
@@ -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
diff --git a/src/bin/d2/d_controller.cc b/src/bin/d2/d_controller.cc
new file mode 100644
index 0000000..2487f2d
--- /dev/null
+++ b/src/bin/d2/d_controller.cc
@@ -0,0 +1,427 @@
+// 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
+// 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.
+
+
+#include <d2/d2_log.h>
+#include <d2/d_controller.h>
+#include <exceptions/exceptions.h>
+#include <log/logger_support.h>
+
+#include <sstream>
+
+namespace isc {
+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),
+    spec_file_name_(""), io_service_(new isc::asiolink::IOService()){
+}
+
+void
+DControllerBase::setController(const DControllerBasePtr& controller) {
+    if (controller_) {
+        // This shouldn't happen, but let's make sure it can't be done.
+        // It represents a programmatic error.
+        isc_throw (DControllerBaseError,
+                "Multiple controller instances attempted.");
+    }
+
+    controller_ = controller;
+}
+
+void
+DControllerBase::launch(int argc, char* argv[]) {
+    // Step 1 is to parse the command line arguments.
+    try {
+        parseArgs(argc, argv);
+    } catch (const InvalidUsage& ex) {
+        usage(ex.what());
+        throw; // rethrow it
+    }
+
+    // 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_)
+                          ? isc::log::DEBUG : isc::log::INFO),
+                         isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone_);
+
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_STARTING).arg(getpid());
+    try {
+        // Step 2 is to create and initialize the application process object.
+        initProcess();
+    } catch (const std::exception& ex) {
+        LOG_FATAL(d2_logger, D2CTL_INIT_PROCESS).arg(ex.what());
+        isc_throw (ProcessInitError, 
+                   "Application Process initialization failed: " << ex.what());
+    }
+
+    // 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_FATAL(d2_logger, D2CTL_SESSION_FAIL).arg(ex.what());
+            isc_throw (SessionStartError, 
+                       "Session start up failed: " << ex.what());
+        }
+    }
+
+    // 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());
+        isc_throw (ProcessRunError, 
+                   "Application process event loop failed: " << ex.what());
+    }
+
+    // If running integrated, disconnect.
+    if (!stand_alone_) {
+        try {
+            disconnectSession();
+        } catch (const std::exception& ex) {
+            LOG_ERROR(d2_logger, D2CTL_DISCONNECT_FAIL).arg(ex.what());
+            isc_throw (SessionEndError, "Session end failed: " << ex.what());
+        }
+    }
+
+    // All done, so bail out.
+    LOG_INFO(d2_logger, D2CTL_STOPPING);
+}
+
+
+void
+DControllerBase::parseArgs(int argc, char* argv[])
+{
+    // 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;
+    optind = 1;
+    std::string opts(":vs" + getCustomOpts());
+    while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
+        switch (ch) {
+        case 'v':
+            // Enables verbose logging.
+            verbose_ = true;
+            break;
+
+        case 's':
+            // Enables stand alone or "BINDLESS" operation.
+            stand_alone_ = true;
+            break;
+
+        case '?': {
+            // We hit an invalid option.
+            isc_throw(InvalidUsage, "unsupported option: [" 
+                      << static_cast<char>(optopt) << "] "
+                      << (!optarg ? "" : optarg));
+
+            break;
+            }
+
+        default:
+            // We hit a valid custom option
+            if (!customOption(ch, optarg)) {
+                // This would be a programmatic error.
+                isc_throw(InvalidUsage, " Option listed but implemented?: [" 
+                          << static_cast<char>(ch) << "] "
+                          << (!optarg ? "" : optarg));
+            }
+            break;
+        }
+    }
+
+    // There was too much information on the command line.
+    if (argc > optind) {
+        isc_throw(InvalidUsage, "extraneous command line information");
+    }
+}
+
+bool
+DControllerBase::customOption(int /* option */, char* /*optarg*/)
+{
+    // Default implementation returns false.
+    return (false);
+}
+
+void
+DControllerBase::initProcess() {
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_INIT_PROCESS);
+
+    // Invoke virtual method to instantiate the application process.
+    try {
+        process_.reset(createProcess());
+    } catch (const std::exception& ex) {
+        isc_throw(DControllerBaseError, std::string("createProcess failed: ")
+                  + 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 (Note this call should throw
+    // DProcessBaseError if it fails).
+    process_->init();
+}
+
+void
+DControllerBase::establishSession() {
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_CCSESSION_STARTING)
+              .arg(spec_file_name_);
+
+    // Create the BIND10 command control session with the our IOService.
+    cc_session_ = SessionPtr(new isc::cc::Session(
+                             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
+    // 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.
+    config_session_ = ModuleCCSessionPtr(new isc::config::ModuleCCSession(
+                                         spec_file_name_, *cc_session_,
+                                         dummyConfigHandler, commandHandler,
+                                         false));
+    // Enable configuration even processing.
+    config_session_->start();
+
+    // We initially create ModuleCCSession() with a dummy configHandler, as
+    // the session module is too eager to send partial configuration.
+    // Replace the dummy config handler with the real handler.
+    config_session_->setConfigHandler(configHandler);
+
+    // Call the real configHandler with the full configuration retrieved
+    // from the config session.
+    isc::data::ConstElementPtr answer = configHandler(
+                                            config_session_->getFullConfig());
+
+    // 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);
+    if (ret) {
+        LOG_ERROR(d2_logger, D2CTL_CONFIG_LOAD_FAIL).arg(comment->str());
+    }
+
+    // Lastly, call onConnect. This allows deriving class to execute custom
+    // logic predicated by session connect.
+    onSessionConnect();
+}
+
+void
+DControllerBase::runProcess() {
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_RUN_PROCESS);
+    if (!process_) {
+        // This should not be possible.
+        isc_throw(DControllerBaseError, "Process not initialized");
+    }
+
+    // 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
+    // logic prior to session loss.
+    onSessionDisconnect();
+
+    // Destroy the BIND10 config session.
+    if (config_session_) {
+        config_session_.reset();
+    }
+
+    // Destroy the BIND10 command and control session.
+    if (cc_session_) {
+        cc_session_->disconnect();
+        cc_session_.reset();
+    }
+}
+
+isc::data::ConstElementPtr
+DControllerBase::dummyConfigHandler(isc::data::ConstElementPtr) {
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2CTL_CONFIG_STUB);
+    return (isc::config::createAnswer(0, "Configuration accepted."));
+}
+
+isc::data::ConstElementPtr
+DControllerBase::configHandler(isc::data::ConstElementPtr new_config) {
+
+    LOG_DEBUG(d2_logger, DBGLVL_COMMAND, D2CTL_CONFIG_UPDATE)
+            .arg(new_config->str());
+
+    if (!controller_) {
+        // This should never happen as we install the handler after we
+        // instantiate the server.
+        isc::data::ConstElementPtr answer =
+            isc::config::createAnswer(1, "Configuration rejected,"
+                                   " Controller has not been initialized.");
+        return (answer);
+    }
+
+    // Invoke the instance method on the controller singleton.
+    return (controller_->updateConfig(new_config));
+}
+
+// Static callback which invokes non-static handler on singleton
+isc::data::ConstElementPtr
+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
+        // instantiate the server.
+        isc::data::ConstElementPtr answer =
+            isc::config::createAnswer(1, "Command rejected,"
+                                   " Controller has not been initialized.");
+        return (answer);
+    }
+
+    // Invoke the instance method on the controller singleton.
+    return (controller_->executeCommand(command, args));
+}
+
+isc::data::ConstElementPtr
+DControllerBase::updateConfig(isc::data::ConstElementPtr new_config) {
+    isc::data::ConstElementPtr full_config;
+    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 {
+        if (!config_session_) {
+            // That should never happen as we install config_handler
+            // after we instantiate the server.
+            isc::data::ConstElementPtr answer =
+                    isc::config::createAnswer(1, "Configuration rejected,"
+                                              " Session has not started.");
+            return (answer);
+        }
+
+        // Let's get the existing configuration.
+        full_config = config_session_->getFullConfig();
+    }
+
+    // The configuration passed to this handler function is partial.
+    // In other words, it just includes the values being modified.
+    // In the same time, there may be dependencies between various
+    // configuration parsers. For example: the option value can
+    // 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
+    // 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>
+                            merged_config(new isc::data::MapElement());
+
+    // Merge an existing and new configuration.
+    merged_config->setValue(full_config->mapValue());
+    isc::data::merge(merged_config, new_config);
+
+    // Send the merged configuration to the application.
+    return (process_->configure(merged_config));
+}
+
+
+isc::data::ConstElementPtr
+DControllerBase::executeCommand(const std::string& command,
+                            isc::data::ConstElementPtr args) {
+    // 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.
+    isc::data::ConstElementPtr answer;
+    if (command.compare(SHUT_DOWN_COMMAND) == 0) {
+        answer = shutdown();
+    } else {
+        // It wasn't shutdown, so may be a custom controller command.
+        int rcode = 0;
+        answer = customControllerCommand(command, args);
+        isc::config::parseAnswer(rcode, answer);
+        if (rcode == COMMAND_INVALID)
+        {
+            // It wasn't controller command, so may be an application command.
+            answer = process_->command(command,args);
+        }
+    }
+
+    return (answer);
+}
+
+isc::data::ConstElementPtr
+DControllerBase::customControllerCommand(const std::string& command,
+                                     isc::data::ConstElementPtr /* args */) {
+
+    // Default implementation always returns invalid command.
+    return (isc::config::createAnswer(COMMAND_INVALID,
+                                      "Unrecognized command: " + command));
+}
+
+isc::data::ConstElementPtr
+DControllerBase::shutdown() {
+    if (process_) {
+        process_->shutdown();
+    } else {
+        // Not really a failure, but this condition is worth noting. In reality
+        // it should be pretty hard to cause this.
+        LOG_WARN(d2_logger, D2CTL_NOT_RUNNING);
+    }
+
+    return (isc::config::createAnswer(0, "Shutting down."));
+}
+
+void
+DControllerBase::usage(const std::string & text)
+{
+    if (text != "") {
+        std::cerr << "Usage error: " << text << std::endl;
+    }
+
+    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::endl;
+
+    std::cerr << getUsageText() << std::endl;
+}
+
+DControllerBase::~DControllerBase() {
+}
+
+}; // namespace isc::d2
+}; // namespace isc
diff --git a/src/bin/d2/d_controller.h b/src/bin/d2/d_controller.h
new file mode 100644
index 0000000..05971fd
--- /dev/null
+++ b/src/bin/d2/d_controller.h
@@ -0,0 +1,524 @@
+// 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
+// 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 D_CONTROLLER_H
+#define D_CONTROLLER_H
+
+#include <asiolink/asiolink.h>
+#include <cc/data.h>
+#include <cc/session.h>
+#include <config/ccsession.h>
+#include <d2/d2_log.h>
+#include <d2/d_process.h>
+#include <exceptions/exceptions.h>
+#include <log/logger_support.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+
+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 Exception thrown when the command line is invalid.
+class InvalidUsage : public isc::Exception {
+public:
+    InvalidUsage(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+/// @brief Exception thrown when the application process fails.
+class ProcessInitError: public isc::Exception {
+public:
+    ProcessInitError (const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+/// @brief Exception thrown when the session start up fails.
+class SessionStartError: public isc::Exception {
+public:
+    SessionStartError (const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+/// @brief Exception thrown when the application process encounters an 
+/// operation in its event loop (i.e. run method).
+class ProcessRunError: public isc::Exception {
+public:
+    ProcessRunError (const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+/// @brief Exception thrown when the session end fails.
+class SessionEndError: public isc::Exception {
+public:
+    SessionEndError (const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+
+/// @brief Exception thrown when the controller encounters an operational error.
+class DControllerBaseError : public isc::Exception {
+public:
+    DControllerBaseError (const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+
+/// @brief Defines a shared pointer to DControllerBase.
+class DControllerBase;
+typedef boost::shared_ptr<DControllerBase> DControllerBasePtr;
+
+/// @brief Defines a shared pointer to a Session.
+typedef boost::shared_ptr<isc::cc::Session> SessionPtr;
+
+/// @brief Defines a shared pointer to a ModuleCCSession.
+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
+/// integrated mode as a BIND10 module or stand-alone. It coordinates command
+/// line argument parsing, process instantiation and initialization, and runtime
+/// control through external command and configuration event handling.
+/// It creates the IOService instance which is used for runtime control
+/// events and passes the IOService into the application process at process
+/// creation.  In integrated mode it is responsible for establishing BIND10
+/// session(s) and passes this IOService into the session creation method(s).
+/// It also provides the callback handlers for command and configuration events
+/// received from the external framework (aka BIND10).  For example, when 
+/// running in integrated mode and a user alters the configuration with the
+/// bindctl tool, BIND10 will emit a configuration message which is sensed by
+/// the controller's IOService. The IOService in turn invokes the configuration
+/// callback, DControllerBase::configHandler().  If the user issues a command
+/// such as shutdown via bindctl,  BIND10 will emit a command message, which is
+/// sensed by controller's IOService which invokes the command callback, 
+/// DControllerBase::commandHandler().
+///
+/// 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 {
+public:
+    /// @brief Constructor
+    ///
+    /// @param name name is a text label for the controller. Typically this
+    /// would be the BIND10 module name.
+    DControllerBase(const char* name);
+
+    /// @brief Destructor
+    virtual ~DControllerBase();
+
+    /// @brief Acts as the primary entry point into the controller execution
+    /// and provides the outermost application control logic:
+    ///
+    /// 1. parse command line arguments
+    /// 2. instantiate and initialize the application process
+    /// 3. establish BIND10 session(s) if in integrated mode
+    /// 4. start and wait on the application process event loop
+    /// 5. upon event loop completion, disconnect from BIND10 (if needed)
+    /// 6. exit to the caller
+    ///
+    /// It is intended to be called from main() and be given the command line
+    /// arguments. Note this method is deliberately not virtual to ensure the
+    /// proper sequence of events occur.
+    ///
+    /// @param argc  is the number of command line arguments supplied
+    /// @param argv  is the array of string (char *) command line arguments
+    ///
+    /// @throw throws one of the following exceptions:
+    /// InvalidUsage - Indicates invalid command line.
+    /// ProcessInitError  - Failed to create and initialize application
+    /// process object.
+    /// SessionStartError  - Could not connect to BIND10 (integrated mode only).
+    /// ProcessRunError - A fatal error occurred while in the application 
+    /// process event loop.
+    /// SessionEndError - Could not disconnect from BIND10 (integrated mode 
+    /// only).
+    void launch(int argc, char* argv[]);
+
+    /// @brief A dummy configuration handler that always returns success.
+    ///
+    /// This configuration handler does not perform configuration
+    /// parsing and always returns success. A dummy handler should
+    /// be installed using \ref isc::config::ModuleCCSession ctor
+    /// to get the initial configuration. This initial configuration
+    /// comprises values for only those elements that were modified
+    /// the previous session. The D2 configuration parsing can't be
+    /// used to parse the initial configuration because it may need the
+    /// full configuration to satisfy dependencies between the
+    /// various configuration values. Installing the dummy handler
+    /// that guarantees to return success causes initial configuration
+    /// to be stored for the session being created and that it can
+    /// be later accessed with \ref isc::ConfigData::getFullConfig.
+    ///
+    /// @param new_config new configuration.
+    ///
+    /// @return success configuration status.
+    static isc::data::ConstElementPtr
+    dummyConfigHandler(isc::data::ConstElementPtr new_config);
+
+    /// @brief A callback for handling all incoming configuration updates.
+    ///
+    /// As a pointer to this method is used as a callback in ASIO for
+    /// ModuleCCSession, it has to be static.  It acts as a wrapper around
+    /// the virtual instance method, updateConfig.
+    ///
+    /// @param new_config textual representation of the new configuration
+    ///
+    /// @return status of the config update
+    static isc::data::ConstElementPtr
+    configHandler(isc::data::ConstElementPtr new_config);
+
+    /// @brief A callback for handling all incoming commands.
+    ///
+    /// As a pointer to this method is used as a callback in ASIO for
+    /// ModuleCCSession, it has to be static.  It acts as a wrapper around
+    /// the virtual instance method, executeCommand.
+    ///
+    /// @param command textual representation of the command
+    /// @param args parameters of the command
+    ///
+    /// @return status of the processed command
+    static isc::data::ConstElementPtr
+    commandHandler(const std::string& command, isc::data::ConstElementPtr args);
+
+    /// @brief Instance method invoked by the configuration event handler and
+    /// which processes the actual configuration update.  Provides behavioral
+    /// path for both integrated and stand-alone modes. The current
+    /// implementation will merge the configuration update into the existing
+    /// configuration and then invoke the application process' configure method.
+    ///
+    /// @TODO This implementation is will evolve as the D2 configuration
+    /// management task is implemented (trac #2957).
+    ///
+    /// @param  new_config is the new configuration
+    ///
+    /// @return returns an Element that contains the results of configuration
+    /// update composed of an integer status value (0 means successful,
+    /// non-zero means failure), and a string explanation of the outcome.
+    virtual isc::data::ConstElementPtr
+    updateConfig(isc::data::ConstElementPtr new_config);
+
+
+    /// @brief Instance method invoked by the command event handler and  which
+    /// processes the actual command directive.
+    ///
+    /// It supports the execution of:
+    ///
+    ///   1. Stock controller commands - commands common to all DControllerBase
+    /// derivations.  Currently there is only one, the shutdown command.
+    ///
+    ///   2. Custom controller commands - commands that the deriving controller
+    /// class implements.  These commands are executed by the deriving
+    /// controller.
+    ///
+    ///   3. Custom application commands - commands supported by the application
+    /// process implementation.  These commands are executed by the application
+    /// process.
+    ///
+    /// @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.
+    ///
+    /// @return an Element that contains the results of command composed
+    /// of an integer status value and a string explanation of the outcome.
+    /// The status value is one of the following:
+    ///   D2::COMMAND_SUCCESS - Command executed successfully
+    ///   D2::COMMAND_ERROR - Command is valid but suffered an operational
+    ///   failure.
+    ///   D2::COMMAND_INVALID - Command is not recognized as valid be either
+    ///   the controller or the application process.
+    virtual isc::data::ConstElementPtr
+    executeCommand(const std::string& command, isc::data::ConstElementPtr args);
+
+protected:
+    /// @brief Virtual method that provides derivations the opportunity to
+    /// support additional command line options.  It is invoked during command
+    /// line argument parsing (see parseArgs method) if the option is not
+    /// recognized as a stock DControllerBase option.
+    ///
+    /// @param option is the option "character" from the command line, without
+    /// any prefixing hyphen(s)
+    /// @optarg optarg is the argument value (if one) associated with the option
+    ///
+    /// @return must return true if the option was valid, false is it is
+    /// invalid. (Note the default implementation always returns false.)
+    virtual bool customOption(int option, char *optarg);
+
+    /// @brief Abstract method that is responsible for instantiating the
+    /// application process object. It is invoked by the controller after
+    /// command line argument parsing as part of the process initialization
+    /// (see initProcess method).
+    ///
+    /// @return returns a pointer to the new process object (DProcessBase*)
+    /// or NULL if the create fails.
+    /// Note this value is subsequently wrapped in a smart pointer.
+    virtual DProcessBase* createProcess() = 0;
+
+    /// @brief Virtual method that provides derivations the opportunity to
+    /// support custom external commands executed by the controller.  This
+    /// method is invoked by the processCommand if the received command is
+    /// not a stock controller command.
+    ///
+    /// @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.
+    ///
+    /// @return an Element that contains the results of command composed
+    /// of an integer status value and a string explanation of the outcome.
+    /// The status value is one of the following:
+    ///   D2::COMMAND_SUCCESS - Command executed successfully
+    ///   D2::COMMAND_ERROR - Command is valid but suffered an operational
+    ///   failure.
+    ///   D2::COMMAND_INVALID - Command is not recognized as a valid custom
+    ///   controller command.
+    virtual isc::data::ConstElementPtr customControllerCommand(
+            const std::string& command, isc::data::ConstElementPtr args);
+
+    /// @brief Virtual method which is invoked after the controller successfully
+    /// establishes BIND10 connectivity.  It provides an opportunity for the
+    /// derivation to execute any custom behavior associated with session
+    /// establishment.
+    ///
+    /// Note, it is not called  when running stand-alone.
+    ///
+    /// @throw should throw a DControllerBaseError if it fails.
+    virtual void onSessionConnect(){};
+
+    /// @brief Virtual method which is invoked as the first action taken when
+    /// the controller is terminating the session(s) with BIND10.  It provides
+    /// an opportunity for the derivation to execute any custom behavior
+    /// associated with session termination.
+    ///
+    /// Note, it is not called  when running stand-alone.
+    ///
+    /// @throw should throw a DControllerBaseError if it fails.
+    virtual void onSessionDisconnect(){};
+
+    /// @brief Virtual method which can be used to contribute derivation
+    /// specific usage text.  It is invoked by the usage() method under
+    /// invalid usage conditions.
+    ///
+    /// @return returns the desired text.
+    virtual const std::string getUsageText() const {
+        return ("");
+    }
+
+    /// @brief Virtual method which returns a string containing the option
+    /// letters for any custom command line options supported by the derivation.
+    /// These are added to the stock options of "s" and "v" during command
+    /// line interpretation.
+    ///
+    /// @return returns a string containing the custom option letters.
+    virtual const std::string getCustomOpts() const {
+        return ("");
+    }
+
+    /// @brief Supplies the controller name.
+    ///
+    /// @return returns the controller name string
+    const std::string getName() const {
+        return (name_);
+    }
+
+    /// @brief Supplies whether or not the controller is in stand alone mode.
+    ///
+    /// @return returns true if in stand alone mode, false otherwise
+    bool isStandAlone() const {
+        return (stand_alone_);
+    }
+
+    /// @brief Method for enabling or disabling stand alone mode.
+    ///
+    /// @param value is the new value to assign the flag.
+    void setStandAlone(bool value) {
+        stand_alone_ = value;
+    }
+
+    /// @brief Supplies whether or not verbose logging is enabled.
+    ///
+    /// @return returns true if verbose logging is enabled.
+    bool isVerbose() const {
+        return (verbose_);
+    }
+
+    /// @brief Method for enabling or disabling verbose logging.
+    ///
+    /// @param value is the new value to assign the flag.
+    void setVerbose(bool value) {
+        verbose_ = value;
+    }
+
+    /// @brief Getter for fetching the controller's IOService
+    ///
+    /// @return returns a pointer reference to the IOService.
+    IOServicePtr& getIOService() {
+        return (io_service_);
+    }
+
+    /// @brief Getter for fetching the name of the controller's BIND10 spec
+    /// file.
+    ///
+    /// @return returns the file name string.
+    const std::string getSpecFileName() const {
+        return (spec_file_name_);
+    }
+
+    /// @brief Setter for setting the name of the controller's BIND10 spec file.
+    ///
+    /// @param value is the file name string.
+    void setSpecFileName(const std::string& spec_file_name) {
+        spec_file_name_ = spec_file_name;
+    }
+
+    /// @brief Static getter which returns the singleton instance.
+    ///
+    /// @return returns a pointer reference to the private singleton instance
+    /// member.
+    static DControllerBasePtr& getController() {
+        return (controller_);
+    }
+
+    /// @brief Static setter which sets the singleton instance.
+    ///
+    /// @param controller is a pointer to the singleton instance.
+    ///
+    /// @throw throws DControllerBase error if an attempt is made to set the
+    /// instance a second time.
+    static void setController(const DControllerBasePtr& controller);
+
+private:
+    /// @brief Processes the command line arguments. It is the first step
+    /// taken after the controller has been launched.  It combines the stock
+    /// list of options with those returned by getCustomOpts(), and uses
+    /// cstdlib's getopt to loop through the command line.  The stock options
+    /// It handles stock options directly, and passes any custom options into
+    /// the customOption method.  Currently there are only two stock options
+    /// -s for stand alone mode, and -v for verbose logging.
+    ///
+    /// @param argc  is the number of command line arguments supplied
+    /// @param argv  is the array of string (char *) command line arguments
+    ///
+    /// @throw throws InvalidUsage when there are usage errors.
+    void parseArgs(int argc, char* argv[]);
+
+    /// @brief Instantiates the application process and then initializes it.
+    /// This is the second step taken during launch, following successful
+    /// command line parsing. It is used to invoke the derivation-specific
+    /// implementation of createProcess, following by an invoking of the
+    /// newly instantiated process's init method.
+    ///
+    /// @throw throws DControllerBaseError or indirectly DProcessBaseError
+    /// if there is a failure creating or initializing the application process.
+    void initProcess();
+
+    /// @brief Establishes connectivity with BIND10.  This method is used
+    /// invoked during launch, if running in integrated mode, following
+    /// successful process initialization.  It is responsible for establishing
+    /// the BIND10 control and config sessions. During the session creation,
+    /// it passes in the controller's IOService and the callbacks for command
+    /// directives and config events.  Lastly, it will invoke the onConnect
+    /// method providing the derivation an opportunity to execute any custom
+    /// logic associated with session establishment.
+    ///
+    /// @throw the BIND10 framework may throw std::exceptions.
+    void establishSession();
+
+    /// @brief Invokes the application process's event loop,(DBaseProcess::run).
+    /// It is called during launch only after successfully completing the
+    /// requested setup: command line parsing, application initialization,
+    /// and session establishment (if not stand-alone).
+    /// The process event loop is expected to only return upon application
+    /// shutdown either in response to the shutdown command or due to an
+    /// unrecoverable error.
+    ///
+    // @throw throws DControllerBaseError or indirectly DProcessBaseError
+    void runProcess();
+
+    /// @brief Terminates connectivity with BIND10. This method is invoked
+    /// in integrated mode after the application event loop has exited. It
+    /// first calls the onDisconnect method providing the derivation an
+    /// opportunity to execute custom logic if needed, and then terminates the
+    /// BIND10 config and control sessions.
+    ///
+    /// @throw the BIND10 framework may throw std:exceptions.
+    void disconnectSession();
+
+    /// @brief Initiates shutdown procedure.  This method is invoked
+    /// by executeCommand in response to the shutdown command. It will invoke
+    /// the application process's shutdown method, which causes the process to
+    /// exit it's event loop.
+    ///
+    /// @return returns an Element that contains the results of shutdown
+    /// attempt composed of an integer status value (0 means successful,
+    /// non-zero means failure), and a string explanation of the outcome.
+    isc::data::ConstElementPtr shutdown();
+
+    /// @brief Prints the program usage text to std error.
+    ///
+    /// @param text is a string message which will preceded the usage text.
+    /// This is intended to be used for specific usage violation messages.
+    void usage(const std::string& text);
+
+private:
+    /// @brief Text label for the controller. Typically this would be the
+    /// BIND10 module name.
+    std::string name_;
+
+    /// @brief Indicates if the controller stand alone mode is enabled. When
+    /// enabled, the controller will not establish connectivity with BIND10.
+    bool stand_alone_;
+
+    /// @brief Indicates if the verbose logging mode is enabled.
+    bool verbose_;
+
+    /// @brief The absolute file name of the BIND10 spec file.
+    std::string spec_file_name_;
+
+    /// @brief Pointer to the instance of the process.
+    ///
+    /// This is required for config and command handlers to gain access to
+    /// the process
+    DProcessBasePtr process_;
+
+    /// @brief Shared pointer to an IOService object, used for ASIO operations.
+    IOServicePtr io_service_;
+
+    /// @brief Helper session object that represents raw connection to msgq.
+    SessionPtr cc_session_;
+
+    /// @brief Session that receives configuration and commands.
+    ModuleCCSessionPtr config_session_;
+
+    /// @brief Singleton instance value.
+    static DControllerBasePtr controller_;
+
+// DControllerTest is named a friend class to facilitate unit testing while
+// leaving the intended member scopes intact.
+friend class DControllerTest;
+};
+
+}; // namespace isc::d2
+}; // namespace isc
+
+#endif
diff --git a/src/bin/d2/d_process.h b/src/bin/d2/d_process.h
index 5c8e50e..8011191 100644
--- a/src/bin/d2/d_process.h
+++ b/src/bin/d2/d_process.h
@@ -33,28 +33,33 @@ public:
         isc::Exception(file, line, what) { };
 };
 
+static const int COMMAND_SUCCESS = 0;
+static const int COMMAND_ERROR = 1;
+static const int COMMAND_INVALID = 2;
+static const std::string SHUT_DOWN_COMMAND("shutdown");
+
 /// @brief Application Process Interface
 ///
-/// DProcessBase is an abstract class represents the primary "application" 
-/// level object in a "managed" asynchronous application. It provides a uniform 
-/// interface such that a managing layer can construct, intialize, and start
+/// DProcessBase is an abstract class represents the primary "application"
+/// level object in a "managed" asynchronous application. It provides a uniform
+/// interface such that a managing layer can construct, initialize, and start
 /// the application's event loop.  The event processing is centered around the
-/// use of isc::asiolink::io_service. The io_service is shared between the 
-/// the managing layer and the DProcessBase.  This allows management layer IO 
-/// such as directives to be sensed and handled, as well as processing IO 
-/// activity specific to the application.  In terms of management layer IO,
-/// there are methods shutdown, configuration updates, and commands unique
-/// to the application.  
+/// use of isc::asiolink::io_service. The io_service is shared between the
+/// managing layer and the DProcessBase.  This allows management layer IO such
+/// as directives to be sensed and handled, as well as processing IO activity
+/// specific to the application.  In terms of management layer IO, there are
+/// methods shutdown, configuration updates, and commands unique to the
+/// application.
 class 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.
     DProcessBase(const char* name, IOServicePtr io_service) : name_(name),
         io_service_(io_service), shut_down_flag_(false) {
 
@@ -64,78 +69,103 @@ public:
     };
 
     /// @brief May be used after instantiation to perform initialization unique
-    /// to application. It must be invoked prior to invoking run. This would 
-    /// likely include the creation of additional IO sources and their 
-    /// integration into the io_service. 
-    virtual void init() = 0; 
-
-    /// @brief Implements the process's event loop. In its simplest form it 
-    /// would an invocation io_service_->run().  This method should not exit 
-    /// until the process itself is exiting due to a request to shutdown or 
-    /// some anomaly is forcing an exit.   
-    /// @return  returns EXIT_SUCCESS upon a successful, normal termination, 
-    /// and EXIT_FAILURE to indicate an abnormal termination.    
-    virtual int run() = 0; 
-
-    /// @brief Implements the process's shutdown processing. When invoked, it 
-    /// should ensure that the process gracefully exits the run method. 
-    virtual int shutdown() = 0;
-
-    /// @brief Processes the given configuration. 
-    /// 
+    /// to application. It must be invoked prior to invoking run. This would
+    /// likely include the creation of additional IO sources and their
+    /// integration into the io_service.
+    /// @throw throws DProcessBaseError if the initialization fails.
+    virtual void init() = 0;
+
+    /// @brief Implements the process's event loop. In its simplest form it
+    /// would an invocation io_service_->run().  This method should not exit
+    /// until the process itself is exiting due to a request to shutdown or
+    /// some anomaly is forcing an exit.
+    /// @throw throws DProcessBaseError if an operational error is encountered.
+    virtual void run() = 0;
+
+    /// @brief Implements the process's shutdown processing. When invoked, it
+    /// should ensure that the process gracefully exits the run method.
+    /// The default implementation sets the shutdown flag and stops IOService.
+    /// @throw throws DProcessBaseError if an operational error is encountered.
+    virtual void shutdown() {
+        setShutdownFlag(true);
+        stopIOService();
+    };
+
+    /// @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) = 0; 
+                                                 config_set) = 0;
 
-    /// @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.  
+    /// and a string explanation of the outcome.
     virtual isc::data::ConstElementPtr command(
-            const std::string& command, isc::data::ConstElementPtr args) = 0; 
+            const std::string& command, isc::data::ConstElementPtr args) = 0;
 
-    /// @brief Destructor 
+    /// @brief Destructor
     virtual ~DProcessBase(){};
 
-    bool shouldShutdown() { 
-        return (shut_down_flag_); 
+    /// @brief Checks if the process has been instructed to shut down.
+    ///
+    /// @return returns true if process shutdown flag is true.
+    bool shouldShutdown() {
+        return (shut_down_flag_);
     }
 
-    void setShutdownFlag(bool value) { 
-        shut_down_flag_ = value; 
+    /// @brief Sets the process shut down flag to the given value.
+    ///
+    /// @param value is the new value to assign the flag.
+    void setShutdownFlag(bool value) {
+        shut_down_flag_ = value;
     }
 
-    const std::string& getName() const {
+    /// @brief Fetches the name of the controller.
+    ///
+    /// @return returns a reference the controller's name string.
+    const std::string getName() const {
         return (name_);
     }
 
+    /// @brief Fetches the controller's IOService.
+    ///
+    /// @return returns a reference to the controller's IOService.
     IOServicePtr& getIoService() {
         return (io_service_);
     }
 
+    /// @brief Convenience method for stopping IOservice processing.
+    /// Invoking this will cause the process to exit any blocking 
+    /// IOService method such as run().  No further IO events will be
+    /// processed.
+    void stopIOService() {
+        io_service_->stop();
+    }
+
 private:
-    /// @brief Text label for the process. Generally used in log statements, 
-    /// but otherwise can be arbitrary. 
+    /// @brief Text label for the process. Generally used in log statements,
+    /// but otherwise can be arbitrary.
     std::string name_;
 
-    /// @brief The IOService to be used for asynchronous event handling. 
+    /// @brief The IOService to be used for asynchronous event handling.
     IOServicePtr io_service_;
 
     /// @brief Boolean flag set when shutdown has been requested.
@@ -145,7 +175,7 @@ private:
 /// @brief Defines a shared pointer to DProcessBase.
 typedef boost::shared_ptr<DProcessBase> DProcessBasePtr;
 
-}; // namespace isc::d2 
+}; // namespace isc::d2
 }; // namespace isc
 
 #endif
diff --git a/src/bin/d2/dhcp-ddns.spec b/src/bin/d2/dhcp-ddns.spec
new file mode 100644
index 0000000..1098ada
--- /dev/null
+++ b/src/bin/d2/dhcp-ddns.spec
@@ -0,0 +1,21 @@
+{
+  "module_spec": {
+    "module_name": "DhcpDdns",
+    "module_description": "DHPC-DDNS Service",
+    "config_data": [
+    ],
+    "commands": [
+      {
+        "command_name": "shutdown",
+        "command_description": "Shut down the DHCP-DDNS service",
+        "command_args": [
+          {
+            "item_name": "pid",
+            "item_type": "integer",
+            "item_optional": true
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/src/bin/d2/main.cc b/src/bin/d2/main.cc
index 5658a8a..fda31038 100644
--- a/src/bin/d2/main.cc
+++ b/src/bin/d2/main.cc
@@ -14,6 +14,8 @@
 
 #include <config.h>
 #include <d2/d2_log.h>
+#include <d2/d2_controller.h>
+#include <exceptions/exceptions.h>
 #include <log/logger_support.h>
 #include <log/logger_manager.h>
 
@@ -22,74 +24,25 @@
 using namespace isc::d2;
 using namespace std;
 
-/// This file contains entry point (main() function) for standard DHCP-DDNS 
-/// process, b10-d2, component for BIND10 framework. It parses command-line
-/// arguments and instantiates D2Controller class that is responsible for
-/// establishing connection with msgq (receiving commands and configuration)
-/// and also creating D2Server object as well.
-///
-/// For detailed explanation or relations between main(), D2Controller,
-/// D2Server and other classes, see \ref d2Session.
-
-namespace {
-
-const char* const D2_NAME = "b10-d2";
-
-void
-usage() {
-    cerr << "Usage: " << D2_NAME << " [-v] [-s]" << endl;
-    cerr << "  -s: stand-alone mode (don't connect to BIND10)" << endl;
-    cerr << "  -v: verbose output (only when in stand-alone mode" << endl;
-    exit(EXIT_FAILURE);
-}
-} // end of anonymous namespace
-
-int
-main(int argc, char* argv[]) {
-    int ch;
-
-    // @TODO NOTE these parameters are preliminary only. They are here to
-    // for symmetry with the DHCP servers.  They may or may not
-    // become part of the eventual implementation.
-
-    bool stand_alone = false;  // Should be connect to BIND10 msgq?
-    bool verbose_mode = false; // Should server be verbose?
-
-    while ((ch = getopt(argc, argv, "vsp:")) != -1) {
-        switch (ch) {
-        case 'v':
-            verbose_mode = true;
-            break;
-
-        case 's':
-            stand_alone = true;
-            break;
-
-        default:
-            usage();
-        }
-    }
-
-    // Check for extraneous parameters.
-    if (argc > optind) {
-        usage();
+/// This file contains entry point (main() function) for standard DHCP-DDNS
+/// process, b10-dhcp-ddns, component for BIND10 framework.  It fetches
+/// the D2Controller singleton instance and invokes its launch method.
+/// The exit value of the program will be EXIT_SUCCESS if there were no
+/// errors, EXIT_FAILURE otherwise.
+int main(int argc, char* argv[]) {
+    int ret = EXIT_SUCCESS;
+
+    // Instantiate/fetch the DHCP-DDNS application controller singleton.
+    DControllerBasePtr& controller = D2Controller::instance();
+
+    // Launch the controller passing in command line arguments.
+    // Exit program with the controller's return code.
+    try  {
+        controller->launch(argc, argv);
+    } catch (const isc::Exception& ex) {
+        std::cerr << "Service failed:" << ex.what() << std::endl;
+        ret = EXIT_FAILURE;
     }
 
-    // Initialize logging.  If verbose, we'll use maximum verbosity.
-    // If standalone is enabled, do not buffer initial log messages
-    // Verbose logging is only enabled when in stand alone mode.
-    isc::log::initLogger(D2_NAME,
-                         ((verbose_mode && stand_alone)
-                           ? isc::log::DEBUG : isc::log::INFO),
-                         isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone);
-
-    LOG_INFO(d2_logger, D2CTL_STARTING);
-
-    // For now we will sleep awhile to simulate doing something.
-    // Without at least a sleep, the process will start, exit and be
-    // restarted by Bind10/Init endlessley in a rapid succession.
-    sleep(1000);
-    LOG_INFO(d2_logger, D2CTL_STOPPING);
-    return (EXIT_SUCCESS);
+    return (ret);
 }
-
diff --git a/src/bin/d2/spec_config.h.pre.in b/src/bin/d2/spec_config.h.pre.in
index e45a69a..6d48a7e 100644
--- a/src/bin/d2/spec_config.h.pre.in
+++ b/src/bin/d2/spec_config.h.pre.in
@@ -12,4 +12,4 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#define D2_SPECFILE_LOCATION "@prefix@/share/@PACKAGE@/d2.spec"
+#define D2_SPECFILE_LOCATION "@prefix@/share/@PACKAGE@/dhcp-ddns.spec"
diff --git a/src/bin/d2/tests/Makefile.am b/src/bin/d2/tests/Makefile.am
index 38701e1..bd7773b 100644
--- a/src/bin/d2/tests/Makefile.am
+++ b/src/bin/d2/tests/Makefile.am
@@ -52,10 +52,15 @@ if HAVE_GTEST
 TESTS += d2_unittests
 
 d2_unittests_SOURCES = ../d2_log.h ../d2_log.cc
-d2_unittests_SOURCES += ../d_process.h 
+d2_unittests_SOURCES += ../d_process.h
+d2_unittests_SOURCES += ../d_controller.cc ../d2_controller.h
 d2_unittests_SOURCES += ../d2_process.cc ../d2_process.h
+d2_unittests_SOURCES += ../d2_controller.cc ../d2_controller.h
+d2_unittests_SOURCES += d_test_stubs.cc d_test_stubs.h
 d2_unittests_SOURCES += d2_unittests.cc
 d2_unittests_SOURCES += d2_process_unittests.cc
+d2_unittests_SOURCES += d_controller_unittests.cc
+d2_unittests_SOURCES += d2_controller_unittests.cc
 nodist_d2_unittests_SOURCES = ../d2_messages.h ../d2_messages.cc
 
 d2_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
diff --git a/src/bin/d2/tests/d2_controller_unittests.cc b/src/bin/d2/tests/d2_controller_unittests.cc
new file mode 100644
index 0000000..75a7f3b
--- /dev/null
+++ b/src/bin/d2/tests/d2_controller_unittests.cc
@@ -0,0 +1,216 @@
+// 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
+// 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.
+
+#include <config/ccsession.h>
+#include <d_test_stubs.h>
+#include <d2/d2_controller.h>
+#include <d2/spec_config.h>
+
+#include <boost/pointer_cast.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <gtest/gtest.h>
+
+#include <config.h>
+#include <sstream>
+
+using namespace boost::posix_time;
+
+namespace isc {
+namespace d2 {
+
+/// @brief Test fixture class for testing D2Controller class. This class
+/// derives from DControllerTest and wraps a D2Controller.  Much of the
+/// underlying functionality is in the DControllerBase class which has an
+/// extensive set of unit tests that are independent of DHCP-DDNS.
+/// @TODO Currently These tests are relatively light and duplicate some of
+/// the testing done on the base class.  These tests are sufficient to ensure
+/// that D2Controller properly derives from its base class and to test the
+/// logic that is unique to D2Controller. These tests will be augmented and
+/// or new tests added as additional functionality evolves.
+/// Unlike the stub testing, there is no use of SimFailure to induce error
+/// conditions as this is production code.
+class D2ControllerTest : public DControllerTest {
+public:
+    /// @brief Constructor
+    /// Note the constructor passes in the static D2Controller instance
+    /// method.
+    D2ControllerTest() : DControllerTest(D2Controller::instance) {
+    }
+
+    /// @brief Destructor
+    ~D2ControllerTest() {
+    }
+};
+
+/// @brief Basic Controller instantiation testing.
+/// Verfies that the controller singleton gets created and that the
+/// basic derivation from the base class is intact.
+TEST_F(D2ControllerTest, basicInstanceTesting) {
+    // Verify the we can the singleton instance can be fetched and that
+    // it is the correct type.
+    DControllerBasePtr& controller = DControllerTest::getController();
+    ASSERT_TRUE(controller);
+    ASSERT_NO_THROW(boost::dynamic_pointer_cast<D2Controller>(controller));
+
+    // Verify that controller's name is correct.
+    EXPECT_TRUE(checkName(D2_MODULE_NAME));
+
+    // Verify that controller's spec file name is correct.
+    EXPECT_TRUE(checkSpecFileName(D2_SPECFILE_LOCATION));
+
+    // Verify that controller's IOService exists.
+    EXPECT_TRUE(checkIOService());
+
+    // Verify that the Process does NOT exist.
+    EXPECT_FALSE(checkProcess());
+}
+
+/// @brief Tests basic command line processing.
+/// Verfies that:
+/// 1. Standard command line options are supported.
+/// 2. Invalid options are detected.
+TEST_F(D2ControllerTest, commandLineArgs) {
+    char* argv[] = { const_cast<char*>("progName"), 
+                     const_cast<char*>("-s"), 
+                     const_cast<char*>("-v") };
+    int argc = 3;
+
+    // Verify that both flags are false initially.
+    EXPECT_TRUE(checkStandAlone(false));
+    EXPECT_TRUE(checkVerbose(false));
+
+    // Verify that standard options can be parsed without error.
+    EXPECT_NO_THROW(parseArgs(argc, argv));
+
+    // Verify that flags are now true.
+    EXPECT_TRUE(checkStandAlone(true));
+    EXPECT_TRUE(checkVerbose(true));
+
+    // Verify that an unknown option is detected.
+    char* argv2[] = { const_cast<char*>("progName"), 
+                      const_cast<char*>("-x") };
+    argc = 2;
+    EXPECT_THROW(parseArgs(argc, argv2), InvalidUsage);
+}
+
+/// @brief Tests application process creation and initialization.
+/// Verifies that the process can be successfully created and initialized.
+TEST_F(D2ControllerTest, initProcessTesting) {
+    ASSERT_NO_THROW(initProcess());
+    EXPECT_TRUE(checkProcess());
+}
+
+/// @brief Tests launch and normal shutdown (stand alone mode).
+/// This creates an interval timer to generate a normal shutdown and then
+/// launches with a valid, stand-alone command line and no simulated errors.
+TEST_F(D2ControllerTest, launchNormalShutdown) {
+    // command line to run standalone
+    char* argv[] = { const_cast<char*>("progName"), 
+                     const_cast<char*>("-s"), 
+                     const_cast<char*>("-v") };
+    int argc = 3;
+
+    // Use an asiolink IntervalTimer and callback to generate the
+    // shutdown invocation. (Note IntervalTimer setup is in milliseconds).
+    isc::asiolink::IntervalTimer timer(*getIOService());
+    timer.setup(genShutdownCallback, 2 * 1000);
+
+    // Record start time, and invoke launch().
+    ptime start = microsec_clock::universal_time();
+    EXPECT_NO_THROW(launch(argc, argv));
+
+    // Record stop time.
+    ptime stop = microsec_clock::universal_time();
+
+    // Verify that duration of the run invocation is the same as the
+    // timer duration.  This demonstrates that the shutdown was driven
+    // by an io_service event and callback.
+    time_duration elapsed = stop - start;
+    EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
+                elapsed.total_milliseconds() <= 2100);
+}
+
+/// @brief Configuration update event testing.
+/// This really tests just the ability of the handlers to invoke the necessary
+/// chain of methods and handle error conditions. Configuration parsing and
+/// retrieval should be tested as part of the d2 configuration management
+/// implementation.  Note that this testing calls the configuration update event
+/// callback, configHandler, directly.
+/// This test verifies that:
+/// 1. Configuration will be rejected in integrated mode when there is no
+/// session established. (This is a very contrived situation).
+/// 2. In stand-alone mode a configuration update results in successful
+/// status return.
+/// 3. That an application process error in configuration updating is handled
+/// properly.
+TEST_F(D2ControllerTest, configUpdateTests) {
+    int rcode = -1;
+    isc::data::ConstElementPtr answer;
+
+    // Initialize the application process.
+    ASSERT_NO_THROW(initProcess());
+    EXPECT_TRUE(checkProcess());
+
+    // Create a configuration set. Content is arbitrary, just needs to be
+    // valid JSON.
+    std::string config = "{ \"test-value\": 1000 } ";
+    isc::data::ElementPtr config_set = isc::data::Element::fromJSON(config);
+
+    // We are not stand-alone, so configuration should be rejected as there is
+    // no session.  This is a pretty contrived situation that shouldn't be
+    // possible other than the handler being called directly (like this does).
+    answer = DControllerBase::configHandler(config_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(1, rcode);
+
+    // Verify that in stand alone we get a successful update result.
+    setStandAlone(true);
+    answer = DControllerBase::configHandler(config_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(0, rcode);
+}
+
+/// @brief Command execution tests.
+/// This really tests just the ability of the handler to invoke the necessary
+/// chain of methods and to handle error conditions. Note that this testing
+/// calls the command callback, commandHandler, directly.
+/// This test verifies that:
+/// 1. That an unrecognized command is detected and returns a status of
+/// d2::COMMAND_INVALID.
+/// 2. Shutdown command is recognized and returns a d2::COMMAND_SUCCESS status.
+TEST_F(D2ControllerTest, executeCommandTests) {
+    int rcode = -1;
+    isc::data::ConstElementPtr answer;
+    isc::data::ElementPtr arg_set;
+
+    // Initialize the application process.
+    ASSERT_NO_THROW(initProcess());
+    EXPECT_TRUE(checkProcess());
+
+    // Verify that an unknown command returns an COMMAND_INVALID response.
+    std::string bogus_command("bogus");
+    answer = DControllerBase::commandHandler(bogus_command, arg_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(COMMAND_INVALID, rcode);
+
+    // Verify that shutdown command returns COMMAND_SUCCESS response.
+    //answer = executeCommand(SHUT_DOWN_COMMAND, isc::data::ElementPtr());
+    answer = DControllerBase::commandHandler(SHUT_DOWN_COMMAND, arg_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(COMMAND_SUCCESS, rcode);
+
+}
+
+}; // end of isc::d2 namespace
+}; // end of isc namespace
diff --git a/src/bin/d2/tests/d2_process_unittests.cc b/src/bin/d2/tests/d2_process_unittests.cc
index 2dc0d3d..40c85f3 100644
--- a/src/bin/d2/tests/d2_process_unittests.cc
+++ b/src/bin/d2/tests/d2_process_unittests.cc
@@ -43,7 +43,7 @@ public:
         process_.reset(new D2Process("TestProcess", io_service_));
     }
 
-    /// @brief Destructor 
+    /// @brief Destructor
     ~D2ProcessTest() {
         io_service_.reset();
         process_.reset();
@@ -59,7 +59,7 @@ public:
         isc_throw (DProcessBaseError, "simulated fatal error");
     }
 
-    /// @brief IOService for event processing. Fills in for IOservice
+    /// @brief IOService for event processing. Fills in for IOService
     /// supplied by management layer.
     IOServicePtr io_service_;
 };
@@ -83,36 +83,36 @@ TEST(D2Process, construction) {
 }
 
 /// @brief Verifies basic configure method behavior.
-// @TODO This test is simplistic and will need to be augmented
-// as configuration ability is implemented.
+/// @TODO This test is simplistic and will need to be augmented as configuration
+/// ability is implemented.
 TEST_F(D2ProcessTest, configure) {
     // Verify that given a configuration "set", configure returns
     // a successful response.
     int rcode = -1;
     string config = "{ \"test-value\": 1000 } ";
     isc::data::ElementPtr json = isc::data::Element::fromJSON(config);
-    isc::data::ConstElementPtr answer = process_->configure(json); 
+    isc::data::ConstElementPtr answer = process_->configure(json);
     isc::config::parseAnswer(rcode, answer);
     EXPECT_EQ(0, rcode);
 }
 
-/// @brief Verifies basic command method behavior. 
-// @TODO IF the D2Process is extended to support extra commands
-// this testing will need to augmented accordingly.
+/// @brief Verifies basic command method behavior.
+/// @TODO IF the D2Process is extended to support extra commands this testing
+/// will need to augmented accordingly.
 TEST_F(D2ProcessTest, command) {
-    // Verfiy that the process will process unsupported command and
+    // Verify that the process will process unsupported command and
     // return a failure response.
     int rcode = -1;
     string args = "{ \"arg1\": 77 } ";
     isc::data::ElementPtr json = isc::data::Element::fromJSON(args);
-    isc::data::ConstElementPtr answer = 
-                                    process_->command("bogus_command", json); 
+    isc::data::ConstElementPtr answer =
+                                    process_->command("bogus_command", json);
     parseAnswer(rcode, answer);
-    EXPECT_EQ(1, rcode);
+    EXPECT_EQ(COMMAND_INVALID, rcode);
 }
 
-/// @brief Verifies that an "external" call to shutdown causes 
-/// the run method to exit gracefully with a return value of EXIT_SUCCESS.
+/// @brief Verifies that an "external" call to shutdown causes the run method
+/// to exit gracefully.
 TEST_F(D2ProcessTest, normalShutdown) {
     // Use an asiolink IntervalTimer and callback to generate the
     // shutdown invocation. (Note IntervalTimer setup is in milliseconds).
@@ -121,24 +121,21 @@ TEST_F(D2ProcessTest, normalShutdown) {
 
     // Record start time, and invoke run().
     ptime start = microsec_clock::universal_time();
-    int rcode = process_->run();
+    EXPECT_NO_THROW(process_->run());
 
     // Record stop time.
     ptime stop = microsec_clock::universal_time();
 
-    // Verify normal shutdown status.
-    EXPECT_EQ(EXIT_SUCCESS, rcode);
-
     // Verify that duration of the run invocation is the same as the
     // timer duration.  This demonstrates that the shutdown was driven
     // by an io_service event and callback.
     time_duration elapsed = stop - start;
-    EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 && 
+    EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
                 elapsed.total_milliseconds() <= 2100);
 }
 
-/// @brief Verifies that an "uncaught" exception thrown during event loop 
-/// processing is treated as a fatal error.
+/// @brief Verifies that an "uncaught" exception thrown during event loop
+/// execution is treated as a fatal error.
 TEST_F(D2ProcessTest, fatalErrorShutdown) {
     // Use an asiolink IntervalTimer and callback to generate the
     // the exception.  (Note IntervalTimer setup is in milliseconds).
@@ -147,19 +144,16 @@ TEST_F(D2ProcessTest, fatalErrorShutdown) {
 
     // Record start time, and invoke run().
     ptime start = microsec_clock::universal_time();
-    int rcode = process_->run();
+    EXPECT_THROW(process_->run(), DProcessBaseError);
 
     // Record stop time.
     ptime stop = microsec_clock::universal_time();
 
-    // Verify failure status.
-    EXPECT_EQ(EXIT_FAILURE, rcode);
-
     // Verify that duration of the run invocation is the same as the
     // timer duration.  This demonstrates that the anomaly occurred
-    // during io callback processing. 
+    // during io callback processing.
     time_duration elapsed = stop - start;
-    EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 && 
+    EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
                 elapsed.total_milliseconds() <= 2100);
 }
 
diff --git a/src/bin/d2/tests/d2_test.py b/src/bin/d2/tests/d2_test.py
index 032aaa4..7011cfc 100644
--- a/src/bin/d2/tests/d2_test.py
+++ b/src/bin/d2/tests/d2_test.py
@@ -159,7 +159,8 @@ class TestD2Daemon(unittest.TestCase):
         print("Note: Simple test to verify that D2 server can be started.")
         # note that "-s" for stand alone is necessary in order to flush the log output
         # soon enough to catch it.
-        (returncode, output, error) = self.runCommand(["../b10-d2", "-s"])
+        (returncode, output, error) = self.runCommand(["../b10-dhcp-ddns", 
+                                                       "-s", "-v"])
         output_text = str(output) + str(error)
         self.assertEqual(output_text.count("D2CTL_STARTING"), 1)
 
diff --git a/src/bin/d2/tests/d_controller_unittests.cc b/src/bin/d2/tests/d_controller_unittests.cc
new file mode 100644
index 0000000..501fe13
--- /dev/null
+++ b/src/bin/d2/tests/d_controller_unittests.cc
@@ -0,0 +1,361 @@
+// 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
+// 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.
+
+#include <config/ccsession.h>
+#include <d_test_stubs.h>
+#include <d2/spec_config.h>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <gtest/gtest.h>
+
+#include <config.h>
+#include <sstream>
+
+using namespace boost::posix_time;
+
+namespace isc {
+namespace d2 {
+
+/// @brief Test fixture class for testing DControllerBase class. This class
+/// derives from DControllerTest and wraps a DStubController.  DStubController
+/// has been constructed to exercise DControllerBase.
+class DStubControllerTest : public DControllerTest {
+public:
+
+    /// @brief Constructor.
+    /// Note the constructor passes in the static DStubController instance
+    /// method.
+    DStubControllerTest() : DControllerTest (DStubController::instance) {
+    }
+
+    virtual ~DStubControllerTest() {
+    }
+};
+
+/// @brief Basic Controller instantiation testing.
+/// Verfies that the controller singleton gets created and that the
+/// basic derivation from the base class is intact.
+TEST_F(DStubControllerTest, basicInstanceTesting) {
+    // Verify that the singleton exists and it is the correct type.
+    DControllerBasePtr& controller = DControllerTest::getController();
+    ASSERT_TRUE(controller);
+    ASSERT_NO_THROW(boost::dynamic_pointer_cast<DStubController>(controller));
+
+    // Verify that controller's name is correct.
+    EXPECT_TRUE(checkName(D2_MODULE_NAME));
+
+    // Verify that controller's spec file name is correct.
+    EXPECT_TRUE(checkSpecFileName(D2_SPECFILE_LOCATION));
+
+    // Verify that controller's IOService exists.
+    EXPECT_TRUE(checkIOService());
+
+    // Verify that the Process does NOT exist.
+    EXPECT_FALSE(checkProcess());
+}
+
+/// @brief Tests basic command line processing.
+/// Verifies that:
+/// 1. Standard command line options are supported.
+/// 2. Custom command line options are supported.
+/// 3. Invalid options are detected.
+/// 4. Extraneous command line information is detected.
+TEST_F(DStubControllerTest, commandLineArgs) {
+
+    // Verify that both flags are false initially.
+    EXPECT_TRUE(checkStandAlone(false));
+    EXPECT_TRUE(checkVerbose(false));
+
+    // Verify that standard options can be parsed without error.
+    char* argv[] = { const_cast<char*>("progName"),
+                     const_cast<char*>("-s"),
+                     const_cast<char*>("-v") };
+    int argc = 3;
+    EXPECT_NO_THROW(parseArgs(argc, argv));
+
+    // Verify that flags are now true.
+    EXPECT_TRUE(checkStandAlone(true));
+    EXPECT_TRUE(checkVerbose(true));
+
+    // Verify that the custom command line option is parsed without error.
+    char xopt[3] = "- ";
+    xopt[1] =  *DStubController::stub_option_x_;
+    char* argv1[] = { const_cast<char*>("progName"), xopt};
+    argc = 2;
+    EXPECT_NO_THROW (parseArgs(argc, argv1));
+
+    // Verify that an unknown option is detected.
+    char* argv2[] = { const_cast<char*>("progName"),
+                      const_cast<char*>("-bs") };
+    argc = 2;
+    EXPECT_THROW (parseArgs(argc, argv2), InvalidUsage);
+
+    // Verify that extraneous information is detected.
+    char* argv3[] = { const_cast<char*>("progName"),
+                      const_cast<char*>("extra"),
+                      const_cast<char*>("information") };
+    argc = 3;
+    EXPECT_THROW (parseArgs(argc, argv3), InvalidUsage);
+}
+
+/// @brief Tests application process creation and initialization.
+/// Verifies that:
+/// 1. An error during process creation is handled.
+/// 2. A NULL returned by process creation is handled.
+/// 3. An error during process initialization is handled.
+/// 4. Process can be successfully created and initialized.
+TEST_F(DStubControllerTest, initProcessTesting) {
+    // Verify that a failure during process creation is caught.
+    SimFailure::set(SimFailure::ftCreateProcessException);
+    EXPECT_THROW(initProcess(), DControllerBaseError);
+    EXPECT_FALSE(checkProcess());
+
+    // Verify that a NULL returned by process creation is handled.
+    SimFailure::set(SimFailure::ftCreateProcessNull);
+    EXPECT_THROW(initProcess(), DControllerBaseError);
+    EXPECT_FALSE(checkProcess());
+
+    // Re-create controller, verify that we are starting clean
+    resetController();
+    EXPECT_FALSE(checkProcess());
+
+    // Verify that an error during process initialization is handled.
+    SimFailure::set(SimFailure::ftProcessInit);
+    EXPECT_THROW(initProcess(), DProcessBaseError);
+
+    // Re-create controller, verify that we are starting clean
+    resetController();
+    EXPECT_FALSE(checkProcess());
+
+    // Verify that the application process can created and initialized.
+    ASSERT_NO_THROW(initProcess());
+    EXPECT_TRUE(checkProcess());
+}
+
+/// @brief Tests launch handling of invalid command line.
+/// This test launches with an invalid command line which should throw
+/// an InvalidUsage.
+TEST_F(DStubControllerTest, launchInvalidUsage) {
+    // Command line to run integrated
+    char* argv[] = { const_cast<char*>("progName"),
+                     const_cast<char*>("-z") };
+    int argc = 2;
+
+    // Launch the controller in integrated mode.
+    EXPECT_THROW(launch(argc, argv), InvalidUsage);
+}
+
+/// @brief Tests launch handling of failure in application process
+/// initialization.  This test launches with a valid command line but with
+/// SimFailure set to fail during process creation.  Launch should throw
+/// ProcessInitError.
+TEST_F(DStubControllerTest, launchProcessInitError) {
+    // Command line to run integrated
+    char* argv[] = { const_cast<char*>("progName"),
+                     const_cast<char*>("-s"),
+                     const_cast<char*>("-v") };
+    int argc = 3;
+
+    // Launch the controller in stand alone mode.
+    SimFailure::set(SimFailure::ftCreateProcessException);
+    EXPECT_THROW(launch(argc, argv), ProcessInitError);
+}
+
+/// @brief Tests launch and normal shutdown (stand alone mode).
+/// This creates an interval timer to generate a normal shutdown and then
+/// launches with a valid, stand-alone command line and no simulated errors.
+TEST_F(DStubControllerTest, launchNormalShutdown) {
+    // command line to run standalone
+    char* argv[] = { const_cast<char*>("progName"),
+                     const_cast<char*>("-s"),
+                     const_cast<char*>("-v") };
+    int argc = 3;
+
+    // Use an asiolink IntervalTimer and callback to generate the
+    // shutdown invocation. (Note IntervalTimer setup is in milliseconds).
+    isc::asiolink::IntervalTimer timer(*getIOService());
+    timer.setup(genShutdownCallback, 2 * 1000);
+
+    // Record start time, and invoke launch().
+    ptime start = microsec_clock::universal_time();
+    EXPECT_NO_THROW(launch(argc, argv));
+
+    // Record stop time.
+    ptime stop = microsec_clock::universal_time();
+
+    // Verify that duration of the run invocation is the same as the
+    // timer duration.  This demonstrates that the shutdown was driven
+    // by an io_service event and callback.
+    time_duration elapsed = stop - start;
+    EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
+                elapsed.total_milliseconds() <= 2100);
+}
+
+/// @brief Tests launch with an operational error during application execution.
+/// This test creates an interval timer to generate a runtime exception during
+/// the process event loop. It launches wih a valid, stand-alone command line
+/// and no simulated errors.  Launch should throw ProcessRunError.
+TEST_F(DStubControllerTest, launchRuntimeError) {
+    // command line to run standalone
+    char* argv[] = { const_cast<char*>("progName"),
+                     const_cast<char*>("-s"),
+                     const_cast<char*>("-v") };
+    int argc = 3;
+
+    // Use an asiolink IntervalTimer and callback to generate the
+    // shutdown invocation. (Note IntervalTimer setup is in milliseconds).
+    isc::asiolink::IntervalTimer timer(*getIOService());
+    timer.setup(genFatalErrorCallback, 2 * 1000);
+
+    // Record start time, and invoke launch().
+    ptime start = microsec_clock::universal_time();
+    EXPECT_THROW(launch(argc, argv), ProcessRunError);
+
+    // Record stop time.
+    ptime stop = microsec_clock::universal_time();
+
+    // Verify that duration of the run invocation is the same as the
+    // timer duration.  This demonstrates that the shutdown was driven
+    // by an io_service event and callback.
+    time_duration elapsed = stop - start;
+    EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
+                elapsed.total_milliseconds() <= 2100);
+}
+
+/// @brief Tests launch with a session establishment failure.
+/// This test launches with a valid command line for integrated mode and no.
+/// Attempting to connect to BIND10 should fail, even if BIND10 is running
+/// UNLESS the test is run as root.  Launch should throw SessionStartError.
+TEST_F(DStubControllerTest, launchSessionFailure) {
+    // Command line to run integrated
+    char* argv[] = { (char*)"progName" };
+    int argc = 1;
+
+    // Launch the controller in integrated mode.
+    EXPECT_THROW(launch(argc, argv), SessionStartError);
+}
+
+/// @brief Configuration update event testing.
+/// This really tests just the ability of the handlers to invoke the necessary
+/// chain of methods and handle error conditions. Configuration parsing and
+/// retrieval should be tested as part of the d2 configuration management
+/// implementation.  Note that this testing calls the configuration update event
+/// callback, configHandler, directly.
+/// This test verifies that:
+/// 1. Configuration will be rejected in integrated mode when there is no
+/// session established. (This is a very contrived situation).
+/// 2. In stand-alone mode a configuration update results in successful
+/// status return.
+/// 3. That an application process error in configuration updating is handled
+/// properly.
+TEST_F(DStubControllerTest, configUpdateTests) {
+    int rcode = -1;
+    isc::data::ConstElementPtr answer;
+
+    // Initialize the application process.
+    ASSERT_NO_THROW(initProcess());
+    EXPECT_TRUE(checkProcess());
+
+    // Create a configuration set. Content is arbitrary, just needs to be
+    // valid JSON.
+    std::string config = "{ \"test-value\": 1000 } ";
+    isc::data::ElementPtr config_set = isc::data::Element::fromJSON(config);
+
+    // We are not stand-alone, so configuration should be rejected as there is
+    // no session.  This is a pretty contrived situation that shouldn't be
+    // possible other than the handler being called directly (like this does).
+    answer = DControllerBase::configHandler(config_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(1, rcode);
+
+    // Verify that in stand alone we get a successful update result.
+    setStandAlone(true);
+    answer = DControllerBase::configHandler(config_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(0, rcode);
+
+    // Verify that an error in process configure method is handled.
+    SimFailure::set(SimFailure::ftProcessConfigure);
+    answer = DControllerBase::configHandler(config_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(1, rcode);
+}
+
+/// @brief Command execution tests.
+/// This really tests just the ability of the handler to invoke the necessary
+/// chain of methods and to handle error conditions. Note that this testing
+/// calls the command callback, commandHandler, directly.
+/// This test verifies that:
+/// 1. That an unrecognized command is detected and returns a status of
+/// d2::COMMAND_INVALID.
+/// 2. Shutdown command is recognized and returns a d2::COMMAND_SUCCESS status.
+/// 3. A valid, custom controller command is recognized a d2::COMMAND_SUCCESS
+/// status.
+/// 4. A valid, custom process command is recognized a d2::COMMAND_SUCCESS
+/// status.
+/// 5. That a valid controller command that fails returns a d2::COMMAND_ERROR.
+/// 6. That a valid process command that fails returns a d2::COMMAND_ERROR.
+TEST_F(DStubControllerTest, executeCommandTests) {
+    int rcode = -1;
+    isc::data::ConstElementPtr answer;
+    isc::data::ElementPtr arg_set;
+
+    // Initialize the application process.
+    ASSERT_NO_THROW(initProcess());
+    EXPECT_TRUE(checkProcess());
+
+    // Verify that an unknown command returns an d2::COMMAND_INVALID response.
+    std::string bogus_command("bogus");
+    answer = DControllerBase::commandHandler(bogus_command, arg_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(COMMAND_INVALID, rcode);
+
+    // Verify that shutdown command returns d2::COMMAND_SUCCESS response.
+    answer = DControllerBase::commandHandler(SHUT_DOWN_COMMAND, arg_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(COMMAND_SUCCESS, rcode);
+
+    // Verify that a valid custom controller command returns
+    // d2::COMMAND_SUCCESS response.
+    answer = DControllerBase::commandHandler(DStubController::
+                                             stub_ctl_command_, arg_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(COMMAND_SUCCESS, rcode);
+
+    // Verify that a valid custom process command returns d2::COMMAND_SUCCESS
+    // response.
+    answer = DControllerBase::commandHandler(DStubProcess::
+                                             stub_proc_command_, arg_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(COMMAND_SUCCESS, rcode);
+
+    // Verify that a valid custom controller command that fails returns
+    // a d2::COMMAND_ERROR.
+    SimFailure::set(SimFailure::ftControllerCommand);
+    answer = DControllerBase::commandHandler(DStubController::
+                                             stub_ctl_command_, arg_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(COMMAND_ERROR, rcode);
+
+    // Verify that a valid custom process command that fails returns
+    // a d2::COMMAND_ERROR.
+    SimFailure::set(SimFailure::ftProcessCommand);
+    answer = DControllerBase::commandHandler(DStubProcess::
+                                             stub_proc_command_, arg_set);
+    isc::config::parseAnswer(rcode, answer);
+    EXPECT_EQ(COMMAND_ERROR, rcode);
+}
+
+}; // end of isc::d2 namespace
+}; // end of isc namespace
diff --git a/src/bin/d2/tests/d_test_stubs.cc b/src/bin/d2/tests/d_test_stubs.cc
new file mode 100644
index 0000000..f348dff
--- /dev/null
+++ b/src/bin/d2/tests/d_test_stubs.cc
@@ -0,0 +1,202 @@
+// 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
+// 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.
+
+#include <d2/d2_log.h>
+#include <d2/spec_config.h>
+#include <d2/tests/d_test_stubs.h>
+
+using namespace asio;
+
+namespace isc {
+namespace d2 {
+
+// Initialize the static failure flag.
+SimFailure::FailureType SimFailure::failure_type_ = SimFailure::ftNoFailure;
+
+// Define custom process command supported by DStubProcess.
+const char*  DStubProcess::stub_proc_command_("cool_proc_cmd");
+
+DStubProcess::DStubProcess(const char* name, IOServicePtr io_service)
+    : DProcessBase(name, io_service) {
+};
+
+void
+DStubProcess::init() {
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_PROCESS_INIT);
+    if (SimFailure::shouldFailOn(SimFailure::ftProcessInit)) {
+        // Simulates a failure to instantiate the process.
+        isc_throw(DProcessBaseError, "DStubProcess simulated init() failure");
+    }
+};
+
+void
+DStubProcess::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
+    // or the call to run will continue to block, and shutdown will not
+    // occur.
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_ENTER);
+    IOServicePtr& io_service = getIoService();
+    while (!shouldShutdown()) {
+        try {
+            io_service->run_one();
+        } catch (const std::exception& ex) {
+            LOG_FATAL(d2_logger, D2PRC_FAILED).arg(ex.what());
+            isc_throw (DProcessBaseError,
+                std::string("Process run method failed:") + ex.what());
+        }
+    }
+
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_EXIT);
+};
+
+void
+DStubProcess::shutdown() {
+    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_SHUTDOWN);
+    if (SimFailure::shouldFailOn(SimFailure::ftProcessShutdown)) {
+        // Simulates a failure during shutdown process.
+        isc_throw(DProcessBaseError, "DStubProcess simulated shutdown failure");
+    }
+
+    DProcessBase::shutdown();
+}
+
+isc::data::ConstElementPtr
+DStubProcess::configure(isc::data::ConstElementPtr config_set) {
+    LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
+              D2PRC_CONFIGURE).arg(config_set->str());
+
+    if (SimFailure::shouldFailOn(SimFailure::ftProcessConfigure)) {
+        // Simulates a process configure failure.
+        return (isc::config::createAnswer(1,
+                "Simulated process configuration error."));
+    }
+
+    return (isc::config::createAnswer(0, "Configuration accepted."));
+}
+
+isc::data::ConstElementPtr
+DStubProcess::command(const std::string& command,
+                      isc::data::ConstElementPtr args) {
+    LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
+              D2PRC_COMMAND).arg(command).arg(args->str());
+
+    isc::data::ConstElementPtr answer;
+    if (SimFailure::shouldFailOn(SimFailure::ftProcessCommand)) {
+        // Simulates a process command execution failure.
+        answer = isc::config::createAnswer(COMMAND_ERROR,
+                                          "SimFailure::ftProcessCommand");
+    } else if (command.compare(stub_proc_command_) == 0) {
+        answer = isc::config::createAnswer(COMMAND_SUCCESS, "Command accepted");
+    } else {
+        answer = isc::config::createAnswer(COMMAND_INVALID,
+                                           "Unrecognized command:" + command);
+    }
+
+    return (answer);
+}
+
+DStubProcess::~DStubProcess() {
+};
+
+//************************** DStubController *************************
+
+// Define custom controller command supported by DStubController.
+const char* DStubController::stub_ctl_command_("spiffy");
+
+// Define custom command line option command supported by DStubController.
+const char* DStubController::stub_option_x_ = "x";
+
+DControllerBasePtr&
+DStubController::instance() {
+    // If the singleton hasn't been created, do it now.
+    if (!getController()) {
+        //setController(new DStubController());
+        DControllerBasePtr p(new DStubController());
+        setController(p);
+    }
+
+    return (getController());
+}
+
+DStubController::DStubController()
+    : DControllerBase(D2_MODULE_NAME) {
+
+    if (getenv("B10_FROM_BUILD")) {
+        setSpecFileName(std::string(getenv("B10_FROM_BUILD")) +
+            "/src/bin/d2/d2.spec");
+    } else {
+        setSpecFileName(D2_SPECFILE_LOCATION);
+    }
+}
+
+bool
+DStubController::customOption(int option, char* /* optarg */)
+{
+    // Check for the custom option supported by DStubController.
+    if (static_cast<char>(option) == *stub_option_x_) {
+        return (true);
+    }
+
+    return (false);
+}
+
+DProcessBase* DStubController::createProcess() {
+    if (SimFailure::shouldFailOn(SimFailure::ftCreateProcessException)) {
+        // Simulates a failure to instantiate the process due to exception.
+        throw std::runtime_error("SimFailure::ftCreateProcess");
+    }
+
+    if (SimFailure::shouldFailOn(SimFailure::ftCreateProcessNull)) {
+        // Simulates a failure to instantiate the process.
+        return (NULL);
+    }
+
+    // This should be a successful instantiation.
+    return (new DStubProcess(getName().c_str(), getIOService()));
+}
+
+isc::data::ConstElementPtr
+DStubController::customControllerCommand(const std::string& command,
+                                     isc::data::ConstElementPtr /* args */) {
+    isc::data::ConstElementPtr answer;
+    if (SimFailure::shouldFailOn(SimFailure::ftControllerCommand)) {
+        // Simulates command failing to execute.
+        answer = isc::config::createAnswer(COMMAND_ERROR,
+                                          "SimFailure::ftControllerCommand");
+    } else if (command.compare(stub_ctl_command_) == 0) {
+        answer = isc::config::createAnswer(COMMAND_SUCCESS, "Command accepted");
+    } else {
+        answer = isc::config::createAnswer(COMMAND_INVALID,
+                                           "Unrecognized command:" + command);
+    }
+
+    return (answer);
+}
+
+const std::string DStubController::getCustomOpts() const {
+    // Return the "list" of custom options supported by DStubController.
+    return (std::string(stub_option_x_));
+}
+
+DStubController::~DStubController() {
+}
+
+// Initialize controller wrapper's static instance getter member.
+DControllerTest::InstanceGetter DControllerTest::instanceGetter_ = NULL;
+
+}; // namespace isc::d2
+}; // namespace isc
diff --git a/src/bin/d2/tests/d_test_stubs.h b/src/bin/d2/tests/d_test_stubs.h
new file mode 100644
index 0000000..1659e52
--- /dev/null
+++ b/src/bin/d2/tests/d_test_stubs.h
@@ -0,0 +1,422 @@
+// 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
+// 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 D_TEST_STUBS_H
+#define D_TEST_STUBS_H
+
+#include <asiolink/asiolink.h>
+#include <cc/data.h>
+#include <cc/session.h>
+#include <config/ccsession.h>
+
+#include <d2/d_controller.h>
+#include <gtest/gtest.h>
+
+namespace isc {
+namespace d2 {
+
+/// @brief Class is used to set a globally accessible value that indicates
+/// a specific type of failure to simulate.  Test derivations of base classes
+/// can exercise error handling code paths by testing for specific SimFailure
+/// values at the appropriate places and then causing the error to "occur".
+/// The class consists of an enumerated set of failures, and static methods
+/// for getting, setting, and testing the current value.
+class SimFailure {
+public:
+    enum FailureType {
+        ftUnknown = -1,
+        ftNoFailure = 0,
+        ftCreateProcessException,
+        ftCreateProcessNull,
+        ftProcessInit,
+        ftProcessConfigure,
+        ftControllerCommand,
+        ftProcessCommand,
+        ftProcessShutdown
+    };
+
+    /// @brief Sets the SimFailure value to the given value.
+    ///
+    /// @param value is the new value to assign to the global value.
+    static void set(enum FailureType value) {
+       failure_type_ = value;
+    }
+
+    /// @brief Gets the current global SimFailure value
+    ///
+    /// @return returns the current SimFailure value
+    static enum FailureType get() {
+       return (failure_type_);
+    }
+
+    /// @brief One-shot test of the SimFailure value. If the global
+    /// SimFailure value is equal to the given value, clear the global
+    /// value and return true.  This makes it convenient for code to
+    /// test and react without having to explicitly clear the global
+    /// value.
+    ///
+    /// @param value is the value against which the global value is
+    /// to be compared.
+    ///
+    /// @return returns true if current SimFailure value matches the
+    /// given value.
+    static bool shouldFailOn(enum FailureType value) {
+        if (failure_type_ == value) {
+            clear();
+            return (true);
+        }
+
+        return (false);
+    }
+
+    static void clear() {
+       failure_type_ = ftNoFailure;
+    }
+
+    static enum FailureType failure_type_;
+};
+
+/// @brief Test Derivation of the DProcessBase class.
+///
+/// This class is used primarily to server as a test process class for testing
+/// DControllerBase.  It provides minimal, but sufficient implementation to
+/// test the majority of DControllerBase functionality.
+class DStubProcess : public DProcessBase {
+public:
+
+    /// @brief Static constant that defines a custom process command string.
+    static const char* stub_proc_command_;
+
+    /// @brief Constructor
+    ///
+    /// @param name name is a text label for the process. Generally used
+    /// 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.
+    DStubProcess(const char* name, IOServicePtr io_service);
+
+    /// @brief Invoked after process instantiation to perform initialization.
+    /// This implementation supports simulating an error initializing the
+    /// process by throwing a DProcessBaseError if SimFailure is set to
+    /// ftProcessInit.
+    virtual void init();
+
+    /// @brief Implements the process's event loop.
+    /// This 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 void run();
+
+    /// @brief Implements the process shutdown procedure. Currently this is
+    /// limited to setting the instance shutdown flag, which is monitored in
+    /// run().
+    virtual void shutdown();
+
+    /// @brief Processes the given configuration.
+    ///
+    /// This implementation fails if SimFailure is set to ftProcessConfigure.
+    /// Otherwise it will complete successfully.  It does not check the content
+    /// of the inbound configuration.
+    ///
+    /// @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.
+    virtual isc::data::ConstElementPtr configure(isc::data::ConstElementPtr
+                                                 config_set);
+
+    /// @brief Executes the given command.
+    ///
+    /// This implementation will recognizes one "custom" process command,
+    /// stub_proc_command_.  It will fail if SimFailure is set to
+    /// ftProcessCommand.
+    ///
+    /// @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.
+    /// @return an Element that contains the results of command composed
+    /// of an integer status value and a string explanation of the outcome.
+    /// The status value is:
+    /// COMMAND_SUCCESS if the command is recognized and executes successfully.
+    /// COMMAND_ERROR if the command is recognized but fails to execute.
+    /// COMMAND_INVALID if the command is not recognized.
+    virtual isc::data::ConstElementPtr command(const std::string& command,
+                                               isc::data::ConstElementPtr args);
+
+    // @brief Destructor
+    virtual ~DStubProcess();
+};
+
+
+/// @brief Test Derivation of the DControllerBase class.
+///
+/// DControllerBase is an abstract class and therefore requires a derivation
+/// for testing.  It allows testing the majority of the base class code
+/// without polluting production derivations (e.g. D2Process).  It uses
+/// DStubProcess as its application process class.  It is a full enough
+/// implementation to support running both stand alone and integrated.
+/// Obviously BIND10 connectivity is not available under unit tests, so
+/// testing here is limited to "failures" to communicate with BIND10.
+class DStubController : public DControllerBase {
+public:
+    /// @brief Static singleton instance method. This method returns the
+    /// base class singleton instance member.  It instantiates the singleton
+    /// and sets the base class instance member upon first invocation.
+    ///
+    /// @return returns a pointer reference to the singleton instance.
+    static DControllerBasePtr& instance();
+
+    /// @brief Defines a custom controller command string. This is a
+    /// custom command supported by DStubController.
+    static const char* stub_ctl_command_;
+
+    /// @brief Defines a custom command line option supported by
+    /// DStubController.
+    static const char* stub_option_x_;
+
+protected:
+    /// @brief Handles additional command line options that are supported
+    /// by DStubController.  This implementation supports an option "-x".
+    ///
+    /// @param option is the option "character" from the command line, without
+    /// any prefixing hyphen(s)
+    /// @optarg optarg is the argument value (if one) associated with the option
+    ///
+    /// @return returns true if the option is "x", otherwise ti returns false.
+    virtual bool customOption(int option, char *optarg);
+
+    /// @brief Instantiates an instance of DStubProcess.
+    ///
+    /// This implementation will fail if SimFailure is set to
+    /// ftCreateProcessException OR ftCreateProcessNull.
+    ///
+    /// @return returns a pointer to the new process instance (DProcessBase*)
+    /// or NULL if SimFailure is set to ftCreateProcessNull.
+    /// @throw throws std::runtime_error if SimFailure is set to
+    /// ftCreateProcessException.
+    virtual DProcessBase* createProcess();
+
+    /// @brief Executes custom controller commands are supported by
+    /// DStubController. This implementation supports one custom controller
+    /// command, stub_ctl_command_.  It will fail if SimFailure is set
+    /// to ftControllerCommand.
+    ///
+    /// @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.
+    /// @return an Element that contains the results of command composed
+    /// of an integer status value and a string explanation of the outcome.
+    /// The status value is:
+    /// COMMAND_SUCCESS if the command is recognized and executes successfully.
+    /// COMMAND_ERROR if the command is recognized but fails to execute.
+    /// COMMAND_INVALID if the command is not recognized.
+    virtual isc::data::ConstElementPtr customControllerCommand(
+            const std::string& command, isc::data::ConstElementPtr args);
+
+    /// @brief Provides a string of the additional command line options
+    /// supported by DStubController.  DStubController supports one
+    /// addition option, stub_option_x_.
+    ///
+    /// @return returns a string containing the option letters.
+    virtual const std::string getCustomOpts() const;
+
+private:
+    /// @brief Constructor is private to protect singleton integrity.
+    DStubController();
+
+public:
+    virtual ~DStubController();
+};
+
+/// @brief Abstract Test fixture class that wraps a DControllerBase. This class
+/// is a friend class of DControllerBase which allows it access to class
+/// content to facilitate testing.  It provides numerous wrapper methods for
+/// the protected and private methods and member of the base class.
+class DControllerTest : public ::testing::Test {
+public:
+
+    /// @brief Defines a function pointer for controller singleton fetchers.
+    typedef DControllerBasePtr& (*InstanceGetter)();
+
+    /// @brief Static storage of the controller class's singleton fetcher.
+    /// We need this this statically available for callbacks.
+    static InstanceGetter instanceGetter_;
+
+    /// @brief Constructor
+    ///
+    /// @param instance_getter is a function pointer to the static instance
+    /// method of the DControllerBase derivation under test.
+    DControllerTest(InstanceGetter instance_getter) {
+        // Set the static fetcher member, then invoke it via getController.
+        // This ensures the singleton is instantiated.
+        instanceGetter_ = instance_getter;
+        getController();
+    }
+
+    /// @brief Destructor
+    /// Note the controller singleton is destroyed. This is essential to ensure
+    /// a clean start between tests.
+    virtual ~DControllerTest() {
+        getController().reset();
+    }
+
+    /// @brief Convenience method that destructs and then recreates the
+    /// controller singleton under test.  This is handy for tests within
+    /// tests.
+    void resetController() {
+        getController().reset();
+        getController();
+    }
+
+    /// @brief Static method which returns the instance of the controller
+    /// under test.
+    /// @return returns a reference to the controller instance.
+    static DControllerBasePtr& getController() {
+        return ((*instanceGetter_)());
+    }
+
+    /// @brief Returns true if the Controller's name matches the given value.
+    ///
+    /// @param should_be is the value to compare against.
+    ///
+    /// @return returns true if the values are equal.
+    bool checkName(const std::string& should_be) {
+        return (getController()->getName().compare(should_be) == 0);
+    }
+
+    /// @brief Returns true if the Controller's spec file name matches the
+    /// given value.
+    ///
+    /// @param should_be is the value to compare against.
+    ///
+    /// @return returns true if the values are equal.
+    bool checkSpecFileName(const std::string& should_be) {
+        return (getController()->getSpecFileName().compare(should_be) == 0);
+    }
+
+    /// @brief Tests the existence of the Controller's application process.
+    ///
+    /// @return returns true if the process instance exists.
+    bool checkProcess() {
+        return (getController()->process_);
+    }
+
+    /// @brief Tests the existence of the Controller's IOService.
+    ///
+    /// @return returns true if the IOService exists.
+    bool checkIOService() {
+        return (getController()->io_service_);
+    }
+
+    /// @brief Gets the Controller's IOService.
+    ///
+    /// @return returns a reference to the IOService
+    IOServicePtr& getIOService() {
+        return (getController()->io_service_);
+    }
+
+    /// @brief Compares stand alone flag with the given value.
+    ///
+    /// @param value
+    ///
+    /// @return returns true if the stand alone flag is equal to the given
+    /// value.
+    bool checkStandAlone(bool value) {
+        return (getController()->isStandAlone() == value);
+    }
+
+    /// @brief Sets the controller's stand alone flag to the given value.
+    ///
+    /// @param value is the new value to assign.
+    ///
+    void setStandAlone(bool value) {
+        getController()->setStandAlone(value);
+    }
+
+    /// @brief Compares verbose flag with the given value.
+    ///
+    /// @param value
+    ///
+    /// @return returns true if the verbose flag is equal to the given value.
+    bool checkVerbose(bool value) {
+        return (getController()->isVerbose() == value);
+    }
+
+    /// @Wrapper to invoke the Controller's parseArgs method.  Please refer to
+    /// DControllerBase::parseArgs for details.
+    void parseArgs(int argc, char* argv[]) {
+        getController()->parseArgs(argc, argv);
+    }
+
+    /// @Wrapper to invoke the Controller's init method.  Please refer to
+    /// DControllerBase::init for details.
+    void initProcess() {
+        getController()->initProcess();
+    }
+
+    /// @Wrapper to invoke the Controller's establishSession method.  Please
+    /// refer to DControllerBase::establishSession for details.
+    void establishSession() {
+        getController()->establishSession();
+    }
+
+    /// @Wrapper to invoke the Controller's launch method.  Please refer to
+    /// DControllerBase::launch for details.
+    void launch(int argc, char* argv[]) {
+        optind = 1;
+        getController()->launch(argc, argv);
+    }
+
+    /// @Wrapper to invoke the Controller's disconnectSession method.  Please
+    /// refer to DControllerBase::disconnectSession for details.
+    void disconnectSession() {
+        getController()->disconnectSession();
+    }
+
+    /// @Wrapper to invoke the Controller's updateConfig method.  Please
+    /// refer to DControllerBase::updateConfig for details.
+    isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr
+                                            new_config) {
+        return (getController()->updateConfig(new_config));
+    }
+
+    /// @Wrapper to invoke the Controller's executeCommand method.  Please
+    /// refer to DControllerBase::executeCommand for details.
+    isc::data::ConstElementPtr executeCommand(const std::string& command,
+                                       isc::data::ConstElementPtr args){
+        return (getController()->executeCommand(command, args));
+    }
+
+    /// @brief Callback that will generate shutdown command via the
+    /// command callback function.
+    static void genShutdownCallback() {
+        isc::data::ElementPtr arg_set;
+        DControllerBase::commandHandler(SHUT_DOWN_COMMAND, arg_set);
+    }
+
+    /// @brief Callback that throws an exception.
+    static void genFatalErrorCallback() {
+        isc_throw (DProcessBaseError, "simulated fatal error");
+    }
+};
+
+}; // namespace isc::d2
+}; // namespace isc
+
+#endif



More information about the bind10-changes mailing list