Browse Source

[trac775] fix change log confilct for

hanfeng 14 years ago
parent
commit
fb4a0a36ba
100 changed files with 1087 additions and 562 deletions
  1. 21 1
      ChangeLog
  2. 12 4
      configure.ac
  3. 1 0
      src/bin/auth/Makefile.am
  4. 6 3
      src/bin/auth/auth_srv.cc
  5. 16 16
      src/bin/auth/auth_srv.h
  6. 1 0
      src/bin/auth/benchmarks/Makefile.am
  7. 5 2
      src/bin/auth/benchmarks/query_bench.cc
  8. 6 2
      src/bin/auth/main.cc
  9. 1 0
      src/bin/auth/tests/Makefile.am
  10. 3 1
      src/bin/auth/tests/auth_srv_unittest.cc
  11. 1 1
      src/bin/auth/tests/command_unittest.cc
  12. 2 1
      src/bin/auth/tests/config_unittest.cc
  13. 38 11
      src/bin/bind10/bind10.8
  14. 51 8
      src/bin/bind10/bind10.xml
  15. 1 1
      src/bin/cfgmgr/Makefile.am
  16. 28 0
      src/bin/cfgmgr/b10-cfgmgr.py.in
  17. 1 0
      src/bin/cfgmgr/plugins/Makefile.am
  18. 34 0
      src/bin/cfgmgr/plugins/README
  19. 2 1
      src/bin/cfgmgr/tests/Makefile.am
  20. 31 0
      src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in
  21. 34 0
      src/bin/cfgmgr/tests/testdata/plugins/testplugin.py
  22. 3 1
      src/bin/host/host.cc
  23. 3 0
      src/bin/resolver/Makefile.am
  24. 4 2
      src/bin/resolver/main.cc
  25. 8 4
      src/bin/resolver/resolver.cc
  26. 22 22
      src/bin/resolver/resolver.h
  27. 1 1
      src/bin/resolver/response_scrubber.cc
  28. 2 2
      src/bin/resolver/response_scrubber.h
  29. 1 0
      src/bin/resolver/tests/Makefile.am
  30. 3 1
      src/bin/resolver/tests/resolver_config_unittest.cc
  31. 3 1
      src/bin/resolver/tests/response_scrubber_unittest.cc
  32. 1 1
      src/bin/xfrin/tests/Makefile.am
  33. 1 1
      src/bin/xfrout/tests/Makefile.am
  34. 83 67
      src/bin/zonemgr/tests/zonemgr_test.py
  35. 13 10
      src/bin/zonemgr/zonemgr.py.in
  36. 9 3
      src/bin/zonemgr/zonemgr.spec.pre.in
  37. 3 3
      src/cppcheck-suppress.lst
  38. 2 2
      src/lib/Makefile.am
  39. 34 0
      src/lib/asiodns/Makefile.am
  40. 157 0
      src/lib/asiodns/README
  41. 14 12
      src/lib/asiolink/asiodef.cc
  42. 23 0
      src/lib/asiodns/asiodef.h
  43. 2 2
      src/lib/asiolink/asiodef.msg
  44. 23 0
      src/lib/asiodns/asiodns.h
  45. 8 4
      src/lib/asiolink/dns_answer.h
  46. 8 6
      src/lib/asiolink/dns_lookup.h
  47. 5 3
      src/lib/asiolink/dns_server.h
  48. 9 8
      src/lib/asiolink/dns_service.cc
  49. 11 9
      src/lib/asiolink/dns_service.h
  50. 70 43
      src/lib/asiolink/io_fetch.cc
  51. 35 10
      src/lib/asiolink/io_fetch.h
  52. 9 4
      src/lib/asiolink/tcp_server.cc
  53. 13 9
      src/lib/asiolink/tcp_server.h
  54. 50 0
      src/lib/asiodns/tests/Makefile.am
  55. 9 7
      src/lib/asiolink/tests/dns_server_unittest.cc
  56. 10 5
      src/lib/asiolink/tests/io_fetch_unittest.cc
  57. 3 1
      src/lib/asiolink/tests/io_service_unittest.cc
  58. 28 0
      src/lib/asiodns/tests/run_unittests.cc
  59. 8 4
      src/lib/asiolink/udp_server.cc
  60. 8 6
      src/lib/asiolink/udp_server.h
  61. 0 12
      src/lib/asiolink/Makefile.am
  62. 0 160
      src/lib/asiolink/README
  63. 0 21
      src/lib/asiolink/asiodef.h
  64. 0 9
      src/lib/asiolink/asiolink.h
  65. 2 0
      src/lib/asiolink/dummy_io_cb.h
  66. 3 1
      src/lib/asiolink/interval_timer.cc
  67. 3 1
      src/lib/asiolink/interval_timer.h
  68. 3 1
      src/lib/asiolink/io_address.cc
  69. 3 1
      src/lib/asiolink/io_address.h
  70. 5 4
      src/lib/asiolink/io_asio_socket.h
  71. 3 1
      src/lib/asiolink/io_endpoint.cc
  72. 3 1
      src/lib/asiolink/io_endpoint.h
  73. 3 1
      src/lib/asiolink/io_error.h
  74. 3 1
      src/lib/asiolink/io_message.h
  75. 3 1
      src/lib/asiolink/io_service.cc
  76. 3 1
      src/lib/asiolink/io_service.h
  77. 3 3
      src/lib/asiolink/io_socket.cc
  78. 2 0
      src/lib/asiolink/io_socket.h
  79. 3 1
      src/lib/asiolink/simple_callback.h
  80. 3 1
      src/lib/asiolink/tcp_endpoint.h
  81. 9 7
      src/lib/asiolink/tcp_socket.h
  82. 2 5
      src/lib/asiolink/tests/Makefile.am
  83. 1 1
      src/lib/asiolink/tests/interval_timer_unittest.cc
  84. 1 1
      src/lib/asiolink/tests/io_address_unittest.cc
  85. 1 1
      src/lib/asiolink/tests/io_endpoint_unittest.cc
  86. 1 1
      src/lib/asiolink/tests/io_socket_unittest.cc
  87. 1 1
      src/lib/asiolink/tests/tcp_endpoint_unittest.cc
  88. 4 4
      src/lib/asiolink/tests/tcp_socket_unittest.cc
  89. 1 1
      src/lib/asiolink/tests/udp_endpoint_unittest.cc
  90. 4 4
      src/lib/asiolink/tests/udp_socket_unittest.cc
  91. 3 1
      src/lib/asiolink/udp_endpoint.h
  92. 4 2
      src/lib/asiolink/udp_socket.h
  93. 2 1
      src/lib/bench/benchmark_util.cc
  94. 1 0
      src/lib/bench/tests/Makefile.am
  95. 2 1
      src/lib/bench/tests/loadquery_unittest.cc
  96. 1 0
      src/lib/cache/Makefile.am
  97. 2 2
      src/lib/cache/message_cache.h
  98. 3 2
      src/lib/cache/rrset_cache.h
  99. 2 0
      src/lib/cache/tests/Makefile.am
  100. 0 0
      src/lib/cache/tests/cache_test_messagefromfile.h

+ 21 - 1
ChangeLog

