[svn] commit: r3686 - in /branches/trac347: ./ src/bin/auth/ src/bin/auth/benchmarks/ src/bin/auth/tests/ src/bin/bind10/

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Dec 1 04:25:19 UTC 2010


Author: y-aharen
Date: Wed Dec  1 04:25:19 2010
New Revision: 3686

Log:
add query counters in b10-auth, interval timer class in asio_link and unittests (ticket #347)

Added:
    branches/trac347/src/bin/auth/stats.cc
    branches/trac347/src/bin/auth/stats.h
Modified:
    branches/trac347/ChangeLog
    branches/trac347/src/bin/auth/Makefile.am
    branches/trac347/src/bin/auth/asio_link.cc
    branches/trac347/src/bin/auth/asio_link.h
    branches/trac347/src/bin/auth/auth.spec.pre.in
    branches/trac347/src/bin/auth/auth_srv.cc
    branches/trac347/src/bin/auth/auth_srv.h
    branches/trac347/src/bin/auth/benchmarks/Makefile.am
    branches/trac347/src/bin/auth/main.cc
    branches/trac347/src/bin/auth/tests/Makefile.am
    branches/trac347/src/bin/auth/tests/asio_link_unittest.cc
    branches/trac347/src/bin/auth/tests/auth_srv_unittest.cc
    branches/trac347/src/bin/bind10/bind10.py.in

Modified: branches/trac347/ChangeLog
==============================================================================
--- branches/trac347/ChangeLog (original)
+++ branches/trac347/ChangeLog Wed Dec  1 04:25:19 2010
@@ -1,3 +1,10 @@
+  TBD.  [func]		y-aharen
+	src/bin/auth: Added a feature to count query and send counter
+	values to b10-stats periodically. To support it, added wrapping
+	class of asio::deadline_timer to use as interval timer.
+	Added a command 'sendstats' to send counter values at once.
+	(Trac #347, svn rxxxx)
+
   122.  [func]		stephen
 	src/bin/bind10: Added configuration options to Boss to determine
 	whether to start the authoritative server, recursive server (or

Modified: branches/trac347/src/bin/auth/Makefile.am
==============================================================================
--- branches/trac347/src/bin/auth/Makefile.am (original)
+++ branches/trac347/src/bin/auth/Makefile.am Wed Dec  1 04:25:19 2010
@@ -58,6 +58,7 @@
 b10_auth_SOURCES = auth_srv.cc auth_srv.h
 b10_auth_SOURCES += change_user.cc change_user.h
 b10_auth_SOURCES += common.h
+b10_auth_SOURCES += stats.cc stats.h
 b10_auth_SOURCES += main.cc
 b10_auth_LDADD =  $(top_builddir)/src/lib/datasrc/libdatasrc.la
 b10_auth_LDADD += $(top_builddir)/src/lib/dns/libdns++.la

Modified: branches/trac347/src/bin/auth/asio_link.cc
==============================================================================
--- branches/trac347/src/bin/auth/asio_link.cc (original)
+++ branches/trac347/src/bin/auth/asio_link.cc Wed Dec  1 04:25:19 2010
@@ -666,4 +666,78 @@
         impl_->tcp6_server_->setCallBack(&impl_->callback_);
     }
 }
-}
+
+class IntervalTimerImpl {
+private:
+    // prohibit copy to avoid the function be called twice
+    IntervalTimerImpl(const IntervalTimerImpl& source);
+    IntervalTimerImpl& operator=(const IntervalTimerImpl& source);
+public:
+    IntervalTimerImpl(asio::io_service& io_service);
+    ~IntervalTimerImpl();
+    bool setupTimer(const IntervalTimer::Callback& cbfunc,
+                    const uint32_t interval);
+    void callback(const asio::error_code& error);
+private:
+    void updateTimer();
+    IntervalTimer::Callback cbfunc_;
+    // interval in seconds
+    uint32_t interval_;
+    asio::deadline_timer timer_;
+};
+
+IntervalTimerImpl::IntervalTimerImpl(asio::io_service& io_service) :
+    timer_(io_service)
+{}
+
+IntervalTimerImpl::~IntervalTimerImpl() {
+    timer_.cancel();
+}
+
+bool
+IntervalTimerImpl::setupTimer(const IntervalTimer::Callback& cbfunc,
+                              const uint32_t interval)
+{
+    // interval value must be positive
+    assert(interval > 0);
+    cbfunc_ = cbfunc;
+    interval_ = interval;
+    // start timer
+    updateTimer();
+    return (true);
+}
+
+void
+IntervalTimerImpl::updateTimer() {
+    // update expire time (current time + interval_)
+    timer_.expires_from_now(boost::posix_time::seconds(interval_));
+    // restart timer
+    timer_.async_wait(boost::bind(&IntervalTimerImpl::callback, this, _1));
+}
+
+void
+IntervalTimerImpl::callback(const asio::error_code& cancelled) {
+    assert(!cbfunc_.empty());
+    // skip function call in case the timer was cancelled
+    if (!cancelled) {
+        cbfunc_();
+        // restart timer
+        updateTimer();
+    }
+}
+
+IntervalTimer::IntervalTimer(asio::io_service& io_service) {
+    impl_ = new IntervalTimerImpl(io_service);
+}
+
+IntervalTimer::~IntervalTimer() {
+    delete impl_;
+}
+
+bool
+IntervalTimer::setupTimer(const Callback& cbfunc,
+                                const uint32_t interval)
+{
+    return (impl_->setupTimer(cbfunc, interval));
+}
+}

