Browse Source

[2955] Addressed review comments. Most notably, renamed DProcess
to DProcessBase.

Thomas Markwalder 12 years ago
parent
commit
d7fe718898

+ 2 - 1
src/bin/d2/Makefile.am

@@ -48,7 +48,8 @@ pkglibexec_PROGRAMS = b10-d2
 
 b10_d2_SOURCES  = main.cc
 b10_d2_SOURCES += d2_log.cc d2_log.h
-b10_d2_SOURCES += d2_process.cc d2_process.h d_process.h
+b10_d2_SOURCES += d2_process.h 
+b10_d2_SOURCES += d2_process.cc d2_process.h
 
 nodist_b10_d2_SOURCES = d2_messages.h d2_messages.cc
 EXTRA_DIST += d2_messages.mes

+ 14 - 18
src/bin/d2/d2_messages.mes

@@ -14,39 +14,35 @@
 
 $NAMESPACE isc::d2
 
-% D2_STARTING : service starting
-This is a debug message issued during a D2 service startup.
+% D2CTL_STARTING DHCP-DDNS controller starting, pid: %1
+This is an informational message issued when controller for DHCP-DDNS 
+service first starts.
 
-% D2_START_INFO pid: %1, verbose: %2, standalone: %3
-This is a debug message issued during the D2 service startup.
-It lists some information about the parameters with which the
-process is running.
+% D2CTL_STOPPING DHCP-DDNS 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.
 
-% D2_SHUTDOWN : service is performing a normal shutting down
-This is a debug message issued when the D2 service shuts down
-normally in response to command to stop.
+% 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_SHUTDOWN : process is performing a normal shutting down
-This is a debug message issued when the D2 process shuts down
-normally in response to service directive to stop.
-
-% D2PRC_RUN_ENTER : process has entered the event loop. 
+% D2PRC_RUN_ENTER process has entered the event loop
 This is a debug message issued when the D2 process enters it's
 run method. 
 
-% D2PRC_RUN_EXIT : process is exiting the event loop.
+% D2PRC_RUN_EXIT process is exiting the event loop
 This is a debug message issued when the D2 process exits the
 in event loop. 
 
-% D2PRC_FAILED : process experienced a fatal error.
+% D2PRC_FAILED process experienced a fatal error: %1
 This is a debug message issued when the D2 process encounters an
 unrecoverable error from within the event loop.
 
-% D2PRC_CONFIGURE : new configuration received: %1
+% D2PRC_CONFIGURE new configuration received: %1
 This is a debug message issued when the D2 process configure method
 has been invoked.
 
-% D2PRC_COMMAND : command directive received, command: %1 - args: %2
+% D2PRC_COMMAND command directive received, command: %1 - args: %2
 This is a debug message issued when the D2 process command method
 has been invoked.
 

+ 5 - 4
src/bin/d2/d2_process.cc