@@ -1,8 +1,28 @@
-219.  [bug]     feng
+223.  [bug]     feng
 	If ip address or port isn't usable for name server, name server process
 	won't exist and give end user chance to reconfigure them.
 	(Trac #775, git 572ac2cf62e18f7eb69d670b890e2a3443bfd6e7)
 
+222.	[bug] 		jerry
+	src/lib/zonemgr: Fix a bug that xfrin not checking for new copy of
+	zone on startup.  Imposes some random jitters to avoid many zones
+	need to do refresh at the same time.
+	(Trac #387, svn 9140fab9bab5f6502bd15d391fd51ac078b0b89b)
+
+221.	[func]*		jerry
+	src/lib/util: Create C++ utility library.
+	(Trac #749, git 084d1285d038d31067f8cdbb058d626acf03566d)
+
+220.	[func]		stephen
+	Added the 'badpacket' program for testing; it sends a set of
+	(potentially) bad packets to a nameserver and prints the responses.
+	(Trac #703, git 1b666838b6c0fe265522b30971e878d9f0d21fde)
+
+219.    [func]          ocean
+	src/lib: move some dns related code out of asiolink library to
+	asiodns library
+	(Trac #751, git 262ac6c6fc61224d54705ed4c700dadb606fcb1c)
+
 218.	[func]		jinmei
 	src/lib/dns: added support for RP RDATA.
 	(Trac #806, git 4e47d5f6b692c63c907af6681a75024450884a88)

+ 12 - 4
configure.ac

@@ -612,6 +612,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/bindctl/Makefile
                  src/bin/bindctl/tests/Makefile
                  src/bin/cfgmgr/Makefile
+                 src/bin/cfgmgr/plugins/Makefile
                  src/bin/cfgmgr/tests/Makefile
                  src/bin/host/Makefile
                  src/bin/loadzone/Makefile
@@ -644,6 +645,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/Makefile
                  src/lib/asiolink/Makefile
                  src/lib/asiolink/tests/Makefile
+                 src/lib/asiodns/Makefile
+                 src/lib/asiodns/tests/Makefile
                  src/lib/bench/Makefile
                  src/lib/bench/example/Makefile
                  src/lib/bench/tests/Makefile
@@ -669,11 +672,17 @@ AC_CONFIG_FILES([Makefile
                  src/lib/config/Makefile
                  src/lib/config/tests/Makefile
                  src/lib/config/tests/testdata/Makefile
+                 src/lib/util/Makefile
+                 src/lib/util/io/Makefile
+                 src/lib/util/io/tests/Makefile
+                 src/lib/util/unittests/Makefile
+                 src/lib/util/tests/Makefile
                  src/lib/dns/Makefile
                  src/lib/dns/tests/Makefile
                  src/lib/dns/tests/testdata/Makefile
                  src/lib/dns/python/Makefile
                  src/lib/dns/python/tests/Makefile
+                 src/lib/dns/benchmarks/Makefile
                  src/lib/exceptions/Makefile
                  src/lib/exceptions/tests/Makefile
                  src/lib/datasrc/Makefile
@@ -694,10 +703,9 @@ AC_CONFIG_FILES([Makefile
                  src/lib/server_common/tests/Makefile
                  tests/Makefile
                  tests/system/Makefile
-                 src/lib/util/Makefile
-                 src/lib/util/io/Makefile
-                 src/lib/util/io/tests/Makefile
-                 src/lib/util/unittests/Makefile
+                 tests/tools/Makefile
+                 tests/tools/badpacket/Makefile
+                 tests/tools/badpacket/tests/Makefile
                ])
 AC_OUTPUT([doc/version.ent
            src/bin/cfgmgr/b10-cfgmgr.py

+ 1 - 0
src/bin/auth/Makefile.am

@@ -49,6 +49,7 @@ b10_auth_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
 b10_auth_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
 b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.la
 b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+b10_auth_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
 b10_auth_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 b10_auth_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
 b10_auth_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la

+ 6 - 3
src/bin/auth/auth_srv.cc

@@ -31,7 +31,8 @@
 
 #include <exceptions/exceptions.h>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
+
 #include <dns/edns.h>
 #include <dns/exceptions.h>
 #include <dns/messagerenderer.h>
@@ -63,12 +64,14 @@ using namespace isc;
 using namespace isc::cc;
 using namespace isc::datasrc;
 using namespace isc::dns;
+using namespace isc::util;
 using namespace isc::auth;
 using namespace isc::dns::rdata;
 using namespace isc::data;
 using namespace isc::config;
 using namespace isc::xfr;
-using namespace asiolink;
+using namespace isc::asiolink;
+using namespace isc::asiodns;
 using namespace isc::server_common::portconfig;
 
 class AuthSrvImpl {
@@ -766,6 +769,6 @@ AuthSrv::setListenAddresses(const AddressList& addresses) {
 }
 
 void
-AuthSrv::setDNSService(asiolink::DNSService& dnss) {
+AuthSrv::setDNSService(isc::asiodns::DNSService& dnss) {
     dnss_ = &dnss;
 }

+ 16 - 16
src/bin/auth/auth_srv.h

@@ -24,13 +24,13 @@
 #include <cc/data.h>
 #include <config/ccsession.h>
 #include <dns/message.h>
-#include <dns/buffer.h>
+#include <util/buffer.h>
 
+#include <asiodns/dns_server.h>
+#include <asiodns/dns_lookup.h>
+#include <asiodns/dns_answer.h>
 #include <asiolink/io_message.h>
 #include <asiolink/io_service.h>
-#include <asiolink/dns_server.h>
-#include <asiolink/dns_lookup.h>
-#include <asiolink/dns_answer.h>
 #include <asiolink/simple_callback.h>
 
 #include <asiolink/asiolink.h>
@@ -116,10 +116,10 @@ public:
     /// \param server Pointer to the \c DNSServer
     ///
     /// \throw isc::Unexpected Protocol type of \a message is unexpected
-    void processMessage(const asiolink::IOMessage& io_message,
+    void processMessage(const isc::asiolink::IOMessage& io_message,
                         isc::dns::MessagePtr message,
-                        isc::dns::OutputBufferPtr buffer,
-                        asiolink::DNSServer* server);
+                        isc::util::OutputBufferPtr buffer,
+                        isc::asiodns::DNSServer* server);
 
     /// \brief Set verbose flag
     ///
@@ -202,16 +202,16 @@ public:
     void setConfigSession(isc::config::ModuleCCSession* config_session);
 
     /// \brief Return this object's ASIO IO Service queue
-    asiolink::IOService& getIOService();
+    isc::asiolink::IOService& getIOService();
 
     /// \brief Return pointer to the DNS Lookup callback function
-    asiolink::DNSLookup* getDNSLookupProvider() const { return (dns_lookup_); }
+    isc::asiodns::DNSLookup* getDNSLookupProvider() const { return (dns_lookup_); }
 
     /// \brief Return pointer to the DNS Answer callback function
-    asiolink::DNSAnswer* getDNSAnswerProvider() const { return (dns_answer_); }
+    isc::asiodns::DNSAnswer* getDNSAnswerProvider() const { return (dns_answer_); }
 
     /// \brief Return pointer to the Checkin callback function
-    asiolink::SimpleCallback* getCheckinProvider() const { return (checkin_); }
+    isc::asiolink::SimpleCallback* getCheckinProvider() const { return (checkin_); }
 
     /// \brief Set or update the size (number of slots) of hot spot cache.
     ///
@@ -372,15 +372,15 @@ public:
         const;
 
     /// \brief Assign an ASIO DNS Service queue to this Auth object
-    void setDNSService(asiolink::DNSService& dnss);
+    void setDNSService(isc::asiodns::DNSService& dnss);
 
 
 private:
     AuthSrvImpl* impl_;
-    asiolink::SimpleCallback* checkin_;
-    asiolink::DNSLookup* dns_lookup_;
-    asiolink::DNSAnswer* dns_answer_;
-    asiolink::DNSService* dnss_;
+    isc::asiolink::SimpleCallback* checkin_;
+    isc::asiodns::DNSLookup* dns_lookup_;
+    isc::asiodns::DNSAnswer* dns_answer_;
+    isc::asiodns::DNSService* dnss_;
 };
 
 #endif // __AUTH_SRV_H

+ 1 - 0
src/bin/auth/benchmarks/Makefile.am

@@ -22,6 +22,7 @@ query_bench_LDADD += $(top_builddir)/src/lib/cc/libcc.la
 query_bench_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
 query_bench_LDADD += $(top_builddir)/src/lib/log/liblog.la
 query_bench_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
+query_bench_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
 query_bench_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 query_bench_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
 query_bench_LDADD += $(SQLITE_LIBS)

+ 5 - 2
src/bin/auth/benchmarks/query_bench.cc

@@ -24,7 +24,7 @@
 #include <bench/benchmark.h>
 #include <bench/benchmark_util.h>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
 #include <dns/message.h>
 #include <dns/name.h>
 #include <dns/question.h>
@@ -36,6 +36,7 @@
 #include <auth/auth_config.h>
 #include <auth/query.h>
 
+#include <asiodns/asiodns.h>
 #include <asiolink/asiolink.h>
 
 using namespace std;
@@ -43,9 +44,11 @@ using namespace isc;
 using namespace isc::data;
 using namespace isc::auth;
 using namespace isc::dns;
+using namespace isc::util;
 using namespace isc::xfr;
 using namespace isc::bench;
-using namespace asiolink;
+using namespace isc::asiodns;
+using namespace isc::asiolink;
 
 namespace {
 // Commonly used constant:

+ 6 - 2
src/bin/auth/main.cc

@@ -27,7 +27,8 @@
 
 #include <exceptions/exceptions.h>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
+
 #include <dns/message.h>
 #include <dns/messagerenderer.h>
 
@@ -43,6 +44,7 @@
 #include <auth/command.h>
 #include <auth/change_user.h>
 #include <auth/auth_srv.h>
+#include <asiodns/asiodns.h>
 #include <asiolink/asiolink.h>
 #include <log/dummylog.h>
 
@@ -51,8 +53,10 @@ using namespace isc::data;
 using namespace isc::cc;
 using namespace isc::config;
 using namespace isc::dns;
+using namespace isc::util;
 using namespace isc::xfr;
-using namespace asiolink;
+using namespace isc::asiolink;
+using namespace isc::asiodns;
 
 namespace {
 

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

@@ -45,6 +45,7 @@ run_unittests_LDADD += $(SQLITE_LIBS)
 run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/datasrc/libdatasrc.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
 run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la

+ 3 - 1
src/bin/auth/tests/auth_srv_unittest.cc

@@ -41,10 +41,12 @@
 using namespace std;
 using namespace isc::cc;
 using namespace isc::dns;
+using namespace isc::util;
 using namespace isc::dns::rdata;
 using namespace isc::data;
 using namespace isc::xfr;
-using namespace asiolink;
+using namespace isc::asiodns;
+using namespace isc::asiolink;
 using namespace isc::testutils;
 using namespace isc::server_common::portconfig;
 using isc::UnitTestUtil;

+ 1 - 1
src/bin/auth/tests/command_unittest.cc

@@ -99,7 +99,7 @@ AuthConmmandTest::stopServer() {
 }
 
 TEST_F(AuthConmmandTest, shutdown) {
-    asiolink::IntervalTimer itimer(server.getIOService());
+    isc::asiolink::IntervalTimer itimer(server.getIOService());
     itimer.setup(boost::bind(&AuthConmmandTest::stopServer, this), 1);
     server.getIOService().run();
     EXPECT_EQ(0, rcode);

+ 2 - 1
src/bin/auth/tests/config_unittest.cc

@@ -35,7 +35,8 @@
 using namespace isc::dns;
 using namespace isc::data;
 using namespace isc::datasrc;
-using namespace asiolink;
+using namespace isc::asiodns;
+using namespace isc::asiolink;
 
 namespace {
 class AuthConfigTest : public ::testing::Test {

File diff suppressed because it is too large
+ 38 - 11
src/bin/bind10/bind10.8


+ 51 - 8
src/bin/bind10/bind10.xml

@@ -20,7 +20,7 @@
 <refentry>
 
   <refentryinfo>
-    <date>February 22, 2011</date>
+    <date>March 31, 2011</date>
   </refentryinfo>
 
   <refmeta>
@@ -44,16 +44,21 @@
   <refsynopsisdiv>
     <cmdsynopsis>
       <command>bind10</command>
+      <arg><option>-c <replaceable>config-filename</replaceable></option></arg>
       <arg><option>-m <replaceable>file</replaceable></option></arg>
       <arg><option>-n</option></arg>
+      <arg><option>-p <replaceable>data_path</replaceable></option></arg>
       <arg><option>-u <replaceable>user</replaceable></option></arg>
       <arg><option>-v</option></arg>
-      <arg><option>-c<replaceable>config-filename</replaceable></option></arg>
-      <arg><option>-p<replaceable>data_path</replaceable></option></arg>
+      <arg><option>--brittle</option></arg>
+      <arg><option>--cmdctl-port</option> <replaceable>port</replaceable></arg>
+      <arg><option>--config-file</option> <replaceable>config-filename</replaceable></arg>
+      <arg><option>--data-path</option> <replaceable>directory</replaceable></arg>
       <arg><option>--msgq-socket-file <replaceable>file</replaceable></option></arg>
       <arg><option>--no-cache</option></arg>
-      <arg><option>--user <replaceable>user</replaceable></option></arg>
+      <arg><option>--pid-file</option> <replaceable>filename</replaceable></arg>
       <arg><option>--pretty-name <replaceable>name</replaceable></option></arg>
+      <arg><option>--user <replaceable>user</replaceable></option></arg>
       <arg><option>--verbose</option></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -82,9 +87,24 @@
     <para>The arguments are as follows:</para>
 
     <variablelist>
+
+      <varlistentry>
+        <term>
+          <option>--brittle</option>
+        </term>
+        <listitem>
+          <para>
+	    Shutdown if any of the child processes of
+	    <command>bind10</command> exit.  This is intended to
+	    help developers debug the server, and should not be
+	    used in production.
+          </para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term>
-          <option>-c</option><replaceable>config-filename</replaceable>,
+          <option>-c</option> <replaceable>config-filename</replaceable>,
           <option>--config-file</option> <replaceable>config-filename</replaceable>
         </term>
         <listitem>
@@ -97,8 +117,22 @@
 
       <varlistentry>
         <term>
-          <option>-p</option><replaceable>data-path</replaceable>,
-          <option>--data-path</option> <replaceable>data-path</replaceable>
+          <option>--cmdctl-port</option> <replaceable>port</replaceable>
+        </term>
+        <listitem>
+	  <para>The <command>b10-cmdctl</command> daemon will listen
+	    on this port.
+	    (See
+	    <refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum>
+            for the default.)
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
+          <option>-p</option> <replaceable>directory</replaceable>,
+          <option>--data-path</option> <replaceable>directory</replaceable>
         </term>
         <listitem>
           <para>The path where BIND 10 programs look for various data files.
@@ -134,7 +168,6 @@
 
       <varlistentry>
         <term><option>-u</option> <replaceable>user</replaceable>, <option>--user</option> <replaceable>name</replaceable></term>
-
         <listitem>
           <para>The username for <command>bind10</command> to run as.
 <!-- TODO: example more detail. -->
@@ -145,6 +178,16 @@
       </varlistentry>
 
       <varlistentry>
+        <term><option>--pid-file</option> <replaceable>filename</replaceable></term>
+        <listitem>
+          <para>If defined, the PID of the <command>bind10</command> is stored
+             in this file.
+             This is used for testing purposes.
+          </para>
+         </listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>--pretty-name <replaceable>name</replaceable></option></term>
 
         <listitem>

+ 1 - 1
src/bin/cfgmgr/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = . tests
+SUBDIRS = . plugins tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 

+ 28 - 0
src/bin/cfgmgr/b10-cfgmgr.py.in

@@ -23,6 +23,8 @@ import isc.util.process
 import signal
 import os
 from optparse import OptionParser
+import glob
+import os.path
 
 isc.util.process.rename()
 
@@ -39,9 +41,11 @@ if "B10_FROM_SOURCE" in os.environ:
         DATA_PATH = os.environ["B10_FROM_SOURCE_LOCALSTATEDIR"]
     else:
         DATA_PATH = os.environ["B10_FROM_SOURCE"]
+    PLUGIN_PATH = [DATA_PATH + '/src/bin/cfgmgr/plugins']
 else:
     PREFIX = "@prefix@"
     DATA_PATH = "@localstatedir@/@PACKAGE@".replace("${prefix}", PREFIX)
+    PLUGIN_PATHS = ["@prefix@/share/@PACKAGE@/config_plugins"]
 DEFAULT_CONFIG_FILE = "b10-config.db"
 
 cm = None
@@ -65,6 +69,28 @@ def signal_handler(signal, frame):
     if cm:
         cm.running = False
 
+def load_plugins(path, cm):
+    """Load all python files in the given path and treat them as plugins."""
+    # Find the python files
+    plugins = glob.glob(path + os.sep + '*.py')
+    # Search this directory first, but leave the others there for the imports
+    # of the modules
+    sys.path.insert(0, path)
+    try:
+        for plugin in plugins:
+            # Generate the name of the plugin
+            filename = os.path.basename(plugin)
+            name = filename[:-3]
+            # Load it
+            module = __import__(name)
+            # Ask it to provide the spec and checking function
+            (spec, check_func) = module.load()
+            # And insert it into the manager
+            cm.set_virtual_module(spec, check_func)
+    finally:
+        # Restore the search path
+        sys.path = sys.path[1:]
+
 def main():
     options = parse_options()
     global cm
@@ -73,6 +99,8 @@ def main():
         signal.signal(signal.SIGINT, signal_handler)
         signal.signal(signal.SIGTERM, signal_handler)
         cm.read_config()
+        for ppath in PLUGIN_PATHS:
+            load_plugins(ppath, cm)
         cm.notify_boss()
         cm.run()
     except SessionError as se:

+ 1 - 0
src/bin/cfgmgr/plugins/Makefile.am

@@ -0,0 +1 @@
+EXTRA_DIST = README

+ 34 - 0
src/bin/cfgmgr/plugins/README

@@ -0,0 +1,34 @@
+How to write a configuration plugin
+===================================
+
+The plugins are used to describe configuration modules that have no hosting
+process. Therefore there's no process to provide their specification and to
+check them for correctness. So the plugin takes this responsibility.
+
+Each plugin is a python file installed into the
+`@prefix@/share/@PACKAGE@/config_plugins` directory (usually
+`/usr/share/bind10/config_plugins`). It is loaded automatically at startup.
+
+The entrypoint of a plugin is function called `load()`. It should return a
+tuple, first value should be the module specification (usually instance of
+`isc.config.module_spec.ModuleSpec`, loaded by `module_spec_from_file()`).
+
+The second value is a callable object. It will be called whenever the
+configuration of module needs to be checked. The only parameter will be the new
+config (as python dictionary). To accept the new configuration, return None. If
+you return a string, it is taken as an error message. If you raise an
+exception, the config is rejected as well, however it is not considered a
+graceful rejection, but a failure of the module.
+
+So, this is how a plugin could look like:
+
+  from isc.config.module_spec import module_spec_from_file
+
+  def check(config):
+      if config['bogosity'] > 1:
+          return "Too bogus to live with"
+      else:
+          return None
+
+  def load():
+      return (module_spec_from_file('module_spec.spec'), check)

+ 2 - 1
src/bin/cfgmgr/tests/Makefile.am

@@ -1,7 +1,7 @@
 PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
 PYTESTS = b10-cfgmgr_test.py
 
-EXTRA_DIST = $(PYTESTS)
+EXTRA_DIST = $(PYTESTS) testdata/plugins/testplugin.py
 
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
@@ -12,6 +12,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	env TESTDATA_PATH=$(abs_srcdir)/testdata \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cfgmgr \
 	$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
 	done

+ 31 - 0
src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in

@@ -30,6 +30,7 @@ class MyConfigManager:
         self.run_called = False
         self.write_config_called = False
         self.running = True
+        self.virtual_modules = []
 
     def read_config(self):
         self.read_config_called = True
@@ -43,6 +44,24 @@ class MyConfigManager:
     def write_config(self):
         self.write_config_called = True
 
+    def set_virtual_module(self, spec, function):
+        self.virtual_modules.append((spec, function))
+
+class TestPlugins(unittest.TestCase):
+    def test_load_plugins(self):
+        """Test we can successfully find and load the mock plugin."""
+        # Let it load the plugin
+        b = __import__("b10-cfgmgr")
+        # The parameters aren't important for this test
+        cm = MyConfigManager(None, None)
+        b.load_plugins(os.environ['TESTDATA_PATH'] + os.sep + 'plugins', cm)
+        # Check exactly one plugin was loaded and the right data were fed into
+        # the cm
+        self.assertEqual(len(cm.virtual_modules), 1)
+        (spec, check) = cm.virtual_modules[0]
+        self.assertEqual(spec.get_module_name(), "mock_config_plugin")
+        self.assertEqual(check(None), "Mock config plugin")
+
 class TestConfigManagerStartup(unittest.TestCase):
     def test_cfgmgr(self):
         # some creative module use;
@@ -50,13 +69,24 @@ class TestConfigManagerStartup(unittest.TestCase):
         # this also gives us the chance to override the imported
         # module ConfigManager in it.
         b = __import__("b10-cfgmgr")
+        orig_load = b.load_plugins
+        b.PLUGIN_PATHS = ["/plugin/path"]
+        self.loaded_plugins = False
+        def load_plugins(path, cm):
+            # Check it's called with proper arguments
+            self.assertEqual(path, "/plugin/path")
+            self.assertTrue(isinstance(cm, MyConfigManager))
+            self.loaded_plugins = True
+        b.load_plugins = load_plugins
         b.ConfigManager = MyConfigManager
 
         b.main()
+        b.load_plugins = orig_load
 
         self.assertTrue(b.cm.read_config_called)
         self.assertTrue(b.cm.notify_boss_called)
         self.assertTrue(b.cm.run_called)
+        self.assertTrue(self.loaded_plugins)
         # if there are no changes, config is not written
         self.assertFalse(b.cm.write_config_called)
 
@@ -81,6 +111,7 @@ class TestConfigManagerStartup(unittest.TestCase):
 
         os.environ["B10_FROM_SOURCE"] = tmp_env_var
         b = __import__("b10-cfgmgr", globals(), locals())
+        b.PLUGIN_PATH = [] # It's enough to test plugins in one test
         b.ConfigManager = MyConfigManager
         self.assertEqual(tmp_env_var, b.DATA_PATH)
 

+ 34 - 0
src/bin/cfgmgr/tests/testdata/plugins/testplugin.py

@@ -0,0 +1,34 @@
+# Copyright (C) 2011  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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.
+
+# A test plugin. It does mostly nothing, just provides a function we can
+# recognize from the test. However, it looks like a real plugin, with the
+# (almost) correct interface, even when it's not used.
+
+class MockSpec:
+    """Mock spec, contains no data, it can only provide it's name.
+       It'll not really be used for anything."""
+    def get_module_name(self):
+        return "mock_config_plugin"
+
+def mock_check_config(config):
+    """Mock function to check config. Does nothing, only returns
+       an "error" string to indicate it's this one."""
+    return "Mock config plugin"
+
+def load():
+    """When a plugin is loaded, this is called to provide the spec and
+       checking function."""
+    return (MockSpec(), mock_check_config)

+ 3 - 1
src/bin/host/host.cc

@@ -24,7 +24,8 @@
 #include <string>
 #include <iostream>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
+
 #include <dns/name.h>
 #include <dns/message.h>
 #include <dns/messagerenderer.h>
@@ -37,6 +38,7 @@
 
 using namespace std;
 using namespace isc::dns;
+using namespace isc::util;
 
 namespace {
 char* dns_type = NULL;    // not set, so A, AAAA, MX

+ 3 - 0
src/bin/resolver/Makefile.am

@@ -4,6 +4,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cc -I$(top_builddir)/src/lib/cc
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiodns
+AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiodns
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiolink
 AM_CPPFLAGS += $(BOOST_INCLUDES)
@@ -45,6 +47,7 @@ b10_resolver_LDADD =  $(top_builddir)/src/lib/dns/libdns++.la
 b10_resolver_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
 b10_resolver_LDADD += $(top_builddir)/src/lib/cc/libcc.la
 b10_resolver_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+b10_resolver_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
 b10_resolver_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 b10_resolver_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
 b10_resolver_LDADD += $(top_builddir)/src/lib/log/liblog.la

+ 4 - 2
src/bin/resolver/main.cc

@@ -27,11 +27,12 @@
 
 #include <boost/foreach.hpp>
 
+#include <asiodns/asiodns.h>
 #include <asiolink/asiolink.h>
 
 #include <exceptions/exceptions.h>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
 #include <dns/rcode.h>
 #include <dns/message.h>
 #include <dns/messagerenderer.h>
@@ -58,7 +59,8 @@ using namespace isc::cc;
 using namespace isc::config;
 using namespace isc::data;
 using isc::log::dlog;
-using namespace asiolink;
+using namespace isc::asiodns;
+using namespace isc::asiolink;
 
 namespace {
 

+ 8 - 4
src/bin/resolver/resolver.cc

@@ -20,6 +20,7 @@
 #include <vector>
 #include <cassert>
 
+#include <asiodns/asiodns.h>
 #include <asiolink/asiolink.h>
 
 #include <boost/foreach.hpp>
@@ -29,9 +30,10 @@
 
 #include <exceptions/exceptions.h>
 
+#include <util/buffer.h>
+
 #include <dns/opcode.h>
 #include <dns/rcode.h>
-#include <dns/buffer.h>
 #include <dns/exceptions.h>
 #include <dns/name.h>
 #include <dns/question.h>
@@ -50,11 +52,13 @@
 using namespace std;
 
 using namespace isc;
+using namespace isc::util;
 using namespace isc::dns;
 using namespace isc::data;
 using namespace isc::config;
 using isc::log::dlog;
-using namespace asiolink;
+using namespace isc::asiodns;
+using namespace isc::asiolink;
 using namespace isc::server_common::portconfig;
 
 class ResolverImpl {
@@ -295,7 +299,7 @@ public:
             edns_response->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
             answer_message->setEDNS(edns_response);
         }
-        
+
         if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
             if (edns) {
                 renderer.setLengthLimit(edns->getUDPSize());
@@ -345,7 +349,7 @@ Resolver::~Resolver() {
 }
 
 void
-Resolver::setDNSService(asiolink::DNSService& dnss) {
+Resolver::setDNSService(isc::asiodns::DNSService& dnss) {
     dnss_ = &dnss;
 }
 

+ 22 - 22
src/bin/resolver/resolver.h

@@ -22,14 +22,14 @@
 #include <cc/data.h>
 #include <config/ccsession.h>
 #include <dns/message.h>
-#include <dns/buffer.h>
+#include <util/buffer.h>
 
+#include <asiodns/dns_server.h>
+#include <asiodns/dns_service.h>
+#include <asiodns/dns_lookup.h>
+#include <asiodns/dns_answer.h>
 #include <asiolink/io_message.h>
 #include <asiolink/io_service.h>
-#include <asiolink/dns_server.h>
-#include <asiolink/dns_service.h>
-#include <asiolink/dns_lookup.h>
-#include <asiolink/dns_answer.h>
 #include <asiolink/simple_callback.h>
 
 #include <nsas/nameserver_address_store.h>
@@ -82,11 +82,11 @@ public:
     /// shall return to the client
     /// \param buffer Pointer to an \c OutputBuffer for the resposne
     /// \param server Pointer to the \c DNSServer
-    void processMessage(const asiolink::IOMessage& io_message,
+    void processMessage(const isc::asiolink::IOMessage& io_message,
                         isc::dns::MessagePtr query_message,
                         isc::dns::MessagePtr answer_message,
-                        isc::dns::OutputBufferPtr buffer,
-                        asiolink::DNSServer* server);
+                        isc::util::OutputBufferPtr buffer,
+                        isc::asiodns::DNSServer* server);
 
     /// \brief Set and get the config session
     isc::config::ModuleCCSession* getConfigSession() const;
@@ -96,16 +96,16 @@ public:
     isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
 
     /// \brief Assign an ASIO IO Service queue to this Resolver object
-    void setDNSService(asiolink::DNSService& dnss);
-    
+    void setDNSService(isc::asiodns::DNSService& dnss);
+
     /// \brief Assign a NameserverAddressStore to this Resolver object
     void setNameserverAddressStore(isc::nsas::NameserverAddressStore &nsas);
-    
+
     /// \brief Assign a cache to this Resolver object
     void setCache(isc::cache::ResolverCache& cache);
 
     /// \brief Return this object's ASIO IO Service queue
-    asiolink::DNSService& getDNSService() const { return (*dnss_); }
+    isc::asiodns::DNSService& getDNSService() const { return (*dnss_); }
 
     /// \brief Returns this object's NSAS
     isc::nsas::NameserverAddressStore& getNameserverAddressStore() const {
@@ -116,15 +116,15 @@ public:
     isc::cache::ResolverCache& getResolverCache() const {
         return *cache_;
     };
-    
+
     /// \brief Return pointer to the DNS Lookup callback function
-    asiolink::DNSLookup* getDNSLookupProvider() { return (dns_lookup_); }
+    isc::asiodns::DNSLookup* getDNSLookupProvider() { return (dns_lookup_); }
 
     /// \brief Return pointer to the DNS Answer callback function
-    asiolink::DNSAnswer* getDNSAnswerProvider() { return (dns_answer_); }
+    isc::asiodns::DNSAnswer* getDNSAnswerProvider() { return (dns_answer_); }
 
     /// \brief Return pointer to the Checkin callback function
-    asiolink::SimpleCallback* getCheckinProvider() { return (checkin_); }
+    isc::asiolink::SimpleCallback* getCheckinProvider() { return (checkin_); }
 
     /**
      * \brief Tell the Resolver that is has already been configured
@@ -238,10 +238,10 @@ public:
 
 private:
     ResolverImpl* impl_;
-    asiolink::DNSService* dnss_;
-    asiolink::SimpleCallback* checkin_;
-    asiolink::DNSLookup* dns_lookup_;
-    asiolink::DNSAnswer* dns_answer_;
+    isc::asiodns::DNSService* dnss_;
+    isc::asiolink::SimpleCallback* checkin_;
+    isc::asiodns::DNSLookup* dns_lookup_;
+    isc::asiodns::DNSAnswer* dns_answer_;
     isc::nsas::NameserverAddressStore* nsas_;
     isc::cache::ResolverCache* cache_;
     // This value is initally false, and will be set to true
@@ -252,6 +252,6 @@ private:
 
 #endif // __RESOLVER_H
 
-// Local Variables: 
+// Local Variables:
 // mode: c++
-// End: 
+// End:

+ 1 - 1
src/bin/resolver/response_scrubber.cc

@@ -26,7 +26,7 @@ using namespace std;
 // Compare addresses etc.
 
 ResponseScrubber::Category ResponseScrubber::addressCheck(
-    const asiolink::IOEndpoint& to, const asiolink::IOEndpoint& from)
+    const isc::asiolink::IOEndpoint& to, const isc::asiolink::IOEndpoint& from)
 {
     if (from.getProtocol() == to.getProtocol()) {
         if (from.getAddress() == to.getAddress()) {

+ 2 - 2
src/bin/resolver/response_scrubber.h

@@ -282,8 +282,8 @@ public:
     ///
     /// \return SUCCESS if the two endpoints match, otherwise an error status
     /// indicating what was incorrect.
-    static Category addressCheck(const asiolink::IOEndpoint& to,
-        const asiolink::IOEndpoint& from);
+    static Category addressCheck(const isc::asiolink::IOEndpoint& to,
+        const isc::asiolink::IOEndpoint& from);
 
     /// \brief Check QID
     ///

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

@@ -31,6 +31,7 @@ run_unittests_LDADD += $(SQLITE_LIBS)
 run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
 run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
 run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
 run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la

+ 3 - 1
src/bin/resolver/tests/resolver_config_unittest.cc

@@ -20,6 +20,7 @@
 
 #include <cc/data.h>
 
+#include <asiodns/asiodns.h>
 #include <asiolink/asiolink.h>
 
 #include <resolver/resolver.h>
@@ -31,7 +32,8 @@
 using namespace std;
 using namespace isc::data;
 using namespace isc::testutils;
-using namespace asiolink;
+using namespace isc::asiodns;
+using namespace isc::asiolink;
 using isc::UnitTestUtil;
 
 namespace {

+ 3 - 1
src/bin/resolver/tests/response_scrubber_unittest.cc

@@ -41,6 +41,7 @@
 // Class for endpoint checks.  The family of the endpoint is set in the
 // constructor; the address family by the string provided for the address.
 
+namespace isc {
 namespace asiolink {
 
 class GenericEndpoint : public IOEndpoint {
@@ -73,13 +74,14 @@ private:
     short       protocol_;      // Protocol of the endpoint
     };
 }
+}
 
 using namespace asio::ip;
 using namespace isc::dns;
 using namespace rdata;
 using namespace isc::dns::rdata::generic;
 using namespace isc::dns::rdata::in;
-using namespace asiolink;
+using namespace isc::asiolink;
 
 // Test class
 

+ 1 - 1
src/bin/xfrin/tests/Makefile.am

@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS

+ 1 - 1
src/bin/xfrout/tests/Makefile.am

@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS

+ 83 - 67
src/bin/zonemgr/tests/zonemgr_test.py

@@ -29,8 +29,9 @@ ZONE_NAME_CLASS2_IN = ("tw.cn.", "IN")
 
 MAX_TRANSFER_TIMEOUT = 14400
 LOWERBOUND_REFRESH = 10
-LOWERBOUND_RETRY = 5 
-JITTER_SCOPE = 0.10
+LOWERBOUND_RETRY = 5
+REFRESH_JITTER = 0.10
+RELOAD_JITTER = 0.75
 
 class ZonemgrTestException(Exception):
     pass
@@ -60,8 +61,10 @@ class FakeConfig:
             return LOWERBOUND_RETRY
         elif name == 'max_transfer_timeout':
             return MAX_TRANSFER_TIMEOUT
-        elif name == 'jitter_scope':
-            return JITTER_SCOPE
+        elif name == 'refresh_jitter':
+            return REFRESH_JITTER
+        elif name == 'reload_jitter':
+            return RELOAD_JITTER
         elif name == 'secondary_zones':
             return self.zone_list
         else:
@@ -71,6 +74,10 @@ class MyZonemgrRefresh(ZonemgrRefresh):
     def __init__(self):
         self._master_socket, self._slave_socket = socket.socketpair()
         self._zonemgr_refresh_info = {}
+        self._lowerbound_refresh = 10
+        self._lowerbound_retry = 5
+        self._reload_jitter = 0.75
+        self._refresh_jitter = 0.25
 
         def get_zone_soa(zone_name, db_file):
             if zone_name == 'sd.cn.':
@@ -86,18 +93,18 @@ class MyZonemgrRefresh(ZonemgrRefresh):
         ZonemgrRefresh.__init__(self, MySession(), "initdb.file",
             self._slave_socket, FakeConfig())
         current_time = time.time()
-        self._zonemgr_refresh_info = { 
+        self._zonemgr_refresh_info = {
          ('sd.cn.', 'IN'): {
          'last_refresh_time': current_time,
-         'next_refresh_time': current_time + 6500, 
-         'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
+         'next_refresh_time': current_time + 6500,
+         'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
          'zone_state': 0},
          ('tw.cn.', 'CH'): {
-         'last_refresh_time': current_time, 
-         'next_refresh_time': current_time + 6900, 
-         'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
+         'last_refresh_time': current_time,
+         'next_refresh_time': current_time + 6900,
+         'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600',
          'zone_state': 0}
-        } 
+        }
 
 class TestZonemgrRefresh(unittest.TestCase):
     def setUp(self):
@@ -109,10 +116,10 @@ class TestZonemgrRefresh(unittest.TestCase):
         max = 100025.120
         jitter = 0
         self.assertEqual(max, self.zone_refresh._random_jitter(max, jitter))
-        jitter = max / 4
+        jitter = 0.3 * max
         for i in range (0, 150):
-            self.assertTrue((3 * max / 4) <= self.zone_refresh._random_jitter(max, jitter)) 
-            self.assertTrue(self.zone_refresh._random_jitter(max, jitter) <= max) 
+            self.assertTrue((max - jitter) <= self.zone_refresh._random_jitter(max, jitter))
+            self.assertTrue(self.zone_refresh._random_jitter(max, jitter) <= max)
             i += 1;
 
     def test_get_current_time(self):
@@ -133,7 +140,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh._set_zone_refresh_timer(ZONE_NAME_CLASS1_IN)
         zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
-        self.assertTrue((time1 + 7200 * 3 / 4) <= zone_timeout)
+        self.assertTrue((time1 + 7200 * (1 - self.zone_refresh._refresh_jitter)) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 7200)
 
     def test_set_zone_retry_timer(self):
@@ -141,7 +148,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh._set_zone_retry_timer(ZONE_NAME_CLASS1_IN)
         zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
-        self.assertTrue((time1 + 3600 * 3 / 4) <= zone_timeout)
+        self.assertTrue((time1 + 3600 * (1 - self.zone_refresh._refresh_jitter)) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 3600)
 
     def test_zone_not_exist(self):
@@ -172,19 +179,19 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.assertTrue(self.zone_refresh._zone_is_expired(ZONE_NAME_CLASS1_IN))
 
     def test_get_zone_soa_rdata(self):
-        soa_rdata1  = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
-        soa_rdata2  = 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600' 
+        soa_rdata1  = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600'
+        soa_rdata2  = 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600'
         self.assertEqual(soa_rdata1, self.zone_refresh._get_zone_soa_rdata(ZONE_NAME_CLASS1_IN))
         self.assertRaises(KeyError, self.zone_refresh._get_zone_soa_rdata, ZONE_NAME_CLASS1_CH)
         self.assertEqual(soa_rdata2, self.zone_refresh._get_zone_soa_rdata(ZONE_NAME_CLASS2_CH))
         self.assertRaises(KeyError, self.zone_refresh._get_zone_soa_rdata, ZONE_NAME_CLASS2_IN)
-         
+
     def test_zonemgr_reload_zone(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
         # We need to restore this not to harm other tests
         old_get_zone_soa = sqlite3_ds.get_zone_soa
         def get_zone_soa(zone_name, db_file):
-            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None, 
+            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None,
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
         sqlite3_ds.get_zone_soa = get_zone_soa
 
@@ -234,7 +241,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         current_time = time.time()
         self.zone_refresh._set_zone_refresh_timeout(ZONE_NAME_CLASS1_IN, current_time)
         refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"]
-        self.assertEqual(current_time, refresh_time) 
+        self.assertEqual(current_time, refresh_time)
 
     def test_get_zone_next_refresh_time(self):
         current_time = time.time()
@@ -256,14 +263,14 @@ class TestZonemgrRefresh(unittest.TestCase):
         current_time = time.time()
         self.zone_refresh._set_zone_last_refresh_time(ZONE_NAME_CLASS1_IN, current_time)
         last_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"]
-        self.assertEqual(current_time, last_refresh_time) 
+        self.assertEqual(current_time, last_refresh_time)
 
     def test_send_command(self):
         self.assertRaises(ZonemgrTestException, self.zone_refresh._send_command, "Unknown", "Notify", None)
 
     def test_zone_mgr_is_empty(self):
         self.assertFalse(self.zone_refresh._zone_mgr_is_empty())
-        self.zone_refresh._zonemgr_refresh_info = {} 
+        self.zone_refresh._zonemgr_refresh_info = {}
         self.assertTrue(self.zone_refresh._zone_mgr_is_empty())
 
     def test_zonemgr_add_zone(self):
@@ -271,9 +278,10 @@ class TestZonemgrRefresh(unittest.TestCase):
         # This needs to be restored. The following test actually failed if we left
         # this unclean
         old_get_zone_soa = sqlite3_ds.get_zone_soa
+        time1 = time.time()
 
         def get_zone_soa(zone_name, db_file):
-            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None, 
+            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None,
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
 
         sqlite3_ds.get_zone_soa = get_zone_soa
@@ -282,10 +290,14 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh.zonemgr_add_zone(ZONE_NAME_CLASS1_IN)
         self.assertEqual(1, len(self.zone_refresh._zonemgr_refresh_info))
         zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
-        self.assertEqual(soa_rdata, zone_soa_rdata) 
+        self.assertEqual(soa_rdata, zone_soa_rdata)
         self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
         self.assertTrue("last_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
         self.assertTrue("next_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        time2 = time.time()
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
+        self.assertTrue((time1 + 900 * (1 - self.zone_refresh._reload_jitter)) <= zone_timeout)
+        self.assertTrue(zone_timeout <= time2 + 900)
 
         def get_zone_soa2(zone_name, db_file):
             return None
@@ -297,7 +309,7 @@ class TestZonemgrRefresh(unittest.TestCase):
     def test_zone_handle_notify(self):
         self.zone_refresh.zone_handle_notify(ZONE_NAME_CLASS1_IN,"127.0.0.1")
         notify_master = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
-        self.assertEqual("127.0.0.1", notify_master) 
+        self.assertEqual("127.0.0.1", notify_master)
         zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         current_time = time.time()
         self.assertTrue(zone_timeout <= current_time)
@@ -309,7 +321,7 @@ class TestZonemgrRefresh(unittest.TestCase):
     def test_zone_refresh_success(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
         def get_zone_soa(zone_name, db_file):
-            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None, 
+            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None,
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
         sqlite3_ds.get_zone_soa = get_zone_soa
         time1 = time.time()
@@ -317,19 +329,19 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh.zone_refresh_success(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
-        self.assertEqual(soa_rdata, zone_soa_rdata) 
+        self.assertEqual(soa_rdata, zone_soa_rdata)
         next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
-        self.assertTrue((time1 + 3 * 1800 / 4) <= next_refresh_time) 
+        self.assertTrue((time1 + 1800 * (1 - self.zone_refresh._refresh_jitter)) <= next_refresh_time)
         self.assertTrue(next_refresh_time <= time2 + 1800)
         self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
         last_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"]
         self.assertTrue(time1 <= last_refresh_time)
         self.assertTrue(last_refresh_time <= time2)
         self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ("org.cn.", "CH"))
-        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ZONE_NAME_CLASS3_IN) 
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ZONE_NAME_CLASS3_IN)
 
     def test_zone_refresh_fail(self):
-        soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
+        soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600'
         time1 = time.time()
         self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_REFRESHING
         self.zone_refresh.zone_refresh_fail(ZONE_NAME_CLASS1_IN)
@@ -337,36 +349,36 @@ class TestZonemgrRefresh(unittest.TestCase):
         zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
         self.assertEqual(soa_rdata, zone_soa_rdata)
         next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
-        self.assertTrue((time1 + 3 * 3600 / 4) <= next_refresh_time)
+        self.assertTrue(((time1 + 3600 * (1 - self.zone_refresh._refresh_jitter))) <= next_refresh_time)
         self.assertTrue(next_refresh_time <= time2 + 3600)
         self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
 
-        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = time1 - 2419200 
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = time1 - 2419200
         self.zone_refresh.zone_refresh_fail(ZONE_NAME_CLASS1_IN)
         self.assertEqual(ZONE_EXPIRED, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
 
         self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ("org.cn.", "CH"))
-        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ZONE_NAME_CLASS3_IN) 
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ZONE_NAME_CLASS3_IN)
 
     def test_find_need_do_refresh_zone(self):
         time1 = time.time()
-        self.zone_refresh._zonemgr_refresh_info = { 
+        self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.","IN"):{
                     'last_refresh_time': time1,
-                    'next_refresh_time': time1 + 7200, 
-                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
+                    'next_refresh_time': time1 + 7200,
+                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
                     'zone_state': ZONE_OK},
                 ("tw.cn.","CH"):{
-                    'last_refresh_time': time1 - 7200, 
-                    'next_refresh_time': time1, 
-                    'refresh_timeout': time1 + MAX_TRANSFER_TIMEOUT, 
-                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
+                    'last_refresh_time': time1 - 7200,
+                    'next_refresh_time': time1,
+                    'refresh_timeout': time1 + MAX_TRANSFER_TIMEOUT,
+                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600',
                     'zone_state': ZONE_REFRESHING}
                 }
         zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
         self.assertEqual(ZONE_NAME_CLASS1_IN, zone_need_refresh)
 
-        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH]["refresh_timeout"] = time1 
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH]["refresh_timeout"] = time1
         zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
         self.assertEqual(ZONE_NAME_CLASS2_CH, zone_need_refresh)
 
@@ -375,42 +387,42 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.", "IN"):{
                     'last_refresh_time': time1 - 7200,
-                    'next_refresh_time': time1 - 1, 
-                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
+                    'next_refresh_time': time1 - 1,
+                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
                     'zone_state': ZONE_OK}
                 }
         self.zone_refresh._do_refresh(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
         self.assertEqual(ZONE_REFRESHING, zone_state)
-        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] 
+        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"]
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
-        self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout) 
+        self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout)
 
         self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = "127.0.0.1"
         self.zone_refresh._do_refresh(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
-        self.assertEqual(ZONE_REFRESHING, zone_state) 
-        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] 
+        self.assertEqual(ZONE_REFRESHING, zone_state)
+        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"]
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
         self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout)
         self.assertFalse("notify_master" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
 
     def test_run_timer(self):
-        """This case will run timer in daemon thread. 
-        The zone's next_refresh_time is less than now, so zonemgr will do zone refresh 
-        immediately. The zone's state will become "refreshing". 
+        """This case will run timer in daemon thread.
+        The zone's next_refresh_time is less than now, so zonemgr will do zone refresh
+        immediately. The zone's state will become "refreshing".
         """
         time1 = time.time()
         self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.", "IN"):{
                     'last_refresh_time': time1 - 7200,
-                    'next_refresh_time': time1 - 1, 
-                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
+                    'next_refresh_time': time1 - 1,
+                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
                     'zone_state': ZONE_OK}
                 }
-        self.zone_refresh._check_sock = self.zone_refresh._master_socket 
+        self.zone_refresh._check_sock = self.zone_refresh._master_socket
         listener = self.zone_refresh.run_timer(daemon=True)
         # Shut down the timer thread
         self.zone_refresh.shutdown()
@@ -424,17 +436,19 @@ class TestZonemgrRefresh(unittest.TestCase):
                     "lowerbound_refresh" : 60,
                     "lowerbound_retry" : 30,
                     "max_transfer_timeout" : 19800,
-                    "jitter_scope" : 0.25,
+                    "refresh_jitter" : 0.25,
+                    "reload_jitter" : 0.75,
                     "secondary_zones": []
                 }
         self.zone_refresh.update_config_data(config_data)
         self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(30, self.zone_refresh._lowerbound_retry)
         self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
-        self.assertEqual(0.25, self.zone_refresh._jitter_scope)
+        self.assertEqual(0.25, self.zone_refresh._refresh_jitter)
+        self.assertEqual(0.75, self.zone_refresh._reload_jitter)
 
     def test_shutdown(self):
-        self.zone_refresh._check_sock = self.zone_refresh._master_socket 
+        self.zone_refresh._check_sock = self.zone_refresh._master_socket
         listener = self.zone_refresh.run_timer()
         self.assertTrue(listener.is_alive())
         # Shut down the timer thread
@@ -473,7 +487,7 @@ class TestZonemgrRefresh(unittest.TestCase):
 class MyCCSession():
     def __init__(self):
         pass
-                    
+
     def get_remote_config_value(self, module_name, identifier):
         if module_name == "Auth" and identifier == "database_file":
             return "initdb.file", False
@@ -493,7 +507,8 @@ class MyZonemgr(Zonemgr):
                     "lowerbound_refresh" : 10,
                     "lowerbound_retry" : 5,
                     "max_transfer_timeout" : 14400,
-                    "jitter_scope" : 0.1,
+                    "refresh_jitter" : 0.1,
+                    "reload_jitter" : 0.75,
                     "secondary_zones": []
                     }
 
@@ -510,7 +525,8 @@ class TestZonemgr(unittest.TestCase):
                     "lowerbound_refresh" : 60,
                     "lowerbound_retry" : 30,
                     "max_transfer_timeout" : 14400,
-                    "jitter_scope" : 0.1,
+                    "refresh_jitter" : 0.1,
+                    "reload_jitter" : 0.75,
                     "secondary_zones": []
                     }
         self.assertEqual(self.zonemgr.config_handler(config_data1),
@@ -520,9 +536,9 @@ class TestZonemgr(unittest.TestCase):
         self.zonemgr.config_handler(config_data2)
         self.assertEqual(config_data1, self.zonemgr._config_data)
         # jitter should not be bigger than half of the original value
-        config_data3 = {"jitter_scope" : 0.7}
+        config_data3 = {"refresh_jitter" : 0.7}
         self.zonemgr.config_handler(config_data3)
-        self.assertEqual(0.5, self.zonemgr._config_data.get("jitter_scope"))
+        self.assertEqual(0.5, self.zonemgr._config_data.get("refresh_jitter"))
         # The zone doesn't exist in database, it should be rejected
         self.zonemgr._zone_refresh = ZonemgrRefresh(None, "initdb.file", None,
                                                     config_data1)
@@ -531,7 +547,7 @@ class TestZonemgr(unittest.TestCase):
         self.assertNotEqual(self.zonemgr.config_handler(config_data1),
                             {"result": [0]})
         # As it is rejected, the old value should be kept
-        self.assertEqual(0.5, self.zonemgr._config_data.get("jitter_scope"))
+        self.assertEqual(0.5, self.zonemgr._config_data.get("refresh_jitter"))
 
     def test_get_db_file(self):
         self.assertEqual("initdb.file", self.zonemgr.get_db_file())
@@ -549,12 +565,12 @@ class TestZonemgr(unittest.TestCase):
 
     def test_config_data_check(self):
         # jitter should not be bigger than half of the original value
-        config_data2 = {"jitter_scope" : 0.2}
-        config_data3 = {"jitter_scope" : 0.6}
+        config_data2 = {"refresh_jitter" : 0.2}
+        config_data3 = {"refresh_jitter" : 0.6}
         self.zonemgr._config_data_check(config_data2)
-        self.assertEqual(0.2, config_data2.get("jitter_scope"))
+        self.assertEqual(0.2, config_data2.get("refresh_jitter"))
         self.zonemgr._config_data_check(config_data3)
-        self.assertEqual(0.5, config_data3.get("jitter_scope"))
+        self.assertEqual(0.5, config_data3.get("refresh_jitter"))
 
     def tearDown(self):
         pass

+ 13 - 10
src/bin/zonemgr/zonemgr.py.in

@@ -125,19 +125,19 @@ class ZonemgrRefresh:
 
     def _set_zone_refresh_timer(self, zone_name_class):
         """Set zone next refresh time after zone refresh success.
-           now + refresh - jitter  <= next_refresh_time <= now + refresh
+           now + refresh - refresh_jitter <= next_refresh_time <= now + refresh
            """
         zone_refresh_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[REFRESH_OFFSET])
         zone_refresh_time = max(self._lowerbound_refresh, zone_refresh_time)
-        self._set_zone_timer(zone_name_class, zone_refresh_time, self._jitter_scope * zone_refresh_time)
+        self._set_zone_timer(zone_name_class, zone_refresh_time, self._refresh_jitter * zone_refresh_time)
 
     def _set_zone_retry_timer(self, zone_name_class):
         """Set zone next refresh time after zone refresh fail.
-           now + retry - jitter <= next_refresh_time <= now + retry
+           now + retry - retry_jitter <= next_refresh_time <= now + retry
            """
         zone_retry_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[RETRY_OFFSET])
         zone_retry_time = max(self._lowerbound_retry, zone_retry_time)
-        self._set_zone_timer(zone_name_class, zone_retry_time, self._jitter_scope * zone_retry_time)
+        self._set_zone_timer(zone_name_class, zone_retry_time, self._refresh_jitter * zone_retry_time)
 
     def _set_zone_notify_timer(self, zone_name_class):
         """Set zone next refresh time after receiving notify
@@ -194,9 +194,11 @@ class ZonemgrRefresh:
         zone_info["zone_soa_rdata"] = zone_soa[7]
         zone_info["zone_state"] = ZONE_OK
         zone_info["last_refresh_time"] = self._get_current_time()
-        zone_info["next_refresh_time"] = self._get_current_time() + \
-                                         float(zone_soa[7].split(" ")[REFRESH_OFFSET])
         self._zonemgr_refresh_info[zone_name_class] = zone_info
+        # Imposes some random jitters to avoid many zones need to do refresh at the same time.
+        zone_reload_jitter = float(zone_soa[7].split(" ")[RETRY_OFFSET])
+        zone_reload_jitter = max(self._lowerbound_retry, zone_reload_jitter)
+        self._set_zone_timer(zone_name_class, zone_reload_jitter, self._reload_jitter * zone_reload_jitter)
 
     def _zone_is_expired(self, zone_name_class):
         """Judge whether a zone is expired or not."""
@@ -431,7 +433,8 @@ class ZonemgrRefresh:
         self._lowerbound_refresh = new_config.get('lowerbound_refresh')
         self._lowerbound_retry = new_config.get('lowerbound_retry')
         self._max_transfer_timeout = new_config.get('max_transfer_timeout')
-        self._jitter_scope = new_config.get('jitter_scope')
+        self._refresh_jitter = new_config.get('refresh_jitter')
+        self._reload_jitter = new_config.get('reload_jitter')
 
 class Zonemgr:
     """Zone manager class."""
@@ -510,9 +513,9 @@ class Zonemgr:
         not. It contains only basic logic, not full check against
         database."""
         # jitter should not be bigger than half of the original value
-        if config_data.get('jitter_scope') > 0.5:
-            config_data['jitter_scope'] = 0.5
-            log_msg("[b10-zonemgr] jitter_scope is too big, its value will "
+        if config_data.get('refresh_jitter') > 0.5:
+            config_data['refresh_jitter'] = 0.5
+            log_msg("[b10-zonemgr] refresh_jitter is too big, its value will "
                       "be set to 0.5")
 
 

+ 9 - 3
src/bin/zonemgr/zonemgr.spec.pre.in

@@ -12,21 +12,27 @@
          "item_name": "lowerbound_retry",
          "item_type": "integer",
          "item_optional": false,
-         "item_default": 5 
+         "item_default": 5
        },
        {
          "item_name": "max_transfer_timeout",
          "item_type": "integer",
          "item_optional": false,
-         "item_default": 14400 
+         "item_default": 14400
        },
        {
-         "item_name": "jitter_scope",
+         "item_name": "refresh_jitter",
          "item_type": "real",
          "item_optional": false,
          "item_default": 0.25
        },
        {
+         "item_name": "reload_jitter",
+         "item_type": "real",
+         "item_optional": false,
+         "item_default": 0.75
+       },
+       {
          "item_name": "secondary_zones",
          "item_type": "list",
          "item_optional": false,

+ 3 - 3
src/cppcheck-suppress.lst

@@ -3,13 +3,13 @@
 debug
 missingInclude
 // This is a template, and should be excluded from the check
-unreadVariable:src/lib/dns/rdata/template.cc:59
+unreadVariable:src/lib/dns/rdata/template.cc:60
 // These three trigger warnings due to the incomplete implementation.  This is
 // our problem, but we need to suppress the warnings for now.
 functionConst:src/lib/cache/resolver_cache.h
 functionConst:src/lib/cache/message_cache.h
 functionConst:src/lib/cache/rrset_cache.h
 // Intentional self assignment tests.  Suppress warning about them.
-selfAssignment:src/lib/dns/tests/name_unittest.cc:292
-selfAssignment:src/lib/dns/tests/rdata_unittest.cc:227
+selfAssignment:src/lib/dns/tests/name_unittest.cc:293
+selfAssignment:src/lib/dns/tests/rdata_unittest.cc:228
 selfAssignment:src/lib/dns/tests/tsigkey_unittest.cc:104

+ 2 - 2
src/lib/Makefile.am

@@ -1,2 +1,2 @@
-SUBDIRS = exceptions dns cc config util python xfr bench log asiolink \
-          nsas cache resolve testutils datasrc server_common
+SUBDIRS = exceptions util dns cc config python xfr bench log asiolink \
+          asiodns nsas cache resolve testutils datasrc server_common

+ 34 - 0
src/lib/asiodns/Makefile.am

@@ -0,0 +1,34 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink -I$(top_builddir)/src/lib/asiolink
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+CLEANFILES = *.gcno *.gcda
+
+lib_LTLIBRARIES = libasiodns.la
+libasiodns_la_SOURCES = dns_answer.h
+libasiodns_la_SOURCES += asiodns.h
+libasiodns_la_SOURCES += asiodef.cc asiodef.h
+libasiodns_la_SOURCES += dns_lookup.h
+libasiodns_la_SOURCES += dns_server.h
+libasiodns_la_SOURCES += dns_service.cc dns_service.h
+libasiodns_la_SOURCES += tcp_server.cc tcp_server.h
+libasiodns_la_SOURCES += udp_server.cc udp_server.h
+libasiodns_la_SOURCES += io_fetch.cc io_fetch.h
+
+EXTRA_DIST = asiodef.msg
+
+# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
+# B10_CXXFLAGS)
+libasiodns_la_CXXFLAGS = $(AM_CXXFLAGS)
+if USE_CLANGPP
+# Same for clang++, but we need to turn off -Werror completely.
+libasiodns_la_CXXFLAGS += -Wno-error
+endif
+libasiodns_la_CPPFLAGS = $(AM_CPPFLAGS)
+libasiodns_la_LIBADD = $(top_builddir)/src/lib/log/liblog.la

+ 157 - 0
src/lib/asiodns/README

@@ -0,0 +1,157 @@
+The asiodns library is intended to provide an abstraction layer between
+BIND10 modules and asiolink library.
+
+These DNS server and client routines are written using the "stackless
+coroutine" pattern invented by Chris Kohlhoff and described at
+http://blog.think-async.com/2010/03/potted-guide-to-stackless-coroutines.html.
+This is intended to simplify development a bit, since it allows the
+routines to be written in a straightfowrard step-step-step fashion rather
+than as a complex chain of separate handler functions.
+
+Coroutine objects (i.e., UDPServer, TCPServer and IOFetch) are objects
+with reenterable operator() members.  When an instance of one of these
+classes is called as a function, it resumes at the position where it left
+off.  Thus, a UDPServer can issue an asynchronous I/O call and specify
+itself as the handler object; when the call completes, the UDPServer
+carries on at the same position.  As a result, the code can look as
+if it were using synchronous, not asynchronous, I/O, providing some of
+the benefit of threading but with minimal switching overhead.
+
+So, in simplified form, the behavior of a DNS Server is:
+
+  REENTER:
+    while true:
+      YIELD packet = read_packet
+      FORK
+      if not parent:
+        break
+
+    # This callback informs the caller that a packet has arrived, and
+    # gives it a chance to update configuration, etc
+    SimpleCallback(packet)
+    YIELD answer = DNSLookup(packet, this)
+    response = DNSAnswer(answer)
+    YIELD send(response)
+
+At each "YIELD" point, the coroutine initiates an asynchronous operation,
+then pauses and turns over control to some other task on the ASIO service
+queue.  When the operation completes, the coroutine resumes.
+
+DNSLookup, DNSAnswer and SimpleCallback define callback methods
+used by a DNS Server to communicate with the module that called it.
+They are abstract-only classes whose concrete implementations
+are supplied by the calling module.
+
+The DNSLookup callback always runs asynchronously.  Concrete
+implementations must be sure to call the server's "resume" method when
+it is finished.
+
+In an authoritative server, the DNSLookup implementation would examine
+the query, look up the answer, then call "resume".  (See the diagram
+in doc/auth_process.jpg.)
+
+In a recursive server, the DNSLookup impelemtation would initiate a
+DNSQuery, which in turn would be responsible for calling the server's
+"resume" method.  (See the diagram in doc/recursive_process.jpg.)
+
+A DNSQuery object is intended to handle resolution of a query over
+the network when the local authoritative data sources or cache are not
+sufficient.  The plan is that it will make use of subsidiary DNSFetch
+calls to get data from particular authoritative servers, and when it has
+gotten a complete answer, it calls "resume".
+
+In current form, however, DNSQuery is much simpler; it forwards queries
+to a single upstream resolver and passes the answers back to the client.
+It is constructed with the address of the forward server.  Queries are
+initiated with the question to ask the forward server, a buffer into
+which to write the answer, and a pointer to the coroutine to be resumed
+when the answer has arrived.  In simplified form, the DNSQuery routine is:
+
+  REENTER:
+    render the question into a wire-format query packet
+    YIELD send(query)
+    YIELD response = read_packet
+    server->resume
+
+Currently, DNSQuery is only implemented for UDP queries.  In future work
+it will be necessary to write code to fall back to TCP when circumstances
+require it.
+
+
+Upstream Fetches
+================
+Upstream fetches (queries by the resolver on behalf of a client) are made
+using a slightly-modified version of the pattern described above.
+
+Sockets
+-------
+First, it will be useful to understand the class hierarchy used in the
+fetch logic:
+
+        IOSocket
+           |
+      IOAsioSocket
+           |
+     +-----+-----+                
+     |           |
+UDPSocket    TCPSocket
+
+IOSocket is a wrapper class for a socket and is used by the authoritative
+server code.  It is an abstract base class, providing little more that the ability to hold the socket and to return the protocol in use.
+
+Built on this is IOAsioSocket, which adds the open, close, asyncSend and
+asyncReceive methods.  This is a template class, which takes as template
+argument the class of the object that will be used as the callback when the
+asynchronous operation completes. This object can be of any type, but must
+include an operator() method with the signature:
+
+   operator()(asio::error_code ec, size_t length)
+
+... the two arguments being the status of the completed I/O operation and
+the number of bytes transferred. (In the case of the open method, the second
+argument will be zero.)
+
+Finally, the TCPSocket and UDPSocket classes provide the body of the
+asynchronous operations.
+
+Fetch Sequence
+--------------
+The fetch is implemented by the IOFetch class, which takes as argument the
+protocol to use.  The sequence is:
+
+  REENTER:
+    render the question into a wire-format query packet
+    open()                           // Open socket and optionally connect
+    if (! synchronous) {
+        YIELD;
+    }
+    YIELD asyncSend(query)           // Send query 
+    do {
+        YIELD asyncReceive(response) // Read response
+    } while (! complete(response))
+    close()                          // Drop connection and close socket
+    server->resume
+
+The open() method opens a socket for use.  On TCP, it also makes a
+connection to the remote end.  So under UDP the operation will complete
+immediately, but under TCP it could take a long time.  One solution would be
+for the open operation to post an event to the I/O queue; then both cases
+could be regarded as being equivalent, with the completion being signalled
+by the posting of the completion event.  However UDP is the most common case
+and that would involve extra overhead.  So the open() returns a status
+indicating whether the operation completed asynchronously.  If it did, the
+code yields back to the coroutine; if not the yield is bypassed.
+
+The asynchronous send is straightforward, invoking the underlying ASIO
+function.  (Note that the address/port is supplied to both the open() and
+asyncSend() methods - it is used by the TCPSocket in open() and by the
+UDPSocket in asyncSend().)
+
+The asyncReceive() method issues an asynchronous read and waits for completion.
+The fetch object keeps track of the amount of data received so far and when
+the receive completes it calls a method on the socket to determine if the
+entire message has been received.  (This will always be the case for UDP.  On
+TCP though, the message is preceded by a count field as several reads may be
+required to read all the data.)  The fetch loops until all the data is read.
+
+Finally, the socket is closed and the server called to resume operation.

+ 14 - 12
src/lib/asiolink/asiodef.cc

@@ -4,18 +4,20 @@
 #include <log/message_types.h>
 #include <log/message_initializer.h>
 
-namespace asiolink {
-
-extern const isc::log::MessageID ASIO_FETCHCOMP = "FETCHCOMP";
-extern const isc::log::MessageID ASIO_FETCHSTOP = "FETCHSTOP";
-extern const isc::log::MessageID ASIO_OPENSOCK = "OPENSOCK";
-extern const isc::log::MessageID ASIO_RECVSOCK = "RECVSOCK";
-extern const isc::log::MessageID ASIO_RECVTMO = "RECVTMO";
-extern const isc::log::MessageID ASIO_SENDSOCK = "SENDSOCK";
-extern const isc::log::MessageID ASIO_UNKORIGIN = "UNKORIGIN";
-extern const isc::log::MessageID ASIO_UNKRESULT = "UNKRESULT";
-
-} // namespace asiolink
+namespace isc {
+namespace asiodns {
+
+extern const isc::log::MessageID ASIODNS_FETCHCOMP = "FETCHCOMP";
+extern const isc::log::MessageID ASIODNS_FETCHSTOP = "FETCHSTOP";
+extern const isc::log::MessageID ASIODNS_OPENSOCK = "OPENSOCK";
+extern const isc::log::MessageID ASIODNS_RECVSOCK = "RECVSOCK";
+extern const isc::log::MessageID ASIODNS_RECVTMO = "RECVTMO";
+extern const isc::log::MessageID ASIODNS_SENDSOCK = "SENDSOCK";
+extern const isc::log::MessageID ASIODNS_UNKORIGIN = "UNKORIGIN";
+extern const isc::log::MessageID ASIODNS_UNKRESULT = "UNKRESULT";
+
+} // namespace asiodns
+} // namespace isc
 
 namespace {
 

+ 23 - 0
src/lib/asiodns/asiodef.h

@@ -0,0 +1,23 @@
+// File created from asiodef.msg on Mon Feb 28 17:15:30 2011
+
+#ifndef __ASIODEF_H
+#define __ASIODEF_H
+
+#include <log/message_types.h>
+
+namespace isc {
+namespace asiodns {
+
+extern const isc::log::MessageID ASIODNS_FETCHCOMP;
+extern const isc::log::MessageID ASIODNS_FETCHSTOP;
+extern const isc::log::MessageID ASIODNS_OPENSOCK;
+extern const isc::log::MessageID ASIODNS_RECVSOCK;
+extern const isc::log::MessageID ASIODNS_RECVTMO;
+extern const isc::log::MessageID ASIODNS_SENDSOCK;
+extern const isc::log::MessageID ASIODNS_UNKORIGIN;
+extern const isc::log::MessageID ASIODNS_UNKRESULT;
+
+} // namespace asiodns
+} // namespace isc
+
+#endif // __ASIODEF_H

+ 2 - 2
src/lib/asiolink/asiodef.msg

@@ -12,8 +12,8 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-$PREFIX ASIO_
-$NAMESPACE asiolink
+$PREFIX ASIODNS_
+$NAMESPACE isc::asiodns
 
 FETCHCOMP   upstream fetch to %s(%d) has now completed
 + A debug message, this records the the upstream fetch (a query made by the

+ 23 - 0
src/lib/asiodns/asiodns.h

@@ -0,0 +1,23 @@
+// Copyright (C) 2011  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 __ASIODNS_H
+#define __ASIODNS_H 1
+
+#include <asiodns/dns_service.h>
+#include <asiodns/dns_server.h>
+#include <asiodns/dns_lookup.h>
+#include <asiodns/dns_answer.h>
+
+#endif // __ASIODNS_H

+ 8 - 4
src/lib/asiolink/dns_answer.h

@@ -16,8 +16,11 @@
 #define __ASIOLINK_DNS_ANSWER_H 1
 
 #include <asiolink/io_message.h>
+#include <util/buffer.h>
+#include <dns/message.h>
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 /// \brief The \c DNSAnswer class is an abstract base class for a DNS
 /// Answer provider function.
@@ -63,11 +66,12 @@ public:
     /// \param answer_message The DNS MessagePtr of the answer we are
     /// building
     /// \param buffer Intermediate data results are put here
-    virtual void operator()(const IOMessage& io_message,
+    virtual void operator()(const asiolink::IOMessage& io_message,
                             isc::dns::MessagePtr query_message,
                             isc::dns::MessagePtr answer_message,
-                            isc::dns::OutputBufferPtr buffer) const = 0;
+                            isc::util::OutputBufferPtr buffer) const = 0;
 };
 
-}      // namespace asiolink
+}      // namespace asiodns
+}      // namespace isc
 #endif // __ASIOLINK_DNS_ANSWER_H

+ 8 - 6
src/lib/asiolink/dns_lookup.h

@@ -16,11 +16,12 @@
 #define __ASIOLINK_DNS_LOOKUP_H 1
 
 #include <asiolink/io_message.h>
-#include <asiolink/dns_server.h>
-#include <dns/buffer.h>
+#include <asiodns/dns_server.h>
 #include <dns/message.h>
+#include <util/buffer.h>
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 /// \brief The \c DNSLookup class is an abstract base class for a DNS
 /// Lookup provider function.
@@ -67,10 +68,10 @@ public:
     ///                       this MessagePtr
     /// \param buffer The final answer is put here
     /// \param server DNSServer object to use
-    virtual void operator()(const IOMessage& io_message,
+    virtual void operator()(const asiolink::IOMessage& io_message,
                             isc::dns::MessagePtr message,
                             isc::dns::MessagePtr answer_message,
-                            isc::dns::OutputBufferPtr buffer,
+                            isc::util::OutputBufferPtr buffer,
                             DNSServer* server) const
     {
         (*self_)(io_message, message, answer_message, buffer, server);
@@ -79,5 +80,6 @@ private:
     DNSLookup* self_;
 };
 
-}      // namespace asiolink
+}      // namespace asiodns
+}      // namespace isc
 #endif // __ASIOLINK_DNS_LOOKUP_H

+ 5 - 3
src/lib/asiolink/dns_server.h

@@ -17,7 +17,8 @@
 
 #include <asiolink/io_message.h>
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 /// \brief The \c DNSServer class is a wrapper (and base class) for
 /// classes which provide DNS server functionality.
@@ -34,7 +35,7 @@ namespace asiolink {
 /// instantiated through a base class) are sometimes passed by
 /// reference (as this superclass); calls to methods in the base
 /// class are then rerouted via this pointer to methods in the derived
-/// class.  This allows code from outside asiolink, with no specific
+/// class.  This allows code from outside asiodns, with no specific
 /// knowledge of \c TCPServer or \c UDPServer, to access their methods.
 ///
 /// This class is both assignable and copy-constructable.  Its subclasses
@@ -151,5 +152,6 @@ private:
 };
 
 
-}      // asiolink
+} // namespace asiodns
+} // namespace isc
 #endif // __ASIOLINK_DNS_SERVER_H

+ 9 - 8
src/lib/asiolink/dns_service.cc

@@ -23,11 +23,11 @@
 #include <log/dummylog.h>
 
 #include <asio.hpp>
-#include <asiolink/dns_service.h>
+#include <dns_service.h>
 #include <asiolink/io_service.h>
 #include <asiolink/io_service.h>
-#include <asiolink/tcp_server.h>
-#include <asiolink/udp_server.h>
+#include <tcp_server.h>
+#include <udp_server.h>
 
 #include <log/dummylog.h>
 
@@ -36,9 +36,11 @@
 
 using isc::log::dlog;
 
-namespace asiolink {
+using namespace isc::asiolink;
+
+namespace isc {
+namespace asiodns {
 
-class SimpleCallback;
 class DNSLookup;
 class DNSAnswer;
 
@@ -195,6 +197,5 @@ DNSService::clearServers() {
     impl_->servers_.clear();
 }
 
-
-
-} // namespace asiolink
+} // namespace asiodns
+} // namespace isc

+ 11 - 9
src/lib/asiolink/dns_service.h

@@ -18,10 +18,11 @@
 #include <resolve/resolver_interface.h>
 
 #include <asiolink/io_service.h>
+#include <asiolink/simple_callback.h>
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
-class SimpleCallback;
 class DNSLookup;
 class DNSAnswer;
 class DNSServiceImpl;
@@ -54,8 +55,8 @@ public:
     /// \param checkin Provider for cc-channel events (see \c SimpleCallback)
     /// \param lookup The lookup provider (see \c DNSLookup)
     /// \param answer The answer provider (see \c DNSAnswer)
-    DNSService(IOService& io_service, const char& port,
-               const char& address, SimpleCallback* checkin,
+    DNSService(asiolink::IOService& io_service, const char& port,
+               const char& address, isc::asiolink::SimpleCallback* checkin,
                DNSLookup* lookup, DNSAnswer* answer);
     /// \brief The constructor with a specific port on which the services
     /// listen on.
@@ -71,14 +72,14 @@ public:
     /// \param checkin Provider for cc-channel events (see \c SimpleCallback)
     /// \param lookup The lookup provider (see \c DNSLookup)
     /// \param answer The answer provider (see \c DNSAnswer)
-    DNSService(IOService& io_service, const char& port,
+    DNSService(asiolink::IOService& io_service, const char& port,
                const bool use_ipv4, const bool use_ipv6,
-               SimpleCallback* checkin, DNSLookup* lookup,
+               isc::asiolink::SimpleCallback* checkin, DNSLookup* lookup,
                DNSAnswer* answer);
     /// \brief The constructor without any servers.
     ///
     /// Use addServer() to add some servers.
-    DNSService(IOService& io_service, SimpleCallback* checkin,
+    DNSService(asiolink::IOService& io_service, isc::asiolink::SimpleCallback* checkin,
                DNSLookup* lookup, DNSAnswer* answer);
     /// \brief The destructor.
     ~DNSService();
@@ -105,8 +106,9 @@ public:
 
 private:
     DNSServiceImpl* impl_;
-    IOService& io_service_;
+    asiolink::IOService& io_service_;
 };
 
-}      // namespace asiolink
+} // namespace asiodns
+} // namespace isc
 #endif // __ASIOLINK_DNS_SERVICE_H

+ 70 - 43
src/lib/asiolink/io_fetch.cc

@@ -14,45 +14,50 @@
 
 #include <config.h>
 
-#include <unistd.h>             // for some IPC/network system calls
-#include <sys/socket.h>
 #include <netinet/in.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <unistd.h>             // for some IPC/network system calls
 
 #include <boost/bind.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 
-#include <dns/message.h>
-#include <dns/messagerenderer.h>
-#include <dns/opcode.h>
-#include <dns/rcode.h>
-#include <log/logger.h>
-
-#include <asiolink/qid_gen.h>
-
 #include <asio.hpp>
 #include <asio/deadline_timer.hpp>
 
-#include <asiolink/asiodef.h>
 #include <asiolink/io_address.h>
 #include <asiolink/io_asio_socket.h>
 #include <asiolink/io_endpoint.h>
-#include <asiolink/io_fetch.h>
 #include <asiolink/io_service.h>
 #include <asiolink/tcp_endpoint.h>
 #include <asiolink/tcp_socket.h>
 #include <asiolink/udp_endpoint.h>
 #include <asiolink/udp_socket.h>
-#include <asiolink/qid_gen.h>
 
-#include <stdint.h>
+#include <dns/message.h>
+#include <dns/messagerenderer.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <log/logger.h>
+
+#include <asiodns/asiodef.h>
+#include <asiodns/io_fetch.h>
+
+#include <util/buffer.h>
+#include <util/random/qid_gen.h>
+
 
 using namespace asio;
+using namespace isc::asiolink;
 using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::util::random;
 using namespace isc::log;
 using namespace std;
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 /// Use the ASIO logger
 
@@ -76,8 +81,8 @@ struct IOFetchData {
     boost::scoped_ptr<IOEndpoint> remote_snd;///< Where the fetch is sent
     boost::scoped_ptr<IOEndpoint> remote_rcv;///< Where the response came from
     isc::dns::Question          question;    ///< Question to be asked
-    isc::dns::OutputBufferPtr   msgbuf;      ///< Wire buffer for question
-    isc::dns::OutputBufferPtr   received;    ///< Received data put here
+    OutputBufferPtr   msgbuf;      ///< Wire buffer for question
+    OutputBufferPtr   received;    ///< Received data put here
     IOFetch::Callback*          callback;    ///< Called on I/O Completion
     asio::deadline_timer        timer;       ///< Timer to measure timeouts
     IOFetch::Protocol           protocol;    ///< Protocol being used
@@ -86,6 +91,7 @@ struct IOFetchData {
     size_t                      offset;      ///< Offset to receive data
     bool                        stopped;     ///< Have we stopped running?
     int                         timeout;     ///< Timeout in ms
+    bool                        packet;      ///< true if packet was supplied
 
     // In case we need to log an error, the origin of the last asynchronous
     // I/O is recorded.  To save time and simplify the code, this is recorded
@@ -117,8 +123,7 @@ struct IOFetchData {
     /// TODO: May need to alter constructor (see comment 4 in Trac ticket #554)
     IOFetchData(IOFetch::Protocol proto, IOService& service,
         const isc::dns::Question& query, const IOAddress& address,
-        uint16_t port, isc::dns::OutputBufferPtr& buff, IOFetch::Callback* cb,
-        int wait)
+        uint16_t port, OutputBufferPtr& buff, IOFetch::Callback* cb, int wait)
         :
         socket((proto == IOFetch::UDP) ?
             static_cast<IOAsioSocket<IOFetch>*>(
@@ -135,9 +140,8 @@ struct IOFetchData {
             static_cast<IOEndpoint*>(new TCPEndpoint(address, port))
             ),
         question(query),
-        msgbuf(new isc::dns::OutputBuffer(512)),
+        msgbuf(new OutputBuffer(512)),
         received(buff),
-
         callback(cb),
         timer(service.get_io_service()),
         protocol(proto),
@@ -146,7 +150,8 @@ struct IOFetchData {
         offset(0),
         stopped(false),
         timeout(wait),
-        origin(ASIO_UNKORIGIN),
+        packet(false),
+        origin(ASIODNS_UNKORIGIN),
         staging(),
         qid(QidGenerator::getInstance().generateQid())
     {}
@@ -175,6 +180,19 @@ IOFetch::IOFetch(Protocol protocol, IOService& service,
 {
 }
 
+IOFetch::IOFetch(Protocol protocol, IOService& service,
+    OutputBufferPtr& outpkt, const IOAddress& address, uint16_t port,
+    OutputBufferPtr& buff, Callback* cb, int wait)
+    :
+    data_(new IOFetchData(protocol, service,
+          isc::dns::Question(isc::dns::Name("dummy.example.org"),
+                             isc::dns::RRClass::IN(), isc::dns::RRType::A()),
+          address, port, buff, cb, wait))
+{
+    data_->msgbuf = outpkt;
+    data_->packet = true;
+}
+
 // Return protocol in use.
 
 IOFetch::Protocol
@@ -201,14 +219,22 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
         /// This is done in a different scope to allow inline variable
         /// declarations.
         {
-            Message msg(Message::RENDER);
-            msg.setQid(data_->qid);
-            msg.setOpcode(Opcode::QUERY());
-            msg.setRcode(Rcode::NOERROR());
-            msg.setHeaderFlag(Message::HEADERFLAG_RD);
-            msg.addQuestion(data_->question);
-            MessageRenderer renderer(*data_->msgbuf);
-            msg.toWire(renderer);
+            if (data_->packet) {
+                // A packet was given, overwrite the QID (which is in the
+                // first two bytes of the packet).
+                data_->msgbuf->writeUint16At(data_->qid, 0);
+
+            } else {
+                // A question was given, construct the packet
+                Message msg(Message::RENDER);
+                msg.setQid(data_->qid);
+                msg.setOpcode(Opcode::QUERY());
+                msg.setRcode(Rcode::NOERROR());
+                msg.setHeaderFlag(Message::HEADERFLAG_RD);
+                msg.addQuestion(data_->question);
+                MessageRenderer renderer(*data_->msgbuf);
+                msg.toWire(renderer);
+            }
         }
 
         // If we timeout, we stop, which will can cancel outstanding I/Os and
@@ -222,7 +248,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
 
         // Open a connection to the target system.  For speed, if the operation
         // is synchronous (i.e. UDP operation) we bypass the yield.
-        data_->origin = ASIO_OPENSOCK;
+        data_->origin = ASIODNS_OPENSOCK;
         if (data_->socket->isOpenSynchronous()) {
             data_->socket->open(data_->remote_snd.get(), *this);
         } else {
@@ -232,7 +258,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
         do {
             // Begin an asynchronous send, and then yield.  When the send completes,
             // we will resume immediately after this point.
-            data_->origin = ASIO_SENDSOCK;
+            data_->origin = ASIODNS_SENDSOCK;
             CORO_YIELD data_->socket->asyncSend(data_->msgbuf->getData(),
                 data_->msgbuf->getLength(), data_->remote_snd.get(), *this);
     
@@ -255,7 +281,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
             // received all the data before copying it back to the user's buffer.
             // And we want to minimise the amount of copying...
     
-            data_->origin = ASIO_RECVSOCK;
+            data_->origin = ASIODNS_RECVSOCK;
             data_->cumulative = 0;          // No data yet received
             data_->offset = 0;              // First data into start of buffer
             data_->received->clear();       // Clear the receive buffer
@@ -271,7 +297,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
 
         // Finished with this socket, so close it.  This will not generate an
         // I/O error, but reset the origin to unknown in case we change this.
-        data_->origin = ASIO_UNKORIGIN;
+        data_->origin = ASIODNS_UNKORIGIN;
         data_->socket->close();
 
         /// We are done
@@ -314,7 +340,7 @@ IOFetch::stop(Result result) {
         switch (result) {
             case TIME_OUT:
                 if (logger.isDebugEnabled(1)) {
-                    logger.debug(20, ASIO_RECVTMO,
+                    logger.debug(20, ASIODNS_RECVTMO,
                                  data_->remote_snd->getAddress().toText().c_str(),
                                  static_cast<int>(data_->remote_snd->getPort()));
                 }
@@ -322,7 +348,7 @@ IOFetch::stop(Result result) {
 
             case SUCCESS:
                 if (logger.isDebugEnabled(50)) {
-                    logger.debug(30, ASIO_FETCHCOMP,
+                    logger.debug(30, ASIODNS_FETCHCOMP,
                                  data_->remote_rcv->getAddress().toText().c_str(),
                                  static_cast<int>(data_->remote_rcv->getPort()));
                 }
@@ -332,13 +358,13 @@ IOFetch::stop(Result result) {
                 // Fetch has been stopped for some other reason.  This is
                 // allowed but as it is unusual it is logged, but with a lower
                 // debug level than a timeout (which is totally normal).
-                logger.debug(1, ASIO_FETCHSTOP,
+                logger.debug(1, ASIODNS_FETCHSTOP,
                              data_->remote_snd->getAddress().toText().c_str(),
                              static_cast<int>(data_->remote_snd->getPort()));
                 break;
 
             default:
-                logger.error(ASIO_UNKRESULT, static_cast<int>(result),
+                logger.error(ASIODNS_UNKRESULT, static_cast<int>(result),
                              data_->remote_snd->getAddress().toText().c_str(),
                              static_cast<int>(data_->remote_snd->getPort()));
         }
@@ -362,10 +388,10 @@ IOFetch::stop(Result result) {
 void IOFetch::logIOFailure(asio::error_code ec) {
 
     // Should only get here with a known error code.
-    assert((data_->origin == ASIO_OPENSOCK) ||
-           (data_->origin == ASIO_SENDSOCK) ||
-           (data_->origin == ASIO_RECVSOCK) ||
-           (data_->origin == ASIO_UNKORIGIN));
+    assert((data_->origin == ASIODNS_OPENSOCK) ||
+           (data_->origin == ASIODNS_SENDSOCK) ||
+           (data_->origin == ASIODNS_RECVSOCK) ||
+           (data_->origin == ASIODNS_UNKORIGIN));
 
     static const char* PROTOCOL[2] = {"TCP", "UDP"};
     logger.error(data_->origin,
@@ -376,5 +402,6 @@ void IOFetch::logIOFailure(asio::error_code ec) {
                  static_cast<int>(data_->remote_snd->getPort()));
 }
 
-} // namespace asiolink
+} // namespace asiodns
+} // namespace isc {
 

+ 35 - 10
src/lib/asiolink/io_fetch.h

@@ -24,16 +24,17 @@
 #include <coroutine.h>
 
 #include <asio/error_code.hpp>
+#include <asiolink/io_address.h>
+#include <asiolink/io_service.h>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
 #include <dns/question.h>
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 // Forward declarations
-class IOAddress;
 class IOFetchData;
-class IOService;
 
 /// \brief Upstream Fetch Processing
 ///
@@ -116,12 +117,34 @@ public:
     ///
     /// Creates the object that will handle the upstream fetch.
     ///
-    /// TODO: Need to randomise the source port
+    /// \param protocol Fetch protocol, either IOFetch::TCP or IOFetch::UDP
+    /// \param service I/O Service object to handle the asynchronous
+    ///        operations.
+    /// \param question DNS question to send to the upstream server.
+    /// \param address IP address of upstream server
+    /// \param port Port to which to connect on the upstream server
+    /// \param buff Output buffer into which the response (in wire format)
+    ///        is written (if a response is received).
+    /// \param cb Callback object containing the callback to be called when we
+    ///        terminate.  The caller is responsible for managing this object
+    ///        and deleting it if necessary.
+    /// \param wait Timeout for the fetch (in ms).  The default value of
+    ///        -1 indicates no timeout.
+    IOFetch(Protocol protocol, isc::asiolink::IOService& service,
+        const isc::dns::Question& question,
+        const isc::asiolink::IOAddress& address,
+        uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
+        int wait = -1);
+
+    /// \brief Constructor.
+    ///
+    /// Creates the object that will handle the upstream fetch.
     ///
     /// \param protocol Fetch protocol, either IOFetch::TCP or IOFetch::UDP
     /// \param service I/O Service object to handle the asynchronous
     ///     operations.
-    /// \param question DNS question to send to the upstream server.
+    /// \param outpkt Packet to send to upstream server.  Note that the
+    ///     QID (first two bytes of the packet) may be altered in the sending.
     /// \param buff Output buffer into which the response (in wire format)
     ///     is written (if a response is received).
     /// \param cb Callback object containing the callback to be called
@@ -132,9 +155,10 @@ public:
     /// (default = 53)
     /// \param wait Timeout for the fetch (in ms).  The default value of
     ///     -1 indicates no timeout.
-    IOFetch(Protocol protocol, IOService& service,
-        const isc::dns::Question& question, const IOAddress& address,
-        uint16_t port, isc::dns::OutputBufferPtr& buff, Callback* cb,
+    IOFetch(Protocol protocol, isc::asiolink::IOService& service,
+        isc::util::OutputBufferPtr& outpkt,
+        const isc::asiolink::IOAddress& address,
+        uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
         int wait = -1);
 
     /// \brief Return Current Protocol
@@ -174,6 +198,7 @@ private:
 
 };
 
-} // namespace asiolink
+} // namespace asiodns
+} // namespace isc
 
 #endif // __IO_FETCH_H

+ 9 - 4
src/lib/asiolink/tcp_server.cc

@@ -23,11 +23,13 @@
 
 #include <log/dummylog.h>
 
+#include <util/buffer.h>
+
 #include <asio.hpp>
 #include <asiolink/dummy_io_cb.h>
 #include <asiolink/tcp_endpoint.h>
 #include <asiolink/tcp_socket.h>
-#include <asiolink/tcp_server.h>
+#include <tcp_server.h>
 
 
 using namespace asio;
@@ -36,8 +38,11 @@ using asio::ip::tcp;
 
 using namespace std;
 using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::asiolink;
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 /// The following functions implement the \c TCPServer class.
 ///
@@ -235,5 +240,5 @@ TCPServer::resume(const bool done) {
     io_.post(*this);
 }
 
-} // namespace asiolink
-
+} // namespace asiodns
+} // namespace isc

+ 13 - 9
src/lib/asiolink/tcp_server.h

@@ -24,9 +24,12 @@
 
 #include <asiolink/asiolink.h>
 #include <coroutine.h>
+#include "dns_server.h"
+#include "dns_lookup.h"
+#include "dns_answer.h"
 
-
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 /// \brief A TCP-specific \c DNSServer object.
 ///
@@ -36,7 +39,7 @@ class TCPServer : public virtual DNSServer, public virtual coroutine {
 public:
     explicit TCPServer(asio::io_service& io_service,
                        const asio::ip::address& addr, const uint16_t port, 
-                       const SimpleCallback* checkin = NULL,
+                       const isc::asiolink::SimpleCallback* checkin = NULL,
                        const DNSLookup* lookup = NULL,
                        const DNSAnswer* answer = NULL);
 
@@ -91,11 +94,11 @@ private:
     boost::shared_ptr<asio::ip::tcp::socket> socket_;
 
     // The buffer into which the response is written
-    boost::shared_ptr<isc::dns::OutputBuffer> respbuf_;
+    boost::shared_ptr<isc::util::OutputBuffer> respbuf_;
 
     // \c IOMessage and \c Message objects to be passed to the
     // DNS lookup and answer providers
-    boost::shared_ptr<asiolink::IOMessage> io_message_;
+    boost::shared_ptr<isc::asiolink::IOMessage> io_message_;
     isc::dns::MessagePtr query_message_;
     isc::dns::MessagePtr answer_message_;
 
@@ -108,13 +111,14 @@ private:
     bool done_;
 
     // Callback functions provided by the caller
-    const SimpleCallback* checkin_callback_;
+    const isc::asiolink::SimpleCallback* checkin_callback_;
     const DNSLookup* lookup_callback_;
     const DNSAnswer* answer_callback_;
 
-    boost::shared_ptr<IOEndpoint> peer_;
-    boost::shared_ptr<IOSocket> iosock_;
+    boost::shared_ptr<isc::asiolink::IOEndpoint> peer_;
+    boost::shared_ptr<isc::asiolink::IOSocket> iosock_;
 };
 
-}      // namespace asiolink
+} // namespace asiodns
+} // namespace isc
 #endif // __TCP_SERVER_H

+ 50 - 0
src/lib/asiodns/tests/Makefile.am

@@ -0,0 +1,50 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -I$(top_builddir)/src/lib/dns -I$(top_srcdir)/src/bin
+AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc  -I$(top_builddir)/src/lib/util
+AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS =
+if HAVE_GTEST
+TESTS += run_unittests
+run_unittests_SOURCES  = run_unittests.cc
+run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.h
+run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
+run_unittests_SOURCES += io_service_unittest.cc
+run_unittests_SOURCES += dns_server_unittest.cc
+run_unittests_SOURCES += io_fetch_unittest.cc
+
+run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+
+run_unittests_LDADD  = $(GTEST_LDADD)
+run_unittests_LDADD += $(SQLITE_LIBS)
+run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
+run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
+run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
+
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) 
+
+# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
+# B10_CXXFLAGS)
+run_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+if USE_GXX
+run_unittests_CXXFLAGS += -Wno-unused-parameter
+endif
+if USE_CLANGPP
+# Same for clang++, but we need to turn off -Werror completely.
+run_unittests_CXXFLAGS += -Wno-error
+endif
+endif
+
+noinst_PROGRAMS = $(TESTS)

+ 9 - 7
src/lib/asiolink/tests/dns_server_unittest.cc

@@ -18,10 +18,10 @@
 #include <asio.hpp>
 #include <asiolink/io_endpoint.h>
 #include <asiolink/io_error.h>
-#include <asiolink/udp_server.h>
-#include <asiolink/tcp_server.h>
-#include <asiolink/dns_answer.h>
-#include <asiolink/dns_lookup.h>
+#include <asiodns/udp_server.h>
+#include <asiodns/tcp_server.h>
+#include <asiodns/dns_answer.h>
+#include <asiodns/dns_lookup.h>
 #include <string>
 #include <csignal>
 #include <unistd.h> //for alarm
@@ -65,8 +65,10 @@
 /// involved so the message sending between client and server is plain text
 /// And the valid checker, question lookup and answer composition are dummy.
 
-using namespace asiolink;
+using namespace isc::asiolink;
+using namespace isc::asiodns;
 using namespace asio;
+
 namespace {
 static const std::string server_ip = "127.0.0.1";
 const int server_port = 5553;
@@ -109,7 +111,7 @@ class DummyLookup : public DNSLookup, public ServerStopper {
         void operator()(const IOMessage& io_message,
                 isc::dns::MessagePtr message,
                 isc::dns::MessagePtr answer_message,
-                isc::dns::OutputBufferPtr buffer,
+                isc::util::OutputBufferPtr buffer,
                 DNSServer* server) const {
             stopServer();
             server->resume(true);
@@ -123,7 +125,7 @@ class SimpleAnswer : public DNSAnswer, public ServerStopper {
         void operator()(const IOMessage& message,
                 isc::dns::MessagePtr query_message,
                 isc::dns::MessagePtr answer_message,
-                isc::dns::OutputBufferPtr buffer) const
+                isc::util::OutputBufferPtr buffer) const
         {
             //copy what we get from user
             buffer->writeData(message.getData(), message.getDataSize());

+ 10 - 5
src/lib/asiolink/tests/io_fetch_unittest.cc

@@ -26,7 +26,9 @@
 
 #include <asio.hpp>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
+#include <util/io_utilities.h>
+
 #include <dns/question.h>
 #include <dns/message.h>
 #include <dns/messagerenderer.h>
@@ -34,18 +36,20 @@
 #include <dns/name.h>
 #include <dns/rcode.h>
 
-#include <asiolink/asiolink_utilities.h>
 #include <asiolink/io_address.h>
 #include <asiolink/io_endpoint.h>
-#include <asiolink/io_fetch.h>
 #include <asiolink/io_service.h>
+#include <asiodns/io_fetch.h>
 
 using namespace asio;
 using namespace isc::dns;
+using namespace isc::util;
 using namespace asio::ip;
 using namespace std;
+using namespace isc::asiolink;
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 const asio::ip::address TEST_HOST(asio::ip::address::from_string("127.0.0.1"));
 const uint16_t TEST_PORT(5301);
@@ -720,4 +724,5 @@ TEST_F(IOFetchTest, TcpSendReceive8192ShortSend) {
 }
 
 
-} // namespace asiolink
+} // namespace asiodns
+} // namespace isc

+ 3 - 1
src/lib/asiolink/tests/io_service_unittest.cc

@@ -17,8 +17,10 @@
 
 #include <asio.hpp>
 #include <asiolink/asiolink.h>
+#include <asiodns/asiodns.h>
 
-using namespace asiolink;
+using namespace isc::asiolink;
+using namespace isc::asiodns;
 
 const char* const TEST_SERVER_PORT = "53535";
 const char* const TEST_CLIENT_PORT = "53536";

+ 28 - 0
src/lib/asiodns/tests/run_unittests.cc

@@ -0,0 +1,28 @@
+// Copyright (C) 2009  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 <gtest/gtest.h>
+
+#include <log/root_logger_name.h>
+#include <dns/tests/unittest_util.h>
+
+int
+main(int argc, char* argv[])
+{
+    ::testing::InitGoogleTest(&argc, argv);         // Initialize Google test
+    isc::log::setRootLoggerName("unittest");        // Set a root logger name
+    isc::UnitTestUtil::addDataPath(TEST_DATA_DIR);  // Add location of test data
+
+    return (RUN_ALL_TESTS());
+}

+ 8 - 4
src/lib/asiolink/udp_server.cc

@@ -27,8 +27,8 @@
 #include <asio/error.hpp>
 #include <asiolink/dummy_io_cb.h>
 #include <asiolink/udp_endpoint.h>
-#include <asiolink/udp_server.h>
 #include <asiolink/udp_socket.h>
+#include "udp_server.h"
 
 #include <dns/opcode.h>
 
@@ -38,8 +38,11 @@ using isc::log::dlog;
 
 using namespace std;
 using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::asiolink;
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 /*
  * Some of the member variables here are shared_ptrs and some are
@@ -134,7 +137,7 @@ struct UDPServer::Data {
     isc::dns::MessagePtr answer_message_;
 
     // The buffer into which the response is written
-    isc::dns::OutputBufferPtr respbuf_;
+    isc::util::OutputBufferPtr respbuf_;
 
     // The buffer into which the query packet is written
     boost::shared_array<char> data_;
@@ -318,4 +321,5 @@ UDPServer::hasAnswer() {
     return (data_->done_);
 }
 
-} // namespace asiolink
+} // namespace asiodns
+} // namespace isc

+ 8 - 6
src/lib/asiolink/udp_server.h

@@ -19,14 +19,15 @@
 #error "asio.hpp must be included before including this, see asiolink.h as to why"
 #endif
 
-#include <asiolink/dns_server.h>
 #include <asiolink/simple_callback.h>
-#include <asiolink/dns_lookup.h>
-#include <asiolink/dns_answer.h>
+#include <asiodns/dns_answer.h>
+#include <asiodns/dns_lookup.h>
+#include <asiodns/dns_server.h>
 
 #include <coroutine.h>
 
-namespace asiolink {
+namespace isc {
+namespace asiodns {
 
 //
 // Asynchronous UDP server coroutine
@@ -47,7 +48,7 @@ public:
     /// \param answer the callbackprovider for DNS answer events
     explicit UDPServer(asio::io_service& io_service,
                        const asio::ip::address& addr, const uint16_t port,
-                       SimpleCallback* checkin = NULL,
+                       isc::asiolink::SimpleCallback* checkin = NULL,
                        DNSLookup* lookup = NULL,
                        DNSAnswer* answer = NULL);
 
@@ -102,5 +103,6 @@ private:
     boost::shared_ptr<Data> data_;
 };
 
-}      // namespace asiolink
+} // namespace asiodns
+} // namespace isc
 #endif // __UDP_SERVER_H

+ 0 - 12
src/lib/asiolink/Makefile.am

@@ -13,33 +13,21 @@ CLEANFILES = *.gcno *.gcda
 # which would make the build fail with -Werror (our default setting).
 lib_LTLIBRARIES = libasiolink.la
 libasiolink_la_SOURCES  = asiolink.h
-libasiolink_la_SOURCES += asiolink_utilities.h
-libasiolink_la_SOURCES += asiodef.cc asiodef.h
-libasiolink_la_SOURCES += dns_answer.h
-libasiolink_la_SOURCES += dns_lookup.h
-libasiolink_la_SOURCES += dns_server.h
-libasiolink_la_SOURCES += dns_service.cc dns_service.h
 libasiolink_la_SOURCES += dummy_io_cb.h
 libasiolink_la_SOURCES += interval_timer.cc interval_timer.h
 libasiolink_la_SOURCES += io_address.cc io_address.h
 libasiolink_la_SOURCES += io_asio_socket.h
 libasiolink_la_SOURCES += io_endpoint.cc io_endpoint.h
 libasiolink_la_SOURCES += io_error.h
-libasiolink_la_SOURCES += io_fetch.cc io_fetch.h
 libasiolink_la_SOURCES += io_message.h
-libasiolink_la_SOURCES += qid_gen.cc qid_gen.h
 libasiolink_la_SOURCES += io_service.h io_service.cc
 libasiolink_la_SOURCES += io_socket.h io_socket.cc
 libasiolink_la_SOURCES += simple_callback.h
 libasiolink_la_SOURCES += tcp_endpoint.h
-libasiolink_la_SOURCES += tcp_server.cc tcp_server.h
 libasiolink_la_SOURCES += tcp_socket.h
 libasiolink_la_SOURCES += udp_endpoint.h
-libasiolink_la_SOURCES += udp_server.cc udp_server.h
 libasiolink_la_SOURCES += udp_socket.h
 
-EXTRA_DIST = asiodef.msg
-
 # Note: the ordering matters: -Wno-... must follow -Wextra (defined in
 # B10_CXXFLAGS)
 libasiolink_la_CXXFLAGS = $(AM_CXXFLAGS)

+ 0 - 160
src/lib/asiolink/README

@@ -16,167 +16,7 @@ including:
     them in only one place allows us to relax strictness here, while
     leaving it in place elsewhere.
 
-Currently, the asiolink library only supports DNS servers (i.e., b10-auth
-and b10-resolver).  The plan is to make it more generic and allow it to
-support other modules as well.
-
 Some of the classes defined here--for example, IOSocket, IOEndpoint,
 and IOAddress--are to be used by BIND 10 modules as wrappers around
 ASIO-specific classes.
 
-Other classes implement the DNS protocol on behalf of BIND 10 modules.
-
-These DNS server and client routines are written using the "stackless
-coroutine" pattern invented by Chris Kohlhoff and described at
-http://blog.think-async.com/2010/03/potted-guide-to-stackless-coroutines.html.
-This is intended to simplify development a bit, since it allows the
-routines to be written in a straightfowrard step-step-step fashion rather
-than as a complex chain of separate handler functions.
-
-Coroutine objects (i.e., UDPServer, TCPServer and IOFetch) are objects
-with reenterable operator() members.  When an instance of one of these
-classes is called as a function, it resumes at the position where it left
-off.  Thus, a UDPServer can issue an asynchronous I/O call and specify
-itself as the handler object; when the call completes, the UDPServer
-carries on at the same position.  As a result, the code can look as
-if it were using synchronous, not asynchronous, I/O, providing some of
-the benefit of threading but with minimal switching overhead.
-
-So, in simplified form, the behavior of a DNS Server is:
-
-  REENTER:
-    while true:
-      YIELD packet = read_packet
-      FORK
-      if not parent:
-        break
-
-    # This callback informs the caller that a packet has arrived, and
-    # gives it a chance to update configuration, etc
-    SimpleCallback(packet)
-    YIELD answer = DNSLookup(packet, this)
-    response = DNSAnswer(answer)
-    YIELD send(response)
-
-At each "YIELD" point, the coroutine initiates an asynchronous operation,
-then pauses and turns over control to some other task on the ASIO service
-queue.  When the operation completes, the coroutine resumes.
-
-DNSLookup, DNSAnswer and SimpleCallback define callback methods
-used by a DNS Server to communicate with the module that called it.
-They are abstract-only classes whose concrete implementations
-are supplied by the calling module.
-
-The DNSLookup callback always runs asynchronously.  Concrete
-implementations must be sure to call the server's "resume" method when
-it is finished.
-
-In an authoritative server, the DNSLookup implementation would examine
-the query, look up the answer, then call "resume".  (See the diagram
-in doc/auth_process.jpg.)
-
-In a recursive server, the DNSLookup impelemtation would initiate a
-DNSQuery, which in turn would be responsible for calling the server's
-"resume" method.  (See the diagram in doc/recursive_process.jpg.)
-
-A DNSQuery object is intended to handle resolution of a query over
-the network when the local authoritative data sources or cache are not
-sufficient.  The plan is that it will make use of subsidiary DNSFetch
-calls to get data from particular authoritative servers, and when it has
-gotten a complete answer, it calls "resume".
-
-In current form, however, DNSQuery is much simpler; it forwards queries
-to a single upstream resolver and passes the answers back to the client.
-It is constructed with the address of the forward server.  Queries are
-initiated with the question to ask the forward server, a buffer into
-which to write the answer, and a pointer to the coroutine to be resumed
-when the answer has arrived.  In simplified form, the DNSQuery routine is:
-
-  REENTER:
-    render the question into a wire-format query packet
-    YIELD send(query)
-    YIELD response = read_packet
-    server->resume
-
-Currently, DNSQuery is only implemented for UDP queries.  In future work
-it will be necessary to write code to fall back to TCP when circumstances
-require it.
-
-
-Upstream Fetches
-================
-Upstream fetches (queries by the resolver on behalf of a client) are made
-using a slightly-modified version of the pattern described above.
-
-Sockets
--------
-First, it will be useful to understand the class hierarchy used in the
-fetch logic:
-
-        IOSocket
-           |
-      IOAsioSocket
-           |
-     +-----+-----+                
-     |           |
-UDPSocket    TCPSocket
-
-IOSocket is a wrapper class for a socket and is used by the authoritative
-server code.  It is an abstract base class, providing little more that the ability to hold the socket and to return the protocol in use.
-
-Built on this is IOAsioSocket, which adds the open, close, asyncSend and
-asyncReceive methods.  This is a template class, which takes as template
-argument the class of the object that will be used as the callback when the
-asynchronous operation completes. This object can be of any type, but must
-include an operator() method with the signature:
-
-   operator()(asio::error_code ec, size_t length)
-
-... the two arguments being the status of the completed I/O operation and
-the number of bytes transferred. (In the case of the open method, the second
-argument will be zero.)
-
-Finally, the TCPSocket and UDPSocket classes provide the body of the
-asynchronous operations.
-
-Fetch Sequence
---------------
-The fetch is implemented by the IOFetch class, which takes as argument the
-protocol to use.  The sequence is:
-
-  REENTER:
-    render the question into a wire-format query packet
-    open()                           // Open socket and optionally connect
-    if (! synchronous) {
-        YIELD;
-    }
-    YIELD asyncSend(query)           // Send query 
-    do {
-        YIELD asyncReceive(response) // Read response
-    } while (! complete(response))
-    close()                          // Drop connection and close socket
-    server->resume
-
-The open() method opens a socket for use.  On TCP, it also makes a
-connection to the remote end.  So under UDP the operation will complete
-immediately, but under TCP it could take a long time.  One solution would be
-for the open operation to post an event to the I/O queue; then both cases
-could be regarded as being equivalent, with the completion being signalled
-by the posting of the completion event.  However UDP is the most common case
-and that would involve extra overhead.  So the open() returns a status
-indicating whether the operation completed asynchronously.  If it did, the
-code yields back to the coroutine; if not the yield is bypassed.
-
-The asynchronous send is straightforward, invoking the underlying ASIO
-function.  (Note that the address/port is supplied to both the open() and
-asyncSend() methods - it is used by the TCPSocket in open() and by the
-UDPSocket in asyncSend().)
-
-The asyncReceive() method issues an asynchronous read and waits for completion.
-The fetch object keeps track of the amount of data received so far and when
-the receive completes it calls a method on the socket to determine if the
-entire message has been received.  (This will always be the case for UDP.  On
-TCP though, the message is preceded by a count field as several reads may be
-required to read all the data.)  The fetch loops until all the data is read.
-
-Finally, the socket is closed and the server called to resume operation.

+ 0 - 21
src/lib/asiolink/asiodef.h

@@ -1,21 +0,0 @@
-// File created from asiodef.msg on Mon Feb 28 17:15:30 2011
-
-#ifndef __ASIODEF_H
-#define __ASIODEF_H
-
-#include <log/message_types.h>
-
-namespace asiolink {
-
-extern const isc::log::MessageID ASIO_FETCHCOMP;
-extern const isc::log::MessageID ASIO_FETCHSTOP;
-extern const isc::log::MessageID ASIO_OPENSOCK;
-extern const isc::log::MessageID ASIO_RECVSOCK;
-extern const isc::log::MessageID ASIO_RECVTMO;
-extern const isc::log::MessageID ASIO_SENDSOCK;
-extern const isc::log::MessageID ASIO_UNKORIGIN;
-extern const isc::log::MessageID ASIO_UNKRESULT;
-
-} // namespace asiolink
-
-#endif // __ASIODEF_H

+ 0 - 9
src/lib/asiolink/asiolink.h

@@ -20,10 +20,6 @@
 // See the description of the namespace below.
 
 #include <asiolink/io_service.h>
-#include <asiolink/dns_service.h>
-#include <asiolink/dns_server.h>
-#include <asiolink/dns_lookup.h>
-#include <asiolink/dns_answer.h>
 #include <asiolink/simple_callback.h>
 #include <asiolink/interval_timer.h>
 
@@ -62,11 +58,6 @@
 /// this module.  The resulting interfaces are thus straightforward mapping
 /// to the ASIO counterparts.
 ///
-/// Notes to developers:
-/// Currently the wrapper interface is fairly specific to use by a
-/// DNS server, i.e., b10-auth or b10-resolver.  But the plan is to
-/// generalize it and have other modules use it as well.
-///
 /// One obvious drawback of this approach is performance overhead
 /// due to the additional layer.  We should eventually evaluate the cost
 /// of the wrapper abstraction in benchmark tests. Another drawback is

+ 2 - 0
src/lib/asiolink/dummy_io_cb.h

@@ -20,6 +20,7 @@
 #include <asio/error.hpp>
 #include <asio/error_code.hpp>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief Asynchronous I/O Completion Callback
@@ -55,5 +56,6 @@ public:
 };
 
 } // namespace asiolink
+} // namespace isc
 
 #endif // __DUMMY_IO_CB_H

+ 3 - 1
src/lib/asiolink/interval_timer.cc

@@ -26,6 +26,7 @@
 #include <asiolink/interval_timer.h>
 #include <asiolink/io_service.h>
 
+namespace isc {
 namespace asiolink {
 
 class IntervalTimerImpl {
@@ -133,4 +134,5 @@ IntervalTimer::getInterval() const {
     return (impl_->getInterval());
 }
 
-}
+} // namespace asiolink
+} // namespace isc

+ 3 - 1
src/lib/asiolink/interval_timer.h

@@ -19,6 +19,7 @@
 
 #include <asiolink/io_service.h>
 
+namespace isc {
 namespace asiolink {
 
 struct IntervalTimerImpl;
@@ -129,5 +130,6 @@ private:
     IntervalTimerImpl* impl_;
 };
 
-}      // namespace asiolink
+} // namespace asiolink
+} // namespace isc
 #endif // __ASIOLINK_INTERVAL_TIMER_H

+ 3 - 1
src/lib/asiolink/io_address.cc

@@ -31,6 +31,7 @@ using asio::ip::tcp;
 
 using namespace std;
 
+namespace isc {
 namespace asiolink {
 
 // XXX: we cannot simply construct the address in the initialization list,
@@ -62,4 +63,5 @@ IOAddress::getFamily() const {
     }
 }
 
-}
+} // namespace asiolink
+} // namespace isc

+ 3 - 1
src/lib/asiolink/io_address.h

@@ -26,6 +26,7 @@
 
 #include <exceptions/exceptions.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c IOAddress class represents an IP addresses (version
@@ -119,5 +120,6 @@ private:
     asio::ip::address asio_address_;
 };
 
-}      // asiolink
+} // namespace asiolink
+} // namespace isc
 #endif // __IO_ADDRESS_H

+ 5 - 4
src/lib/asiolink/io_asio_socket.h

@@ -26,12 +26,12 @@
 #include <exceptions/exceptions.h>
 #include <coroutine.h>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
 
 #include <asiolink/io_error.h>
 #include <asiolink/io_socket.h>
 
-
+namespace isc {
 namespace asiolink {
 
 /// \brief Socket not open
@@ -270,7 +270,7 @@ public:
     virtual bool processReceivedData(const void* staging, size_t length,
                                      size_t& cumulative, size_t& offset,
                                      size_t& expected,
-                                     isc::dns::OutputBufferPtr& outbuff) = 0;
+                                     isc::util::OutputBufferPtr& outbuff) = 0;
 
     /// \brief Cancel I/O On AsioSocket
     virtual void cancel() = 0;
@@ -372,7 +372,7 @@ public:
     virtual bool receiveComplete(const void* staging, size_t length,
                                  size_t& cumulative, size_t& offset,
                                  size_t& expected,
-                                 isc::dns::OutputBufferPtr& outbuff)
+                                 isc::util::OutputBufferPtr& outbuff)
     {
         return (true);
     }
@@ -395,5 +395,6 @@ private:
 };
 
 } // namespace asiolink
+} // namespace isc
 
 #endif // __IO_ASIO_SOCKET_H

+ 3 - 1
src/lib/asiolink/io_endpoint.cc

@@ -28,6 +28,7 @@
 
 using namespace std;
 
+namespace isc {
 namespace asiolink {
 
 const IOEndpoint*
@@ -57,4 +58,5 @@ IOEndpoint::operator!=(const IOEndpoint& other) const {
     return (!operator==(other));
 }
 
-}
+} // namespace asiolink
+} // namespace isc

+ 3 - 1
src/lib/asiolink/io_endpoint.h

@@ -26,6 +26,7 @@
 #include <exceptions/exceptions.h>
 #include <asiolink/io_address.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c IOEndpoint class is an abstract base class to represent
@@ -117,5 +118,6 @@ public:
                                     const unsigned short port);
 };
 
-}      // asiolink
+} // namespace asiolink
+} // namespace isc
 #endif // __IO_ENDPOINT_H

+ 3 - 1
src/lib/asiolink/io_error.h

@@ -18,6 +18,7 @@
 
 #include <exceptions/exceptions.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief An exception that is thrown if an error occurs within the IO
@@ -30,6 +31,7 @@ public:
 };
 
 
-}      // asiolink
+} // namespace asiolink
+} // namespace isc
 
 #endif // __IO_ERROR_H

+ 3 - 1
src/lib/asiolink/io_message.h

@@ -28,6 +28,7 @@
 #include <asiolink/io_endpoint.h>
 #include <asiolink/io_socket.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c IOMessage class encapsulates an incoming message received
@@ -96,5 +97,6 @@ private:
 };
 
 
-}      // asiolink
+} // namespace asiolink
+} // namespace isc
 #endif // __IO_MESSAGE_H

+ 3 - 1
src/lib/asiolink/io_service.cc

@@ -21,6 +21,7 @@
 #include <asio.hpp>
 #include <asiolink/io_service.h>
 
+namespace isc {
 namespace asiolink {
 
 class IOServiceImpl {
@@ -95,4 +96,5 @@ IOService::get_io_service() {
     return (io_impl_->get_io_service());
 }
 
-} // namepsace asiolink
+} // namespace asiolink
+} // namespace isc

+ 3 - 1
src/lib/asiolink/io_service.h

@@ -19,6 +19,7 @@ namespace asio {
     class io_service;
 }
 
+namespace isc {
 namespace asiolink {
 
 struct IOServiceImpl;
@@ -73,5 +74,6 @@ private:
     IOServiceImpl* io_impl_;
 };
 
-}      // namespace asiolink
+} // namespace asiolink
+} // namespace isc
 #endif // __ASIOLINK_IO_SERVICE_H

+ 3 - 3
src/lib/asiolink/io_socket.cc

@@ -16,8 +16,7 @@
 
 #include <asio.hpp>
 
-using namespace asio;
-
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c DummySocket class is a concrete derived class of
@@ -62,4 +61,5 @@ IOSocket::getDummyTCPSocket() {
     return (socket);
 }
 
-}
+} // namespace asiolink
+} // namespace isc

+ 2 - 0
src/lib/asiolink/io_socket.h

@@ -25,6 +25,7 @@
 
 #include <exceptions/exceptions.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c IOSocket class is an abstract base class to represent
@@ -120,5 +121,6 @@ public:
 };
 
 } // namespace asiolink
+} // namespace isc
 
 #endif // __IO_SOCKET_H

+ 3 - 1
src/lib/asiolink/simple_callback.h

@@ -17,6 +17,7 @@
 
 #include <asiolink/io_message.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c SimpleCallback class is an abstract base class for a
@@ -67,5 +68,6 @@ private:
     SimpleCallback* self_;
 };
 
-}      // namespace asiolink
+} // namespace asiolink
+} // namespace isc
 #endif // __ASIOLINK_SIMPLE_CALLBACK_H

+ 3 - 1
src/lib/asiolink/tcp_endpoint.h

@@ -21,6 +21,7 @@
 
 #include <asiolink/io_endpoint.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c TCPEndpoint class is a concrete derived class of
@@ -109,5 +110,6 @@ private:
     asio::ip::tcp::endpoint& asio_endpoint_;
 };
 
-}      // namespace asiolink
+} // namespace asiolink
+} // namespace isc
 #endif // __TCP_ENDPOINT_H

+ 9 - 7
src/lib/asiolink/tcp_socket.h

@@ -33,14 +33,15 @@
 
 #include <config.h>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
+#include <util/io_utilities.h>
 
-#include <asiolink/asiolink_utilities.h>
 #include <asiolink/io_asio_socket.h>
 #include <asiolink/io_endpoint.h>
 #include <asiolink/io_service.h>
 #include <asiolink/tcp_endpoint.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief Buffer Too Large
@@ -155,7 +156,7 @@ public:
     virtual bool processReceivedData(const void* staging, size_t length,
                                      size_t& cumulative, size_t& offset,
                                      size_t& expected,
-                                     isc::dns::OutputBufferPtr& outbuff);
+                                     isc::util::OutputBufferPtr& outbuff);
 
     /// \brief Cancel I/O On Socket
     virtual void cancel();
@@ -185,7 +186,7 @@ private:
     // The option of sending the data in two operations, the count followed by
     // the data was discounted as that would lead to two callbacks which would
     // cause problems with the stackless coroutine code.
-    isc::dns::OutputBufferPtr   send_buffer_;   ///< Send buffer
+    isc::util::OutputBufferPtr   send_buffer_;   ///< Send buffer
 };
 
 // Constructor - caller manages socket
@@ -268,7 +269,7 @@ TCPSocket<C>::asyncSend(const void* data, size_t length,
             uint16_t count = boost::numeric_cast<uint16_t>(length);
 
             // Copy data into a buffer preceded by the count field.
-            send_buffer_.reset(new isc::dns::OutputBuffer(length + 2));
+            send_buffer_.reset(new isc::util::OutputBuffer(length + 2));
             send_buffer_->writeUint16(count);
             send_buffer_->writeData(data, length);
 
@@ -333,7 +334,7 @@ template <typename C> bool
 TCPSocket<C>::processReceivedData(const void* staging, size_t length,
                                   size_t& cumulative, size_t& offset,
                                   size_t& expected,
-                                  isc::dns::OutputBufferPtr& outbuff)
+                                  isc::util::OutputBufferPtr& outbuff)
 {
     // Point to the data in the staging buffer and note how much there is.
     const uint8_t* data = static_cast<const uint8_t*>(staging);
@@ -358,7 +359,7 @@ TCPSocket<C>::processReceivedData(const void* staging, size_t length,
         }
 
         // Have enough data to interpret the packet count, so do so now.
-        expected = readUint16(data);
+        expected = isc::util::readUint16(data);
 
         // We have two bytes less of data to process.  Point to the start of the
         // data and adjust the packet size.  Note that at this point,
@@ -412,5 +413,6 @@ TCPSocket<C>::close() {
 }
 
 } // namespace asiolink
+} // namespace isc
 
 #endif // __TCP_SOCKET_H

+ 2 - 5
src/lib/asiolink/tests/Makefile.am

@@ -1,6 +1,7 @@
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/dns -I$(top_srcdir)/src/bin
+AM_CPPFLAGS += -I$(top_builddir)/src/lib/util -I$(top_srcdir)/src/util
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
 AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
 
@@ -18,19 +19,14 @@ TESTS += run_unittests
 run_unittests_SOURCES  = run_unittests.cc
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.h
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
-run_unittests_SOURCES += asiolink_utilities_unittest.cc
 run_unittests_SOURCES += io_address_unittest.cc
 run_unittests_SOURCES += io_endpoint_unittest.cc
-run_unittests_SOURCES += io_fetch_unittest.cc
 run_unittests_SOURCES += io_socket_unittest.cc
-run_unittests_SOURCES += io_service_unittest.cc
 run_unittests_SOURCES += interval_timer_unittest.cc
 run_unittests_SOURCES += tcp_endpoint_unittest.cc
 run_unittests_SOURCES += tcp_socket_unittest.cc
 run_unittests_SOURCES += udp_endpoint_unittest.cc
 run_unittests_SOURCES += udp_socket_unittest.cc
-run_unittests_SOURCES += dns_server_unittest.cc
-run_unittests_SOURCES += qid_gen_unittest.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 
@@ -38,6 +34,7 @@ run_unittests_LDADD  = $(GTEST_LDADD)
 run_unittests_LDADD += $(SQLITE_LIBS)
 run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
 run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 

+ 1 - 1
src/lib/asiolink/tests/interval_timer_unittest.cc

@@ -26,7 +26,7 @@ const boost::posix_time::time_duration TIMER_MARGIN_MSEC =
     boost::posix_time::milliseconds(50);
 }
 
-using namespace asiolink;
+using namespace isc::asiolink;
 
 // This fixture is for testing IntervalTimer. Some callback functors are 
 // registered as callback function of the timer to test if they are called

+ 1 - 1
src/lib/asiolink/tests/io_address_unittest.cc

@@ -18,7 +18,7 @@
 #include <asiolink/io_error.h>
 #include <asiolink/io_address.h>
 
-using namespace asiolink;
+using namespace isc::asiolink;
 
 TEST(IOAddressTest, fromText) {
     IOAddress io_address_v4("192.0.2.1");

+ 1 - 1
src/lib/asiolink/tests/io_endpoint_unittest.cc

@@ -18,7 +18,7 @@
 #include <asiolink/io_endpoint.h>
 #include <asiolink/io_error.h>
 
-using namespace asiolink;
+using namespace isc::asiolink;
 
 TEST(IOEndpointTest, createUDPv4) {
     const IOEndpoint* ep;

+ 1 - 1
src/lib/asiolink/tests/io_socket_unittest.cc

@@ -20,7 +20,7 @@
 #include <asio.hpp>
 #include <asiolink/io_socket.h>
 
-using namespace asiolink;
+using namespace isc::asiolink;
 
 TEST(IOSocketTest, dummySockets) {
     EXPECT_EQ(IPPROTO_UDP, IOSocket::getDummyUDPSocket().getProtocol());

+ 1 - 1
src/lib/asiolink/tests/tcp_endpoint_unittest.cc

@@ -22,7 +22,7 @@
 #include <asiolink/io_address.h>
 #include <asiolink/tcp_endpoint.h>
 
-using namespace asiolink;
+using namespace isc::asiolink;
 using namespace std;
 
 // This test checks that the endpoint can manage its own internal

+ 4 - 4
src/lib/asiolink/tests/tcp_socket_unittest.cc

@@ -35,19 +35,19 @@
 #include <boost/bind.hpp>
 #include <boost/shared_ptr.hpp>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
+#include <util/io_utilities.h>
 
 #include <asio.hpp>
 
-#include <asiolink/asiolink_utilities.h>
 #include <asiolink/io_service.h>
 #include <asiolink/tcp_endpoint.h>
 #include <asiolink/tcp_socket.h>
 
 using namespace asio;
 using namespace asio::ip;
-using namespace asiolink;
-using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::asiolink;
 using namespace std;
 
 namespace {

+ 1 - 1
src/lib/asiolink/tests/udp_endpoint_unittest.cc

@@ -22,7 +22,7 @@
 #include <asiolink/io_address.h>
 #include <asiolink/udp_endpoint.h>
 
-using namespace asiolink;
+using namespace isc::asiolink;
 using namespace std;
 
 // This test checks that the endpoint can manage its own internal

+ 4 - 4
src/lib/asiolink/tests/udp_socket_unittest.cc

@@ -35,18 +35,18 @@
 #include <boost/bind.hpp>
 #include <boost/shared_ptr.hpp>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
+#include <util/io_utilities.h>
 
 #include <asio.hpp>
 
-#include <asiolink/asiolink_utilities.h>
 #include <asiolink/io_service.h>
 #include <asiolink/udp_endpoint.h>
 #include <asiolink/udp_socket.h>
 
 using namespace asio;
-using namespace asiolink;
-using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::asiolink;
 using namespace std;
 
 namespace {

+ 3 - 1
src/lib/asiolink/udp_endpoint.h

@@ -21,6 +21,7 @@
 
 #include <asiolink/io_endpoint.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c UDPEndpoint class is a concrete derived class of
@@ -109,5 +110,6 @@ private:
     asio::ip::udp::endpoint& asio_endpoint_;
 };
 
-}      // namespace asiolink
+} // namespace asiolink
+} // namespace isc
 #endif // __UDP_ENDPOINT_H

+ 4 - 2
src/lib/asiolink/udp_socket.h

@@ -33,6 +33,7 @@
 #include <asiolink/io_service.h>
 #include <asiolink/udp_endpoint.h>
 
+namespace isc {
 namespace asiolink {
 
 /// \brief The \c UDPSocket class is a concrete derived class of \c IOAsioSocket
@@ -141,7 +142,7 @@ public:
     virtual bool processReceivedData(const void* staging, size_t length,
                                      size_t& cumulative, size_t& offset,
                                      size_t& expected,
-                                     isc::dns::OutputBufferPtr& outbuff);
+                                     isc::util::OutputBufferPtr& outbuff);
 
     /// \brief Cancel I/O On Socket
     virtual void cancel();
@@ -283,7 +284,7 @@ template <typename C> bool
 UDPSocket<C>::processReceivedData(const void* staging, size_t length,
                                   size_t& cumulative, size_t& offset,
                                   size_t& expected,
-                                  isc::dns::OutputBufferPtr& outbuff)
+                                  isc::util::OutputBufferPtr& outbuff)
 {
     // Set return values to what we should expect.
     cumulative = length;
@@ -318,5 +319,6 @@ UDPSocket<C>::close() {
 }
 
 } // namespace asiolink
+} // namespace isc
 
 #endif // __UDP_SOCKET_H

+ 2 - 1
src/lib/bench/benchmark_util.cc

@@ -19,7 +19,7 @@
 
 #include <exceptions/exceptions.h>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
 #include <dns/exceptions.h>
 #include <dns/name.h>
 #include <dns/message.h>
@@ -35,6 +35,7 @@
 using namespace std;
 using namespace isc;
 using namespace isc::dns;
+using namespace isc::util;
 
 namespace isc {
 namespace bench {

+ 1 - 0
src/lib/bench/tests/Makefile.am

@@ -16,6 +16,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
 run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
 run_unittests_LDADD += $(top_builddir)/src/lib/bench/libbench.la
 run_unittests_LDADD += $(GTEST_LDADD)
 endif

+ 2 - 1
src/lib/bench/tests/loadquery_unittest.cc

@@ -17,7 +17,7 @@
 #include <vector>
 #include <sstream>
 
-#include <dns/buffer.h>
+#include <util/buffer.h>
 #include <dns/message.h>
 #include <dns/name.h>
 #include <dns/opcode.h>
@@ -32,6 +32,7 @@
 using namespace std;
 using namespace isc::bench;
 using namespace isc::dns;
+using namespace isc::util;
 
 namespace {
 typedef pair<string, string> QueryParam;

+ 1 - 0
src/lib/cache/Makefile.am

@@ -2,6 +2,7 @@ SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES) $(MULTITHREADING_FLAG)
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/nsas -I$(top_builddir)/src/lib/nsas
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cache -I$(top_builddir)/src/lib/cache

+ 2 - 2
src/lib/cache/message_cache.h

@@ -20,7 +20,7 @@
 #include <dns/message.h>
 #include "message_entry.h"
 #include <nsas/hash_table.h>
-#include <nsas/lru_list.h>
+#include <util/lru_list.h>
 #include "rrset_cache.h"
 
 namespace isc {
@@ -92,7 +92,7 @@ protected:
     RRsetCachePtr rrset_cache_;
     RRsetCachePtr negative_soa_cache_;
     isc::nsas::HashTable<MessageEntry> message_table_;
-    isc::nsas::LruList<MessageEntry> message_lru_;
+    isc::util::LruList<MessageEntry> message_lru_;
 };
 
 typedef boost::shared_ptr<MessageCache> MessageCachePtr;

+ 3 - 2
src/lib/cache/rrset_cache.h

@@ -17,7 +17,8 @@
 
 #include <cache/rrset_entry.h>
 #include <nsas/hash_table.h>
-#include <nsas/lru_list.h>
+
+#include <util/lru_list.h>
 
 using namespace isc::nsas;
 
@@ -98,7 +99,7 @@ public:
 protected:
     uint16_t class_; // The class of the rrset cache.
     isc::nsas::HashTable<RRsetEntry> rrset_table_;
-    isc::nsas::LruList<RRsetEntry> rrset_lru_;
+    isc::util::LruList<RRsetEntry> rrset_lru_;
 };
 
 typedef boost::shared_ptr<RRsetCache> RRsetCachePtr;

+ 2 - 0
src/lib/cache/tests/Makefile.am

@@ -2,6 +2,7 @@ SUBDIRS = .
 
 AM_CPPFLAGS  = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES) $(MULTITHREADING_FLAG)
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cache -I$(top_builddir)/src/lib/cache
 AM_CPPFLAGS += -DTEST_DATA_SRCDIR=\"$(srcdir)/testdata\"
@@ -54,6 +55,7 @@ endif
 run_unittests_LDADD += $(top_builddir)/src/lib/cache/libcache.la
 run_unittests_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
 run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif

+ 0 - 0
src/lib/cache/tests/cache_test_messagefromfile.h


Some files were not shown because too many files changed in this diff