Modified: branches/trac347/src/bin/auth/asio_link.h
==============================================================================
--- branches/trac347/src/bin/auth/asio_link.h (original)
+++ branches/trac347/src/bin/auth/asio_link.h Wed Dec  1 04:25:19 2010
@@ -89,6 +89,7 @@
 
 namespace asio_link {
 class IOServiceImpl;
+struct IntervalTimerImpl;
 
 /// \brief An exception that is thrown if an error occurs within the IO
 /// module.  This is mainly intended to be a wrapper exception class for
@@ -444,6 +445,46 @@
 private:
     IOServiceImpl* impl_;
 };
+
+/// \brief The \c IntervalTimer class is a wrapper for the ASIO \c deadline_timer
+/// class.
+///
+/// This class is implemented to use boost::deadline_timer as interval timer.
+/// Copy of this class is prohibited not to call the callback function twice.
+class IntervalTimer {
+public:
+    /// \name The type of timer callback function
+    typedef boost::function<void(void)> Callback;
+
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IntervalTimer(const IntervalTimer& source);
+    IntervalTimer& operator=(const IntervalTimer& source);
+public:
+    /// \brief The constructor with asio::io_service.
+    ///
+    /// \param io_service A reference to an instance of asio::io_service
+    IntervalTimer(asio::io_service& io_service);
+    /// \brief The destructor.
+    ~IntervalTimer();
+    //@}
+
+    /// \brief Register timer callback function
+    ///
+    /// \param cbfunc A reference to a function to call back
+    /// when the timer is expired
+    /// \param interval Interval in seconds
+    ///
+    /// \return \c true on success
+    bool setupTimer(const Callback& cbfunc, const uint32_t interval);
+private:
+    IntervalTimerImpl* impl_;
+};
 }      // asio_link
 #endif // __ASIO_LINK_H
 

Modified: branches/trac347/src/bin/auth/auth.spec.pre.in
==============================================================================
--- branches/trac347/src/bin/auth/auth.spec.pre.in (original)
+++ branches/trac347/src/bin/auth/auth.spec.pre.in Wed Dec  1 04:25:19 2010
@@ -14,6 +14,11 @@
         "command_name": "shutdown",
         "command_description": "Shut down authoritative DNS server",
         "command_args": []
+      },
+      {
+        "command_name": "sendstats",
+        "command_description": "Send statistics data to b10-stats at once",
+        "command_args": []
       }
     ]
   }

Modified: branches/trac347/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/trac347/src/bin/auth/auth_srv.cc (original)
+++ branches/trac347/src/bin/auth/auth_srv.cc Wed Dec  1 04:25:19 2010
@@ -128,10 +128,13 @@
 
 AuthSrv::AuthSrv(const bool use_cache, AbstractXfroutClient& xfrout_client) :
     impl_(new AuthSrvImpl(use_cache, xfrout_client))
-{}
+{
+    counter = new statistics::Counter(impl_->verbose_mode_);
+}
 
 AuthSrv::~AuthSrv() {
     delete impl_;
+    delete counter;
 }
 
 namespace {
@@ -214,6 +217,11 @@
     impl_->config_session_ = config_session;
 }
 
+void
+AuthSrv::setStatsSession(AbstractSession* stats_session) {
+    counter->setStatsSession(stats_session);
+}
+
 ModuleCCSession*
 AuthSrv::getConfigSession() const {
     return (impl_->config_session_);
@@ -264,6 +272,19 @@
 
     if (impl_->verbose_mode_) {
         cerr << "[b10-auth] received a message:\n" << message.toText() << endl;
+    }
+
+    // increment Query Counter
+    if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
+        counter->inc(statistics::Counter::COUNTER_UDP);
+    } else if (io_message.getSocket().getProtocol() == IPPROTO_TCP) {
+        counter->inc(statistics::Counter::COUNTER_TCP);
+    } else {
+        // unknown protocol
+        if (impl_->verbose_mode_) {
+            cerr << "[b10-auth] Unknown protocol: " <<
+                     io_message.getSocket().getProtocol() << endl;
+        }
     }
 
     // Perform further protocol-level validation.