@@ -22,7 +22,7 @@ namespace isc {
 namespace d2 {
 
 D2Process::D2Process(const char* name, IOServicePtr io_service) 
-    : DProcess(name, io_service) {
+    : DProcessBase(name, io_service) {
 };
 
 void
@@ -38,9 +38,10 @@ D2Process::run() {
     // or the call to run will continue to block, and shutdown will not
     // occur.
     LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_ENTER);
-    while (!shut_down_) {
+    IOServicePtr& io_service = getIoService();
+    while (!shouldShutDown()) {
         try {
-            io_service_->run_one();
+            io_service->run_one();
         } catch (const std::exception& ex) {
             LOG_FATAL(d2_logger, D2PRC_FAILED).arg(ex.what());
             return (EXIT_FAILURE); 
@@ -54,7 +55,7 @@ D2Process::run() {
 int 
 D2Process::shutdown() {
     LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_SHUTDOWN);
-    shut_down_ = true;
+    setShutdownFlag(true);
     return (0);
 }    
 

+ 3 - 3
src/bin/d2/d2_process.h

@@ -25,10 +25,10 @@ namespace d2 {
 /// 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 DProcess interface, which structures it such that it
+/// It implements the DProcessBase interface, which structures it such that it
 /// is a managed "application", controlled by a management layer. 
 
-class D2Process : public DProcess {
+class D2Process : public DProcessBase {
 public:
     /// @brief Constructor
     ///
@@ -37,7 +37,7 @@ public:
     /// @param io_service is the io_service used by the caller for
     /// asynchronous event handling.
     ///
-    /// @throw DProcessError 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 

+ 32 - 16
src/bin/d2/d_process.h

@@ -27,25 +27,25 @@ namespace isc {
 namespace d2 {
 
 /// @brief Exception thrown if the process encountered an operational error.
-class DProcessError : public isc::Exception {
+class DProcessBaseError : public isc::Exception {
 public:
-    DProcessError(const char* file, size_t line, const char* what) :
+    DProcessBaseError(const char* file, size_t line, const char* what) :
         isc::Exception(file, line, what) { };
 };
 
 /// @brief Application Process Interface
 ///
-/// DProcess is an abstract class represents the primary "application" level  
-/// object in a "managed" asyncrhonous application.  It provides a uniform 
+/// 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
 /// 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 DProcess.  This allows management layer IO 
+/// 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 fo management layer 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 DProcess {
+class DProcessBase {
 public:
     /// @brief Constructor
     ///
@@ -54,12 +54,12 @@ public:
     /// @param io_service is the io_service used by the caller for
     /// asynchronous event handling.
     ///
-    /// @throw DProcessError is io_service is NULL. 
-    DProcess(const char* name, IOServicePtr io_service) : name_(name),
-        io_service_(io_service), shut_down_(false) {
+    /// @throw DProcessBaseError is io_service is NULL. 
+    DProcessBase(const char* name, IOServicePtr io_service) : name_(name),
+        io_service_(io_service), shut_down_flag(false) {
 
         if (!io_service_) {
-            isc_throw (DProcessError, "IO Service cannot be null");
+            isc_throw (DProcessBaseError, "IO Service cannot be null");
         }
     };
 
@@ -112,9 +112,25 @@ public:
             const std::string& command, isc::data::ConstElementPtr args) = 0; 
 
     /// @brief Destructor 
-    virtual ~DProcess(){};
+    virtual ~DProcessBase(){};
 
-protected:
+    bool shouldShutDown() { 
+        return shut_down_flag; 
+    }
+
+    void setShutdownFlag(bool value) { 
+        shut_down_flag = value; 
+    }
+
+    const std::string& getName() {
+        return (name_);
+    }
+
+    IOServicePtr& getIoService() {
+        return (io_service_);
+    }
+
+private:
     /// @brief Text label for the process. Generally used in log statements, 
     /// but otherwise can be arbitrary. 
     std::string name_;
@@ -123,11 +139,11 @@ protected:
     IOServicePtr io_service_;
 
     /// @brief Boolean flag set when shutdown has been requested.
-    bool shut_down_;
+    bool shut_down_flag;
 };
 
-/// @brief Defines a shared pointer to DProcess.
-typedef boost::shared_ptr<DProcess> DProcessPtr;
+/// @brief Defines a shared pointer to DProcessBase.
+typedef boost::shared_ptr<DProcessBase> DProcessBasePtr;
 
 }; // namespace isc::d2 
 }; // namespace isc

+ 3 - 5
src/bin/d2/main.cc

@@ -82,16 +82,14 @@ main(int argc, char* argv[]) {
                          ((verbose_mode && stand_alone)
                            ? isc::log::DEBUG : isc::log::INFO),
                          isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone);
-    LOG_INFO(d2_logger, D2_STARTING);
-    LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2_START_INFO)
-              .arg(getpid()).arg(verbose_mode ? "yes" : "no")
-              .arg(stand_alone ? "yes" : "no" );
+
+    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, D2_SHUTDOWN);
+    LOG_INFO(d2_logger, D2CTL_STOPPING);
     return (EXIT_SUCCESS);
 }
 

+ 1 - 0
src/bin/d2/tests/Makefile.am

@@ -52,6 +52,7 @@ if HAVE_GTEST
 TESTS += d2_unittests
 
 d2_unittests_SOURCES = ../d2_log.h ../d2_log.cc
+d2_unittests_SOURCES += ../d2_process.h 
 d2_unittests_SOURCES += ../d2_process.cc ../d2_process.h ../d_process.h
 d2_unittests_SOURCES += d2_unittests.cc
 d2_unittests_SOURCES += d2_process_unittests.cc

+ 16 - 14
src/bin/d2/tests/d2_process_unittests.cc

@@ -35,7 +35,7 @@ class D2ProcessTest : public ::testing::Test {
 public:
 
     /// @brief Static instance accessible via test callbacks.
-    static DProcessPtr process_;
+    static DProcessBasePtr process_;
 
     /// @brief Constructor
     D2ProcessTest() {
@@ -56,7 +56,7 @@ public:
 
     /// @brief Callback that throws an exception.
     static void genFatalErrorCallback() {
-        isc_throw (DProcessError, "simulated fatal error");
+        isc_throw (DProcessBaseError, "simulated fatal error");
     }
 
     /// @brief IOService for event processing. Fills in for IOservice
@@ -65,7 +65,7 @@ public:
 };
 
 // Define the static process instance
-DProcessPtr D2ProcessTest::process_;
+DProcessBasePtr D2ProcessTest::process_;
 
 
 /// @brief Verifies D2Process constructor behavior.
@@ -75,7 +75,7 @@ TEST(D2Process, construction) {
     // Verify that the constructor will fail if given an empty
     // io service.
     IOServicePtr lcl_io_service;
-    EXPECT_THROW (D2Process("TestProcess", lcl_io_service), DProcessError);
+    EXPECT_THROW (D2Process("TestProcess", lcl_io_service), DProcessBaseError);
 
     // Verify that the constructor succeeds with a valid io_service
     lcl_io_service.reset(new isc::asiolink::IOService());
@@ -115,16 +115,16 @@ TEST_F(D2ProcessTest, command) {
 /// the run method to exit gracefully with a return value of EXIT_SUCCESS.
 TEST_F(D2ProcessTest, normalShutdown) {
     // Use an asiolink IntervalTimer and callback to generate the
-    // shutdown invocation. 
+    // shutdown invocation. (Note IntervalTimer setup is in milliseconds).
     isc::asiolink::IntervalTimer timer(*io_service_);
-    timer.setup(genShutdownCallback, 2*1000);
+    timer.setup(genShutdownCallback, 2 * 1000);
 
     // Record start time, and invoke run().
-    ptime start = second_clock::universal_time();
+    ptime start = microsec_clock::universal_time();
     int rcode = process_->run();
 
     // Record stop time.
-    ptime stop = second_clock::universal_time();
+    ptime stop = microsec_clock::universal_time();
 
     // Verify normal shutdown status.
     EXPECT_EQ(EXIT_SUCCESS, rcode);
@@ -133,23 +133,24 @@ TEST_F(D2ProcessTest, normalShutdown) {
     // timer duration.  This demonstrates that the shutdown was driven
     // by an io_service event and callback.
     time_duration elapsed = stop - start;
-    EXPECT_EQ(2L, elapsed.seconds());
+    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.
 TEST_F(D2ProcessTest, fatalErrorShutdown) {
     // Use an asiolink IntervalTimer and callback to generate the
-    // the exception.
+    // the exception.  (Note IntervalTimer setup is in milliseconds).
     isc::asiolink::IntervalTimer timer(*io_service_);
-    timer.setup(genFatalErrorCallback, 2*1000);
+    timer.setup(genFatalErrorCallback, 2 * 1000);
 
     // Record start time, and invoke run().
-    ptime start = second_clock::universal_time();
+    ptime start = microsec_clock::universal_time();
     int rcode = process_->run();
 
     // Record stop time.
-    ptime stop = second_clock::universal_time();
+    ptime stop = microsec_clock::universal_time();
 
     // Verify failure status.
     EXPECT_EQ(EXIT_FAILURE, rcode);
@@ -158,7 +159,8 @@ TEST_F(D2ProcessTest, fatalErrorShutdown) {
     // timer duration.  This demonstrates that the anomaly occurred
     // during io callback processing. 
     time_duration elapsed = stop - start;
-    EXPECT_EQ(2L, elapsed.seconds());
+    EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 && 
+                elapsed.total_milliseconds() <= 2100);
 }
 
 } // end of anonymous namespace

+ 1 - 1
src/bin/d2/tests/d2_test.py

@@ -161,7 +161,7 @@ class TestD2Daemon(unittest.TestCase):
         # soon enough to catch it.
         (returncode, output, error) = self.runCommand(["../b10-d2", "-s"])
         output_text = str(output) + str(error)
-        self.assertEqual(output_text.count("D2_STARTING"), 1)
+        self.assertEqual(output_text.count("D2CTL_STARTING"), 1)
 
 if __name__ == '__main__':
     unittest.main()