@@ -543,3 +564,10 @@
         return (isc::config::createAnswer(1, error.what()));
     }
 }
+
+asio_link::IntervalTimer::Callback
+AuthSrv::getStatsCallback() {
+    // just invoke statistics::Counter::getStatsCallback()
+    // and return its return value
+    return (counter->getCallback());
+}

Modified: branches/trac347/src/bin/auth/auth_srv.h
==============================================================================
--- branches/trac347/src/bin/auth/auth_srv.h (original)
+++ branches/trac347/src/bin/auth/auth_srv.h Wed Dec  1 04:25:19 2010
@@ -21,6 +21,12 @@
 
 #include <cc/data.h>
 #include <config/ccsession.h>
+
+/// for the typedef of asio_link::IntervalTimer::Callback
+#include <auth/asio_link.h>
+
+// for class statistics::Counter
+#include <auth/stats.h>
 
 namespace isc {
 namespace dns {
@@ -199,8 +205,28 @@
     /// is shutdown.
     ///
     void setXfrinSession(isc::cc::AbstractSession* xfrin_session);
+
+    /// \brief Set the communication session with Statistics.
+    ///
+    void setStatsSession(isc::cc::AbstractSession* stats_session);
+
+    /// \brief Return the function that sends statistics information
+    /// to Statistics module.
+    /// 
+    /// This function returns the return value of
+    /// statistics::Counter::getCallback().
+    ///
+    /// \return \c boost::function which contains the procedure
+    /// to send statistics.
+    asio_link::IntervalTimer::Callback getStatsCallback();
 private:
     AuthSrvImpl* impl_;
+
+    // TODO: consider where to put the counter.
+    // Currently, count-up is in AuthSrv::processMessage.
+    // In the future, count-up will be in AuthSrvImpl::process*Query
+    // and this declaration will be moved into AuthSrvImpl.
+    statistics::Counter *counter;
 };
 
 #endif // __AUTH_SRV_H

Modified: branches/trac347/src/bin/auth/benchmarks/Makefile.am
==============================================================================
--- branches/trac347/src/bin/auth/benchmarks/Makefile.am (original)
+++ branches/trac347/src/bin/auth/benchmarks/Makefile.am Wed Dec  1 04:25:19 2010
@@ -9,6 +9,7 @@
 noinst_PROGRAMS = query_bench
 query_bench_SOURCES = query_bench.cc
 query_bench_SOURCES += ../auth_srv.h ../auth_srv.cc
+query_bench_SOURCES += ../stats.h ../stats.cc
 
 query_bench_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
 query_bench_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la

Modified: branches/trac347/src/bin/auth/main.cc
==============================================================================
--- branches/trac347/src/bin/auth/main.cc (original)
+++ branches/trac347/src/bin/auth/main.cc Wed Dec  1 04:25:19 2010
@@ -59,6 +59,10 @@
 const string PROGRAM = "Auth";
 const char* DNSPORT = "5300";
 
+// Note: this value must be greater than 0.
+// TODO: make it configurable via command channel.
+const uint32_t STATS_SEND_INTERVAL_SEC = 60;
+
 /* need global var for config/command handlers.
  * todo: turn this around, and put handlers in the authserver
  * class itself? */
@@ -81,6 +85,13 @@
         answer = createAnswer(0, args);
     } else if (command == "shutdown") {
         io_service->stop();
+    } else if (command == "sendstats") {
+        if (verbose_mode) {
+            cerr << "[b10-auth] command 'sendstats' received" << endl;
+        }
+        if (auth_server != NULL) {
+            auth_server->getStatsCallback()();
+        }
     }
     
     return (answer);
@@ -154,7 +165,10 @@
     // XXX: we should eventually pass io_service here.
     Session* cc_session = NULL;
     Session* xfrin_session = NULL;
+    Session* stats_session = NULL;
+    asio_link::IntervalTimer* itimer = NULL;
     bool xfrin_session_established = false; // XXX (see Trac #287)
+    bool stats_session_established = false; // XXX (see Trac #287)
     ModuleCCSession* config_session = NULL;
     string xfrout_socket_path;
     if (getenv("B10_FROM_BUILD") != NULL) {
@@ -209,14 +223,29 @@
         xfrin_session_established = true;
         cout << "[b10-auth] Xfrin session channel established." << endl;
 
+        stats_session = new Session(io_service->get_io_service());
+        cout << "[b10-auth] Stats session channel created." << endl;
+        stats_session->establish(NULL);
+        stats_session_established = true;
+        cout << "[b10-auth] Stats session channel established." << endl;
+
         // XXX: with the current interface to asio_link we have to create
         // auth_server before io_service while Session needs io_service.
         // In a next step of refactoring we should make asio_link independent
         // from auth_server, and create io_service, auth_server, and
         // sessions in that order.
         auth_server->setXfrinSession(xfrin_session);
+        auth_server->setStatsSession(stats_session);
         auth_server->setConfigSession(config_session);
         auth_server->updateConfig(ElementPtr());
+
+        // create interval timer instance
+        itimer = new asio_link::IntervalTimer(io_service->get_io_service());
+        // set up interval timer
+        // register function to send statistics with interval
+        itimer->setupTimer(auth_server->getStatsCallback(),
+                           STATS_SEND_INTERVAL_SEC);
+        cout << "[b10-auth] Interval timer set to send stats." << endl;
 
         cout << "[b10-auth] Server started." << endl;
         io_service->run();
@@ -225,10 +254,16 @@
         ret = 1;
     }
 
+    if (stats_session_established) {
+        stats_session->disconnect();
+    }
+
     if (xfrin_session_established) {
         xfrin_session->disconnect();
     }
 
+    delete itimer;
+    delete stats_session;
     delete xfrin_session;
     delete config_session;
     delete cc_session;

Modified: branches/trac347/src/bin/auth/tests/Makefile.am
==============================================================================
--- branches/trac347/src/bin/auth/tests/Makefile.am (original)
+++ branches/trac347/src/bin/auth/tests/Makefile.am Wed Dec  1 04:25:19 2010
@@ -22,6 +22,7 @@
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
 run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
 run_unittests_SOURCES += ../change_user.h ../change_user.cc
+run_unittests_SOURCES += ../stats.h ../stats.cc
 run_unittests_SOURCES += auth_srv_unittest.cc
 run_unittests_SOURCES += change_user_unittest.cc
 run_unittests_SOURCES += asio_link_unittest.cc

Modified: branches/trac347/src/bin/auth/tests/asio_link_unittest.cc
==============================================================================
--- branches/trac347/src/bin/auth/tests/asio_link_unittest.cc (original)
+++ branches/trac347/src/bin/auth/tests/asio_link_unittest.cc Wed Dec  1 04:25:19 2010
@@ -252,6 +252,15 @@
                             callback_data_.size(),
                             expected_data, expected_datasize);
     }
+    void doTimerTest(asio_link::IntervalTimer* itimer) {
+        // interval timer test
+        // set test_obj_->timerCallBack() as callback function
+        // and check that the function was called
+        timer_called_ = false;
+        EXPECT_TRUE(itimer->setupTimer(TimerCallBack(this), 1));
+        io_service_->run();
+        EXPECT_TRUE(timer_called_);
+    }
 private:
     class ASIOCallBack : public std::unary_function<IOMessage, void> {
     public:
@@ -273,12 +282,27 @@
             io_message.getDataSize());
         io_service_->stop();
     }
+private:
+    class TimerCallBack : public std::unary_function<void, void> {
+    public:
+        TimerCallBack(ASIOLinkTest* test_obj) : test_obj_(test_obj) {}
+        void operator()(void) const {
+            test_obj_->timerCallBack();
+        }
+    private:
+        ASIOLinkTest* test_obj_;
+    };
+    void timerCallBack() {
+        timer_called_ = true;
+        io_service_->stop();
+    }
 protected:
     IOService* io_service_;
     int callback_protocol_;
     int callback_native_;
     string callback_address_;
     vector<uint8_t> callback_data_;
+    bool timer_called_;
     int sock_;
 private:
     struct addrinfo* res_;
@@ -354,4 +378,12 @@
     EXPECT_THROW(sendTCP(AF_INET6), IOError);
 }
 
-}
+TEST_F(ASIOLinkTest, startIntervalTimer) {
+    // Create asio_link::IntervalTimer and setup.
+    // Then run IOService and test if the callback function is called.
+    setIOService(false, false);
+    asio_link::IntervalTimer *itimer = new asio_link::IntervalTimer(io_service_->get_io_service());
+    doTimerTest(itimer);
+    delete itimer;
+}
+}

Modified: branches/trac347/src/bin/auth/tests/auth_srv_unittest.cc
==============================================================================
--- branches/trac347/src/bin/auth/tests/auth_srv_unittest.cc (original)
+++ branches/trac347/src/bin/auth/tests/auth_srv_unittest.cc Wed Dec  1 04:25:19 2010
@@ -44,6 +44,7 @@
 using namespace isc::data;
 using namespace isc::xfr;
 using namespace asio_link;
+using namespace statistics;
 
 namespace {
 const char* const CONFIG_TESTDB =
@@ -120,15 +121,18 @@
                     qclass(RRClass::IN()), qtype(RRType::A()),
                     io_message(NULL), endpoint(NULL), request_obuffer(0),
                     request_renderer(request_obuffer),
-                    response_obuffer(0), response_renderer(response_obuffer)
+                    response_obuffer(0), response_renderer(response_obuffer),
+                    counter(counter_verbose)
     {
         server.setXfrinSession(&notify_session);
+        server.setStatsSession(&stats_session);
     }
     ~AuthSrvTest() {
         delete io_message;
         delete endpoint;
     }
     MockSession notify_session;
+    MockSession stats_session;
     MockXfroutClient xfrout;
     AuthSrv server;
     Message request_message;
@@ -145,6 +149,12 @@
     OutputBuffer response_obuffer;
     MessageRenderer response_renderer;
     vector<uint8_t> data;
+    // for Counter unittest
+    // TODO: consider where to put Counter
+    // AuthSrvTest is now includes a test for Counter
+    // In future make a test class CounterTest
+    bool counter_verbose;
+    Counter counter;
 
     void createDataFromFile(const char* const datafile, int protocol);
     void createRequestMessage(const Opcode& opcode, const Name& request_name,
@@ -767,4 +777,52 @@
     server.setCacheSlots(0);
     EXPECT_EQ(00, server.getCacheSlots());
 }
-}
+
+TEST_F(AuthSrvTest, statsCallback) {
+    // getStatsCallback() test
+    // expect returning a valid function
+    asio_link::IntervalTimer::Callback cbFunc;
+    cbFunc = server.getStatsCallback();
+    EXPECT_FALSE(cbFunc.empty());
+}
+
+TEST_F(AuthSrvTest, sendStatsWithoutSession) {
+    // to cover the code path in case the stats session is not set
+    // expect to put an error message
+    server.setStatsSession(NULL);
+    bool verbose = server.getVerbose();
+    server.setVerbose(true);
+    server.getStatsCallback()();
+    server.setVerbose(verbose);
+}
+
+//
+// statistics::Counter unittest
+
+TEST_F(AuthSrvTest, counter_incUDP) {
+    counter.inc(Counter::COUNTER_UDP);
+}
+
+TEST_F(AuthSrvTest, counter_incTCP) {
+    counter.inc(Counter::COUNTER_TCP);
+}
+
+TEST_F(AuthSrvTest, counter_incUnknown) {
+    EXPECT_THROW(counter.inc(Counter::COUNTER_TYPES), std::out_of_range);
+}
+
+TEST_F(AuthSrvTest, counter_getCallback) {
+    // getCallback() test
+    // expect returning a valid function
+    asio_link::IntervalTimer::Callback cbFunc;
+    cbFunc = counter.getCallback();
+    EXPECT_FALSE(cbFunc.empty());
+}
+
+TEST_F(AuthSrvTest, counter_sendStatsWithSession) {
+    // Test the function to send statistics information to b10-stats
+    // expect to run without throwing any exception
+    counter.setStatsSession(&stats_session);
+    counter.getCallback()();
+}
+}

Modified: branches/trac347/src/bin/bind10/bind10.py.in
==============================================================================
--- branches/trac347/src/bin/bind10/bind10.py.in (original)
+++ branches/trac347/src/bin/bind10/bind10.py.in Wed Dec  1 04:25:19 2010
@@ -544,10 +544,10 @@
         self.cc_session.group_sendmsg(cmd, "ConfigManager", "ConfigManager")
         self.cc_session.group_sendmsg(cmd, "Auth", "Auth")
         self.cc_session.group_sendmsg(cmd, "Recurse", "Recurse")
+        self.cc_session.group_sendmsg(cmd, "Stats", "Stats")
         self.cc_session.group_sendmsg(cmd, "Xfrout", "Xfrout")
         self.cc_session.group_sendmsg(cmd, "Xfrin", "Xfrin")
         self.cc_session.group_sendmsg(cmd, "Zonemgr", "Zonemgr")
-        self.cc_session.group_sendmsg(cmd, "Boss", "Stats")
 
     def stop_process(self, process):
         """Stop the given process, friendly-like."""




More information about the bind10-changes mailing list