BIND 10 trac2225_xfrout, updated. 514cd120aa0ac15c4e2118255d6176e90add211b [2225_xfrout] s/dump_statistics/get_statistics/

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Jan 18 06:34:33 UTC 2013


The branch, trac2225_xfrout has been updated
  discards  01c389aec693882f1b8233500cba1f7f65517fd0 (commit)
  discards  c3df8d055117b28da4fabc20e15a14d4def90c00 (commit)
  discards  46478bcb06ce13b7e2c1b342e6b7e63764c1e225 (commit)
  discards  89f99b959381e5d976199785cd4432b7aa82757d (commit)
  discards  da239e501ca0db170007d4d3462a96da2ccc3a99 (commit)
  discards  f27d218ea32e57bc08c4b1db77e0a7a05862345c (commit)
  discards  f516250903358f645c37f6ab0d313e3571c52d66 (commit)
  discards  c087ea5ba98e927b5c523a0b02f4b3858c602e8d (commit)
  discards  64416e1d8bdd8cdf9c0535098b78eb96ce03fe26 (commit)
  discards  df8958f661691900968a43d344e0bd548703b9d5 (commit)
  discards  5360d3c534c58a31223cba2a69265f93976f59c0 (commit)
  discards  143b9517ac82f0682cc6b39a58bdd292e0c2ce8e (commit)
  discards  a3b6ba5f5ad3c2455635a8aff1ba475e3ce56337 (commit)
  discards  d929e11039128ce6f1e5b4798de81d3c967996d1 (commit)
  discards  7c19613f47670a123ba3bb08b0f64b47086cec84 (commit)
  discards  0eba3b5dfc1d263ad55e90a07c6b12c94fc09155 (commit)
  discards  c1473d95e39b86ebfa57eb47f7da8e96ebe55203 (commit)
  discards  37391946e9c47b849e5f6e38345aa8298c963f87 (commit)
  discards  b25e2ffb1e511dacc6703935e819ed3ae922e293 (commit)
  discards  77171e9cda20fab175b23359c7412c9df26d5107 (commit)
  discards  6535b61e9ddc6325ccd7bbfd56e1c094a0f54335 (commit)
  discards  216f61003202faf7381a627a1138d891a6d1e28a (commit)
  discards  cc098e6d33b092c46194dcb40179d5688655964f (commit)
  discards  09c9166b4a26afa42b6b51070d4a05b2fea6e87e (commit)
       via  514cd120aa0ac15c4e2118255d6176e90add211b (commit)
       via  b541596415b3a79c9ec5e7e2c32b2acb1a9be28c (commit)
       via  9ca7f37f2fc5464446a38a7ebc9256b71fb8944f (commit)
       via  17ace8323f227b86f9b3c376ffb0cdbd86075710 (commit)
       via  ca8b0515f7c638d9697b608965f18b5d1c5b5fa0 (commit)
       via  da7349e2f4f79a781365a4198f9425865c729d1a (commit)
       via  cb9e424c61fc7b42038fd2c5d49a22b3ca581a01 (commit)
       via  52ec102b16ae6969c4aa405ec6617765336d69f1 (commit)
       via  4a1c77d95ad8c51b4a47a379b273809e8e8e2621 (commit)
       via  b2a12049d34b061dff5027e9a78e6a00d751c773 (commit)
       via  12ed470e0c12f4879c5398a52c7364e2fe4ce01c (commit)
       via  657c926eaa761b234d648aa4eac99e7f99a4f1e7 (commit)
       via  8a0613d11028d6eba72e08dd7d44aa08bcc682c2 (commit)
       via  9de118b1aadb88902755c18ff7b584ceb84ac545 (commit)
       via  32c40f54a0b1e833d8b03cfb43da064d39a7591c (commit)
       via  1112a612b9df64344416a10730df3ed843b3c5de (commit)
       via  58ce07ad5ba3d527384ca88a5139f5a6faee004a (commit)
       via  7025d308cd3f2a68cc370835ba059b3a43051fc0 (commit)
       via  8770765db4becde5c0347a055dd7db7bfd6120c0 (commit)
       via  f4c26bfac4daf9520d189259d0380c5fa814e0ae (commit)
       via  1b87787e20f6333959235623754fbebae0445e43 (commit)
       via  83c439eff853360e633b6e539c6d38ff9c49e971 (commit)
       via  fa4cd1a315d67c2f48f28bc487035bbe44f291d9 (commit)
       via  34900ee9027ff21655fbaca820696f10a69b2f83 (commit)
       via  7c1af32c1336e61c9546f8cd564ff9c660ccf203 (commit)
       via  a165423b537cf5771ea810dba64215a724050a5a (commit)
       via  bc8dde5aaed1b519e26a20b383cddec07c01369d (commit)
       via  2a337c756ad1064af1cbcaa8cd2c79be65f0b4d5 (commit)
       via  28a20a3ee754d03ea90f13f76fa8e6d44c696b69 (commit)
       via  2ad5c3c52b9106f68a6fb24a2ebfc85067877a04 (commit)
       via  be258adbecd48f1d46e47566f54843db1b579b9c (commit)
       via  02a31879b8d8db032883d6e28d57c2369f2299cf (commit)
       via  df03141495a568971ff26d78a229beaa5b373e19 (commit)
       via  cd917b3660e1d944d749fb2fb19ce9dfb622c39c (commit)
       via  cc0c7a0a7b9b4abdb94b7c5a2007334b914218f8 (commit)
       via  e12dee22bbc97e49c7e5641cf50e39f64e5cbed2 (commit)
       via  927c2a94869d76fdbb30018861ba235ddf9389f2 (commit)
       via  6443e079d1d0dd3b0de766196a2f9b711bd4f4f5 (commit)
       via  78f11bb1db706b793f2b45d94da3c613c2f8ca9e (commit)
       via  08d9023ba335f084034ec31cf7e304964b267acb (commit)
       via  dc7e03f9cca07ef79b5741f4353f570f383dbb9b (commit)
       via  bc768d296fbd5b86b9d100672792605c79c81739 (commit)
       via  a9f24702174e022332b528b8d39a21c203b67d3e (commit)
       via  ef7776ea48e1ddbfb3b727836722cbfc8b65f4fa (commit)
       via  f098bc21fd0c528fdd55bdbd8f99f6fec36c9222 (commit)
       via  607d55c17a1d1becedf6e0fb81673627cab763f8 (commit)
       via  903087f3c9e778e762483cf11992e4f5ddc9b7d1 (commit)
       via  65bbcd0970063c0923f597ee4413ccbcc969ba58 (commit)
       via  e8ed9fd77960f2e3c4cfc5948d356b47524d441c (commit)
       via  31b16f3568b95073fc15b68e435215572f25c5b8 (commit)
       via  6fe2c80c65634db3c5b9ef7fab2e2f48a507fc94 (commit)
       via  87ff7feca9801dc6c78a5553c090819a66afe918 (commit)
       via  48974a8f8351415321dcabf039296e9e7854fbe1 (commit)
       via  652859d50201a5fd7d7ec3bc4266ead82fc86c4b (commit)
       via  aa70659de52c486695a6fc822b673adf51a2abcf (commit)
       via  c9e1f35632323f09a1e61f96f88df384e337f885 (commit)
       via  ad322965f290c5d594e084eb57f9bf16eff87717 (commit)
       via  ad6e16d25942d9bb308fcc1cf4ec839769956981 (commit)
       via  2b861742dc6b8461984a1c1c0437b46a313f672b (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (01c389aec693882f1b8233500cba1f7f65517fd0)
            \
             N -- N -- N (514cd120aa0ac15c4e2118255d6176e90add211b)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

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

- Log -----------------------------------------------------------------
commit 514cd120aa0ac15c4e2118255d6176e90add211b
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jan 18 15:31:29 2013 +0900

    [2225_xfrout] s/dump_statistics/get_statistics/
    
    Due to the the method name changed

commit b541596415b3a79c9ec5e7e2c32b2acb1a9be28c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jan 18 15:30:35 2013 +0900

    [2225_xfrout] s/clear_counters/clear_all/
    
    Due to the the method name changed

commit 9ca7f37f2fc5464446a38a7ebc9256b71fb8944f
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jan 18 15:22:44 2013 +0900

    [2225_xfrout] s/counter/counters/
    
    Due to the class name changed

commit 17ace8323f227b86f9b3c376ffb0cdbd86075710
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 15:00:13 2012 +0900

    [2225_xfrout] remove assignment of an unused variable

commit ca8b0515f7c638d9697b608965f18b5d1c5b5fa0
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:57:58 2012 +0900

    [2225_xfrout] update creating the counter object and invoking the getter method according to the new interface

commit da7349e2f4f79a781365a4198f9425865c729d1a
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:46:28 2012 +0900

    [2225_xfrout] update creating the counter object and invoking the incrementer method according to the new interface

commit cb9e424c61fc7b42038fd2c5d49a22b3ca581a01
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:42:50 2012 +0900

    [2225_xfrout] remove obsolete creation of a counter object

commit 52ec102b16ae6969c4aa405ec6617765336d69f1
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:40:52 2012 +0900

    [2225_xfrout] fix the wrong counter numbers
    
    It is realized that the removed dummy counter class didn't increase
    the counters properly.

commit 4a1c77d95ad8c51b4a47a379b273809e8e8e2621
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:39:51 2012 +0900

    [2225_xfrout] update the counter object and its getter method according to the new interface
    
    It raises DataNotFoundError instead of zero-count on the new interface when the
    getter method is invoked if its counter hasn't been incremented yet

commit b2a12049d34b061dff5027e9a78e6a00d751c773
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:35:31 2012 +0900

    [2225_xfrout] update the counter object and its getter method since the interface of the counter class was changed

commit 12ed470e0c12f4879c5398a52c7364e2fe4ce01c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:13:04 2012 +0900

    [2225_xfrout] remove an unnecessary dummy counter class

commit 657c926eaa761b234d648aa4eac99e7f99a4f1e7
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:11:22 2012 +0900

    [2225_xfrout] remove an unnecessary keyword argument

commit 8a0613d11028d6eba72e08dd7d44aa08bcc682c2
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Dec 6 14:10:28 2012 +0900

    [2225_xfrout] update the counter object according since the interface of the counter class is changed

commit 9de118b1aadb88902755c18ff7b584ceb84ac545
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 16:15:03 2012 +0900

    [2225_xfrout] changed the test condition for "socket/unixdomain/open" counter of Xfrout
    
    because its counter would probably return 0 or 1 depending on timing

commit 32c40f54a0b1e833d8b03cfb43da064d39a7591c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 15:58:09 2012 +0900

    [2225_xfrout] rename module name(counter) to class name(Counter)

commit 1112a612b9df64344416a10730df3ed843b3c5de
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Sep 12 16:29:21 2012 +0900

    [2252] added checking DataNotFoundError is raised
    
    If un-incremented counter is referred, DataNotFoundError exception
    must be raised.

commit 58ce07ad5ba3d527384ca88a5139f5a6faee004a
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Sep 28 14:19:52 2012 +0900

    [2225] added a new scenario which a slave isn't started

commit 7025d308cd3f2a68cc370835ba059b3a43051fc0
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Sep 28 13:17:00 2012 +0900

    [2225] added same tests as the above tests

commit 8770765db4becde5c0347a055dd7db7bfd6120c0
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Sep 28 11:13:49 2012 +0900

    [2225] removed duplicate tests

commit f4c26bfac4daf9520d189259d0380c5fa814e0ae
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 3 18:58:47 2012 +0900

    [2225] corrected the wrong place to count receive errors of a unix socket
    
    moved the counter from handle_request() to _select_loop() and revised the
    related unit test

commit 1b87787e20f6333959235623754fbebae0445e43
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Aug 31 14:48:52 2012 +0900

    [2225] added descriptions about unixsocket counters into the manpage

commit 83c439eff853360e633b6e539c6d38ff9c49e971
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Aug 31 12:16:17 2012 +0900

    [2225] added checks for statistics unixsocket counters

commit fa4cd1a315d67c2f48f28bc487035bbe44f291d9
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Aug 31 14:31:31 2012 +0900

    [2225] changed according the changes of the counter class
    
     - implemented a dummy counter class inside of the notifyout test and made it
       use it.

commit 34900ee9027ff21655fbaca820696f10a69b2f83
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Aug 31 12:13:10 2012 +0900

    [2225] changed the format of the debug when revised getstats command
    
     - output content of answer to the stats module with the debug message

commit 7c1af32c1336e61c9546f8cd564ff9c660ccf203
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 19 14:31:36 2012 +0900

    [2225] removed obsoleted classes from xfrout.py and xfrout_test.py
    
    XfroutCounter class and TestXfroutCounter are removed

commit a165423b537cf5771ea810dba64215a724050a5a
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Nov 22 18:56:28 2012 +0900

    [2252] fixed the spec file path of Xfrin for unittesting
    
    SPECFILE_LOCATION was located under the B10_FROM_SOURCE tree

commit bc8dde5aaed1b519e26a20b383cddec07c01369d
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 19 14:31:31 2012 +0900

    [2225] add unixdomain socket as statistics spec

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

Summary of changes:
 src/bin/xfrout/tests/xfrout_test.py.in             |   72 ++--
 src/bin/xfrout/xfrout.py.in                        |   40 +-
 src/lib/python/isc/notify/notify_out.py            |    8 +-
 src/lib/python/isc/notify/tests/notify_out_test.py |   26 +-
 src/lib/python/isc/statistics/Makefile.am          |    2 +-
 src/lib/python/isc/statistics/__init__.py          |    2 +-
 .../isc/statistics/{counter.py => counters.py}     |  255 ++++++------
 src/lib/python/isc/statistics/tests/Makefile.am    |    2 +-
 .../python/isc/statistics/tests/counter_test.py    |  301 --------------
 .../python/isc/statistics/tests/counters_test.py   |  416 ++++++++++++++++++++
 10 files changed, 634 insertions(+), 490 deletions(-)
 rename src/lib/python/isc/statistics/{counter.py => counters.py} (57%)
 delete mode 100644 src/lib/python/isc/statistics/tests/counter_test.py
 create mode 100644 src/lib/python/isc/statistics/tests/counters_test.py

-----------------------------------------------------------------------
diff --git a/src/bin/xfrout/tests/xfrout_test.py.in b/src/bin/xfrout/tests/xfrout_test.py.in
index 53a80f9..7506095 100644
--- a/src/bin/xfrout/tests/xfrout_test.py.in
+++ b/src/bin/xfrout/tests/xfrout_test.py.in
@@ -291,7 +291,7 @@ class TestXfroutSessionBase(unittest.TestCase):
         # the XfroutSession object.  We check the condition here.
         self.assertEqual(0, self.xfrsess._server.transfer_counter)
         # clear statistics counters
-        self.xfrsess._counter.clear_counters()
+        self.xfrsess._counters.clear_all()
 
 class TestXfroutSession(TestXfroutSessionBase):
     def test_quota_error(self):
@@ -380,7 +380,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         ]))
         # check the 'xfrrej' counter initially
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.xfrsess._counter.get, 'zones',
+                          self.xfrsess._counters.get, 'zones',
                           TEST_ZONE_NAME_STR, 'xfrrej')
         # Localhost (the default in this test) is accepted
         rcode, msg = self.xfrsess._parse_query_message(self.mdata)
@@ -396,7 +396,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         rcode, msg = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.xfrsess._counter.get(
+        self.assertEqual(self.xfrsess._counters.get(
                 'zones', TEST_ZONE_NAME_STR, 'xfrrej'), 1)
 
         # TSIG signed request
@@ -427,7 +427,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         [rcode, msg] = self.xfrsess._parse_query_message(request_data)
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.xfrsess._counter.get(
+        self.assertEqual(self.xfrsess._counters.get(
                 'zones', TEST_ZONE_NAME_STR, 'xfrrej'), 2)
 
         # ACL using TSIG: no TSIG; should be rejected
@@ -437,7 +437,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.xfrsess._counter.get(
+        self.assertEqual(self.xfrsess._counters.get(
                 'zones', TEST_ZONE_NAME_STR, 'xfrrej'), 3)
 
         #
@@ -459,7 +459,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         [rcode, msg] = self.xfrsess._parse_query_message(request_data)
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.xfrsess._counter.get(
+        self.assertEqual(self.xfrsess._counters.get(
                 'zones', TEST_ZONE_NAME_STR, 'xfrrej'), 4)
         # Address matches, but TSIG doesn't (not included)
         self.xfrsess._remote = (socket.AF_INET, socket.SOCK_STREAM,
@@ -467,7 +467,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.xfrsess._counter.get(
+        self.assertEqual(self.xfrsess._counters.get(
                 'zones', TEST_ZONE_NAME_STR, 'xfrrej'), 5)
         # Neither address nor TSIG matches
         self.xfrsess._remote = (socket.AF_INET, socket.SOCK_STREAM,
@@ -475,7 +475,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.xfrsess._counter.get(
+        self.assertEqual(self.xfrsess._counters.get(
                 'zones', TEST_ZONE_NAME_STR, 'xfrrej'), 6)
 
     def test_transfer_acl(self):
@@ -860,10 +860,10 @@ class TestXfroutSession(TestXfroutSessionBase):
 
         self.xfrsess._reply_xfrout_query = myreply
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.xfrsess._counter.get,
+                          self.xfrsess._counters.get,
                           'socket', 'unixdomain', 'senderr')
         self.xfrsess.dns_xfrout_start(self.sock, self.mdata)
-        self.assertEqual(self.xfrsess._counter.get(
+        self.assertEqual(self.xfrsess._counters.get(
                 'socket', 'unixdomain', 'senderr'), 1)
 
     def test_dns_xfrout_start_noerror(self):
@@ -875,12 +875,12 @@ class TestXfroutSession(TestXfroutSessionBase):
             self.sock.send(b"success")
 
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.xfrsess._counter.get,
+                          self.xfrsess._counters.get,
                           'zones', TEST_ZONE_NAME_STR, 'xfrreqdone')
         self.xfrsess._reply_xfrout_query = myreply
         self.xfrsess.dns_xfrout_start(self.sock, self.mdata)
         self.assertEqual(self.sock.readsent(), b"success")
-        self.assertGreater(self.xfrsess._counter.get(
+        self.assertGreater(self.xfrsess._counters.get(
             'zones', TEST_ZONE_NAME_STR, 'xfrreqdone'), 0)
 
     def test_reply_xfrout_query_axfr(self):
@@ -1138,7 +1138,7 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
 
     def test_axfr_normal_session(self):
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.xfrsess._counter.get, 'axfr_running')
+                          self.xfrsess._counters.get, 'axfr_running')
         XfroutSession._handle(self.xfrsess)
         response = self.sock.read_msg(Message.PRESERVE_ORDER);
         self.assertEqual(Rcode.NOERROR(), response.get_rcode())
@@ -1146,8 +1146,8 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
         self.assertEqual(self.xfrsess._request_type, RRType.AXFR())
         self.assertNotEqual(self.xfrsess._request_type, RRType.IXFR())
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.xfrsess._counter.get, 'ixfr_running')
-        self.assertEqual(self.xfrsess._counter.get('axfr_running'), 0)
+                          self.xfrsess._counters.get, 'ixfr_running')
+        self.assertEqual(self.xfrsess._counters.get('axfr_running'), 0)
 
     def test_ixfr_to_axfr(self):
         self.xfrsess._request_data = \
@@ -1167,9 +1167,9 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
         self.xfrsess._request_data = \
             self.create_request_data(ixfr=IXFR_OK_VERSION)
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.xfrsess._counter.get, 'axfr_running')
+                          self.xfrsess._counters.get, 'axfr_running')
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.xfrsess._counter.get, 'ixfr_running')
+                          self.xfrsess._counters.get, 'ixfr_running')
         XfroutSession._handle(self.xfrsess)
         response = self.sock.read_msg(Message.PRESERVE_ORDER)
         actual_records = response.get_section(Message.SECTION_ANSWER)
@@ -1188,8 +1188,8 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
         self.assertNotEqual(self.xfrsess._request_type, RRType.AXFR())
         self.assertEqual(self.xfrsess._request_type, RRType.IXFR())
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.xfrsess._counter.get, 'axfr_running')
-        self.assertEqual(self.xfrsess._counter.get('ixfr_running'), 0)
+                          self.xfrsess._counters.get, 'axfr_running')
+        self.assertEqual(self.xfrsess._counters.get('ixfr_running'), 0)
 
     def ixfr_soa_only_common_checks(self, request_serial):
         self.xfrsess._request_data = \
@@ -1217,7 +1217,7 @@ class MyUnixSockServer(UnixSockServer):
         self._common_init()
         self._cc = MyCCSession()
         self.update_config_data(self._cc.get_full_config())
-        self._counter = xfrout.Counter(xfrout.SPECFILE_LOCATION)
+        self._counters = xfrout.Counters(xfrout.SPECFILE_LOCATION)
 
 class TestUnixSockServer(unittest.TestCase):
     def setUp(self):
@@ -1578,57 +1578,57 @@ class TestUnixSockServerForCounter(unittest.TestCase):
             super,
             self.orig_process_request,
             self.orig_select )
-        self.unix._counter.clear_counters()
+        self.unix._counters.clear_all()
 
     def test_open(self):
         # open
         self.assertEqual(
-            self.unix._counter.get('socket', 'unixdomain', 'open'), 1)
+            self.unix._counters.get('socket', 'unixdomain', 'open'), 1)
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.unix._counter.get,
+                          self.unix._counters.get,
                           'socket', 'unixdomain', 'openfail')
         xfrout.ThreadingUnixStreamServer = DummySocketserverException
         self.unix = UnixSockServer(None, None, None, None, None)
         self.assertEqual(
-            self.unix._counter.get('socket', 'unixdomain', 'open'), 1)
+            self.unix._counters.get('socket', 'unixdomain', 'open'), 1)
         self.assertEqual(
-            self.unix._counter.get('socket', 'unixdomain', 'openfail'), 1)
+            self.unix._counters.get('socket', 'unixdomain', 'openfail'), 1)
 
     def test_close(self):
         # close
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.unix._counter.get,
+                          self.unix._counters.get,
                           'socket','unixdomain', 'close')
         self.unix.shutdown()
         self.assertEqual(
-            self.unix._counter.get('socket', 'unixdomain', 'close'), 1)
+            self.unix._counters.get('socket', 'unixdomain', 'close'), 1)
 
     def test_bindfail(self):
         # bindfail
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.unix._counter.get,
+                          self.unix._counters.get,
                           'socket', 'unixdomain', 'bindfail')
         self.assertRaises(Exception, self.unix.server_bind)
         self.assertEqual(
-            self.unix._counter.get('socket', 'unixdomain', 'bindfail'), 1)
+            self.unix._counters.get('socket', 'unixdomain', 'bindfail'), 1)
 
     def test_accept(self):
         # accept
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.unix._counter.get,
+                          self.unix._counters.get,
                           'socket', 'unixdomain', 'accept')
         self.unix.get_request()
         self.assertEqual(
-            self.unix._counter.get('socket', 'unixdomain', 'accept'), 1)
+            self.unix._counters.get('socket', 'unixdomain', 'accept'), 1)
         # acceptfail
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.unix._counter.get,
+                          self.unix._counters.get,
                           'socket', 'unixdomain', 'acceptfail')
         xfrout.super = lambda : DummyClassException()
         self.unix = UnixSockServer(None, None, None, None, None)
         self.assertRaises(Exception, self.unix.get_request)
         self.assertEqual(
-            self.unix._counter.get('socket', 'unixdomain', 'acceptfail'), 1)
+            self.unix._counters.get('socket', 'unixdomain', 'acceptfail'), 1)
 
     def test_senderr(self):
         # do inside of above TestXfroutSession
@@ -1637,13 +1637,13 @@ class TestUnixSockServerForCounter(unittest.TestCase):
     def test_recverr(self):
         # recverr
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.unix._counter.get,
+                          self.unix._counters.get,
                           'socket', 'unixdomain', 'recverr')
         def raise_socketerror(x,y):
             raise socket.error
         self.unix.process_request = raise_socketerror
         self.unix._select_loop(None)
-        self.assertEqual(self.unix._counter.get(
+        self.assertEqual(self.unix._counters.get(
                 'socket', 'unixdomain', 'recverr'), 1)
 
 class TestInitialization(unittest.TestCase):
@@ -1694,7 +1694,7 @@ class MyXfroutServer(XfroutServer):
         self._wait_for_threads = lambda : None
         self._cc.get_module_spec = lambda:\
             isc.config.module_spec_from_file(xfrout.SPECFILE_LOCATION)
-        self._counter = xfrout.Counter(xfrout.SPECFILE_LOCATION)
+        self._counters = xfrout.Counters(xfrout.SPECFILE_LOCATION)
 
 class TestXfroutServer(unittest.TestCase):
     def setUp(self):
diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in
index 8d51438..b834982 100755
--- a/src/bin/xfrout/xfrout.py.in
+++ b/src/bin/xfrout/xfrout.py.in
@@ -27,7 +27,7 @@ from socketserver import *
 import os
 from isc.config.ccsession import *
 from isc.cc import SessionError, SessionTimeout
-from isc.statistics import Counter
+from isc.statistics import Counters
 from isc.notify import notify_out
 import isc.util.process
 import socket
@@ -169,9 +169,9 @@ class XfroutSession():
         self.ClientClass = client_class # parameterize this for testing
         self._soa = None # will be set in _xfrout_setup or in tests
         self._jnl_reader = None # will be set to a reader for IXFR
-        # Creation of self.counter should be done before of
+        # Creation of self.counters should be done before of
         # invoking self._handle()
-        self._counter = Counter(SPECFILE_LOCATION)
+        self._counters = Counters(SPECFILE_LOCATION)
         self._handle()
 
     def create_tsig_ctx(self, tsig_record, tsig_key_ring):
@@ -275,7 +275,7 @@ class XfroutSession():
             return None, None
         elif acl_result == REJECT:
             # count rejected Xfr request by each zone name
-            self._counter.inc('zones', zone_name.to_text(), 'xfrrej')
+            self._counters.inc('zones', zone_name.to_text(), 'xfrrej')
             logger.debug(DBG_XFROUT_TRACE, XFROUT_QUERY_REJECTED,
                          self._request_type, format_addrinfo(self._remote),
                          format_zone_str(zone_name, zone_class))
@@ -527,25 +527,25 @@ class XfroutSession():
         try:
             # increment Xfr starts by RRType
             if self._request_type == RRType.AXFR():
-                self._counter.inc('axfr_running')
+                self._counters.inc('axfr_running')
             else:
-                self._counter.inc('ixfr_running')
+                self._counters.inc('ixfr_running')
             logger.info(XFROUT_XFR_TRANSFER_STARTED, self._request_typestr,
                         format_addrinfo(self._remote), zone_str)
             self._reply_xfrout_query(msg, sock_fd)
         except Exception as err:
             # count unixsockets send errors
-            self._counter.inc('socket', 'unixdomain', 'senderr')
+            self._counters.inc('socket', 'unixdomain', 'senderr')
             logger.error(XFROUT_XFR_TRANSFER_ERROR, self._request_typestr,
                     format_addrinfo(self._remote), zone_str, err)
         finally:
             # decrement Xfr starts by RRType
             if self._request_type == RRType.AXFR():
-                self._counter.dec('axfr_running')
+                self._counters.dec('axfr_running')
             else:
-                self._counter.dec('ixfr_running')
+                self._counters.dec('ixfr_running')
         # count done Xfr requests by each zone name
-        self._counter.inc('zones', zone_name.to_text(), 'xfrreqdone')
+        self._counters.inc('zones', zone_name.to_text(), 'xfrreqdone')
         logger.info(XFROUT_XFR_TRANSFER_DONE, self._request_typestr,
                     format_addrinfo(self._remote), zone_str)
 
@@ -659,14 +659,14 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
         self._remove_unused_sock_file(sock_file)
         self._sock_file = sock_file
         socketserver_mixin.NoPollMixIn.__init__(self)
-        self._counter = Counter(SPECFILE_LOCATION)
+        self._counters = Counters(SPECFILE_LOCATION)
         try:
             ThreadingUnixStreamServer.__init__(self, sock_file, \
                                                    handle_class)
         except:
-            self._counter.inc('socket', 'unixdomain', 'openfail')
+            self._counters.inc('socket', 'unixdomain', 'openfail')
         else:
-            self._counter.inc('socket', 'unixdomain', 'open')
+            self._counters.inc('socket', 'unixdomain', 'open')
         self._shutdown_event = shutdown_event
         self._write_sock, self._read_sock = socket.socketpair()
         self._common_init()
@@ -683,7 +683,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
             return super().server_bind()
         except:
             # count bind failed unixsockets
-            self._counter.inc('socket', 'unixdomain', 'bindfail')
+            self._counters.inc('socket', 'unixdomain', 'bindfail')
             raise
 
     def get_request(self):
@@ -695,11 +695,11 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
             # ThreadingUnixStreamServer
             ret = super().get_request()
             # count successfully accepted unixsockets
-            self._counter.inc('socket', 'unixdomain', 'accept')
+            self._counters.inc('socket', 'unixdomain', 'accept')
             return ret
         except:
             # count failed accepted unixsockets
-            self._counter.inc('socket', 'unixdomain', 'acceptfail')
+            self._counters.inc('socket', 'unixdomain', 'acceptfail')
             raise
 
     def _common_init(self):
@@ -769,7 +769,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
                     break
             except Exception as pre:
                 # count unixsockets receive errors
-                self._counter.inc('socket', 'unixdomain', 'recverr')
+                self._counters.inc('socket', 'unixdomain', 'recverr')
                 logger.error(XFROUT_PROCESS_REQUEST_ERROR, pre)
                 break
 
@@ -896,7 +896,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
         super().shutdown() # call the shutdown() of class socketserver_mixin.NoPollMixIn
         try:
             # count closed unixsockets
-            self._counter.inc('socket', 'unixdomain', 'close')
+            self._counters.inc('socket', 'unixdomain', 'close')
             os.unlink(self._sock_file)
         except Exception as e:
             logger.error(XFROUT_REMOVE_UNIX_SOCKET_FILE_ERROR, self._sock_file, str(e))
@@ -999,7 +999,7 @@ class XfroutServer:
         isc.server_common.tsig_keyring.init_keyring(self._cc)
         self._start_xfr_query_listener()
         self._start_notifier()
-        self._counter = Counter(SPECFILE_LOCATION)
+        self._counters = Counters(SPECFILE_LOCATION)
 
     def _start_xfr_query_listener(self):
         '''Start a new thread to accept xfr query. '''
@@ -1095,7 +1095,7 @@ class XfroutServer:
             # The log level is here set to debug in order to avoid
             # that a log becomes too verbose. Because the b10-stats
             # daemon is periodically asking to the b10-xfrout daemon.
-            answer = create_answer(0, self._counter.dump_statistics())
+            answer = create_answer(0, self._counters.get_statistics())
             logger.debug(DBG_XFROUT_TRACE, \
                              XFROUT_RECEIVED_GETSTATS_COMMAND, \
                              str(answer))
diff --git a/src/lib/python/isc/notify/notify_out.py b/src/lib/python/isc/notify/notify_out.py
index 64f9186..fdd9bb9 100644
--- a/src/lib/python/isc/notify/notify_out.py
+++ b/src/lib/python/isc/notify/notify_out.py
@@ -25,7 +25,7 @@ from isc.datasrc import DataSourceClient
 from isc.net import addr
 import isc
 from isc.log_messages.notify_out_messages import *
-from isc.statistics import Counter
+from isc.statistics import Counters
 
 logger = isc.log.Logger("notify_out")
 
@@ -143,7 +143,7 @@ class NotifyOut:
         # Use nonblock event to eliminate busy loop
         # If there are no notifying zones, clear the event bit and wait.
         self._nonblock_event = threading.Event()
-        self._counter = Counter()
+        self._counters = Counters()
 
     def _init_notify_out(self, datasrc_file):
         '''Get all the zones name and its notify target's address.
@@ -482,10 +482,10 @@ class NotifyOut:
             sock.sendto(render.get_data(), 0, addrinfo)
             # count notifying by IPv4 or IPv6 for statistics
             if zone_notify_info.get_socket().family == socket.AF_INET:
-                self._counter.inc('zones', zone_notify_info.zone_name,
+                self._counters.inc('zones', zone_notify_info.zone_name,
                                   'notifyoutv4')
             elif zone_notify_info.get_socket().family == socket.AF_INET6:
-                self._counter.inc('zones', zone_notify_info.zone_name,
+                self._counters.inc('zones', zone_notify_info.zone_name,
                                   'notifyoutv6')
             logger.info(NOTIFY_OUT_SENDING_NOTIFY, addrinfo[0],
                         addrinfo[1])
diff --git a/src/lib/python/isc/notify/tests/notify_out_test.py b/src/lib/python/isc/notify/tests/notify_out_test.py
index 149096c..08663d4 100644
--- a/src/lib/python/isc/notify/tests/notify_out_test.py
+++ b/src/lib/python/isc/notify/tests/notify_out_test.py
@@ -112,7 +112,7 @@ class TestNotifyOut(unittest.TestCase):
         com_ch_info.notify_slaves.append(('1.1.1.1', 5353))
 
     def tearDown(self):
-        self._notify._counter.clear_counters()
+        self._notify._counters.clear_all()
 
     def test_send_notify(self):
         notify_out._MAX_NOTIFY_NUM = 2
@@ -267,10 +267,10 @@ class TestNotifyOut(unittest.TestCase):
         example_com_info = self._notify._notify_infos[('example.net.', 'IN')]
 
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self._notify._counter.get,
+                          self._notify._counters.get,
                           'zones', 'example.net.', 'notifyoutv4')
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self._notify._counter.get,
+                          self._notify._counters.get,
                           'zones', 'example.net.', 'notifyoutv6')
 
         example_com_info.prepare_notify_out()
@@ -278,38 +278,38 @@ class TestNotifyOut(unittest.TestCase):
                                                     ('192.0.2.1', 53))
         self.assertTrue(ret)
         self.assertEqual(socket.AF_INET, example_com_info.sock_family)
-        self.assertEqual(self._notify._counter.get(
+        self.assertEqual(self._notify._counters.get(
                 'zones', 'example.net.', 'notifyoutv4'), 1)
-        self.assertEqual(self._notify._counter.get(
+        self.assertEqual(self._notify._counters.get(
                 'zones', 'example.net.', 'notifyoutv6'), 0)
 
     def test_send_notify_message_udp_ipv6(self):
         example_com_info = self._notify._notify_infos[('example.net.', 'IN')]
 
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self._notify._counter.get,
+                          self._notify._counters.get,
                           'zones', 'example.net.', 'notifyoutv4')
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self._notify._counter.get,
+                          self._notify._counters.get,
                           'zones', 'example.net.', 'notifyoutv6')
 
         ret = self._notify._send_notify_message_udp(example_com_info,
                                                     ('2001:db8::53', 53))
         self.assertTrue(ret)
         self.assertEqual(socket.AF_INET6, example_com_info.sock_family)
-        self.assertEqual(self._notify._counter.get(
+        self.assertEqual(self._notify._counters.get(
                 'zones', 'example.net.', 'notifyoutv4'), 0)
-        self.assertEqual(self._notify._counter.get(
+        self.assertEqual(self._notify._counters.get(
                 'zones', 'example.net.', 'notifyoutv6'), 1)
 
     def test_send_notify_message_with_bogus_address(self):
         example_com_info = self._notify._notify_infos[('example.net.', 'IN')]
 
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self._notify._counter.get,
+                          self._notify._counters.get,
                           'zones', 'example.net.', 'notifyoutv4')
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self._notify._counter.get,
+                          self._notify._counters.get,
                           'zones', 'example.net.', 'notifyoutv6')
 
         # As long as the underlying data source validates RDATA this shouldn't
@@ -321,10 +321,10 @@ class TestNotifyOut(unittest.TestCase):
         self.assertFalse(ret)
 
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self._notify._counter.get,
+                          self._notify._counters.get,
                           'zones', 'example.net.', 'notifyoutv4')
         self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self._notify._counter.get,
+                          self._notify._counters.get,
                           'zones', 'example.net.', 'notifyoutv4')
 
     def test_zone_notify_handler(self):
diff --git a/src/lib/python/isc/statistics/Makefile.am b/src/lib/python/isc/statistics/Makefile.am
index e269b1e..9be1312 100644
--- a/src/lib/python/isc/statistics/Makefile.am
+++ b/src/lib/python/isc/statistics/Makefile.am
@@ -1,6 +1,6 @@
 SUBDIRS = . tests
 
-python_PYTHON = __init__.py counter.py
+python_PYTHON = __init__.py counters.py
 pythondir = $(pyexecdir)/isc/statistics
 
 CLEANDIRS = __pycache__
diff --git a/src/lib/python/isc/statistics/__init__.py b/src/lib/python/isc/statistics/__init__.py
index 2daa4b7..9e77ed6 100644
--- a/src/lib/python/isc/statistics/__init__.py
+++ b/src/lib/python/isc/statistics/__init__.py
@@ -1 +1 @@
-from isc.statistics.counter import *
+from isc.statistics.counters import *
diff --git a/src/lib/python/isc/statistics/counter.py b/src/lib/python/isc/statistics/counter.py
deleted file mode 100644
index 5946790..0000000
--- a/src/lib/python/isc/statistics/counter.py
+++ /dev/null
@@ -1,370 +0,0 @@
-# Copyright (C) 2012  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.
-
-"""BIND 10 Statistics counter module
-
-This module handles the statistics counters for BIND 10 modules.  For
-using the module `counter.py`, firstly the init() method should be
-invoked in each module like b10-xfrin or b10-xfrout after importing
-this module.
-
-  from isc.statistics import Counter
-  self.counter = Counter(/path/to/foo.spec)
-
-The first argument of Counter() can be specified, which is the
-location of the specification file like src/bin/xfrout/xfrout.spec. If
-this initial preparation is done, statistics counters can be accessed
-from each module. For example, in case that the item `xfrreqdone` is
-defined in statistics_spec in xfrout.spec, the following methods is
-callable. Since these methods requires the string of the zone name in
-the first argument, in the b10-xfrout,
-
-  self.counter.inc('zones', zone_name, 'xfrreqdone')
-
-then the counter for xfrreqdone corresponding to zone_name was
-incremented. For getting the current number of this counter, we can do
-this,
-
-  number = self.counter.get('zones', zone_name, 'xfrreqdone')
-
-then the current number was obtained and set in the above variable
-`number`. Such a getter method would be mainly used for unittesting.
-In other example, regarding the item `axfr_running`, the decrementer
-method is also callable.  This method is used for decrementing the
-counter number.  Regarding the item `axfr_running`, an argument like
-zone name is not required.
-
-  self.counter.dec('axfr_running')
-
-These methods are effective in other module. For example, in case
-that this module `counter.py` is once imported in such a main module
-as b10-xfrout, Regarding the item `notifyoutv4`, the incrementer
-as the following can be invoked via other module like notify_out.py,
-which is firstly imported in the main module.
-
-  self.counter.inc('zones', zone_name, 'notifyoutv4')
-
-In this example this is for incrementing the counter of the item
-notifyoutv4. Thus, such statement can be also written in the other
-library like isc.notify.notify_out. If this module `counter.py` isn't
-imported in the main module but imported in such a library module as
-isc.notify.notify_out, in this example, empty methods would be
-invoked, which is directly defined in `counter.py`.
-"""
-
-import threading
-import isc.config
-from datetime import datetime
-
-# static internal functions
-def _add_counter(element, spec, identifier):
-    """Returns value of the identifier if the identifier is in the
-    element. Otherwise, sets a default value from the spec then
-    returns it. If the top-level type of the identifier is named_set
-    and the second-level type is map, it sets a set of default values
-    under the level and then returns the default value of the
-    identifier. Raises DataNotFoundError if the element is invalid for
-    spec."""
-    try:
-        return isc.cc.data.find(element, identifier)
-    except isc.cc.data.DataNotFoundError:
-        pass
-    try:
-        isc.config.find_spec_part(spec, identifier)
-    except isc.cc.data.DataNotFoundError:
-        # spec or identifier is wrong
-        raise
-    # examine spec of the top-level item first
-    spec_ = isc.config.find_spec_part(
-        spec, '%s' % identifier.split('/')[0])
-    if spec_['item_type'] == 'named_set' and \
-            spec_['named_set_item_spec']['item_type'] ==  'map':
-        map_spec = spec_['named_set_item_spec']['map_item_spec']
-        for name in isc.config.spec_name_list(map_spec):
-            spec_ = isc.config.find_spec_part(map_spec, name)
-            id_str = '%s/%s/%s' % \
-                tuple(identifier.split('/')[0:2] + [name])
-            isc.cc.data.set(element, id_str, spec_['item_default'])
-    else:
-        spec_ = isc.config.find_spec_part(spec, identifier)
-        isc.cc.data.set(element, identifier, spec_['item_default'])
-    return isc.cc.data.find(element, identifier)
-
-def _set_counter(element, spec, identifier, value):
-    """Invokes _add_counter() for checking whether the identifier is
-    in the element. If not, it creates a new identifier in the element
-    and set the default value from the spec. After that, it sets the
-    value specified in the arguments."""
-    _add_counter(element, spec, identifier)
-    isc.cc.data.set(element, identifier, value)
-
-def _get_counter(element, identifier):
-    """Returns the value of the identifier in the element"""
-    return isc.cc.data.find(element, identifier)
-
-def _inc_counter(element, spec, identifier, step=1):
-    """Increments the value of the identifier in the element to the
-    step from the current value. If the identifier isn't in the
-    element, it creates a new identifier in the element."""
-    isc.cc.data.set(element, identifier,
-                    _add_counter(element, spec, identifier) + step)
-
-def _start_timer():
-    """Returns the current datetime as a datetime object."""
-    return datetime.now()
-
-def _stop_timer(start_time, element, spec, identifier):
-    """Sets duration time in seconds as a value of the identifier in
-    the element, which is in seconds between start_time and the
-    current time and is float-type."""
-    delta = datetime.now() - start_time
-    sec = round(delta.days * 86400 + delta.seconds + \
-                    delta.microseconds * 1E-6, 6)
-    _set_counter(element, spec, identifier, sec)
-
-class _Statistics():
-    """Statistics data set"""
-    # default statistics data
-    _data = {}
-    # default statistics spec used in case of the specfile omitted in
-    # Counter()
-    _spec = [
-      {
-        "item_name": "zones",
-        "item_type": "named_set",
-        "item_optional": False,
-        "item_default": {
-          "_SERVER_" : {
-            "notifyoutv4" : 0,
-            "notifyoutv6" : 0
-          }
-        },
-        "item_title": "Zone names",
-        "item_description": "Zone names",
-        "named_set_item_spec": {
-          "item_name": "zonename",
-          "item_type": "map",
-          "item_optional": False,
-          "item_default": {},
-          "item_title": "Zone name",
-          "item_description": "Zone name",
-          "map_item_spec": [
-            {
-              "item_name": "notifyoutv4",
-              "item_type": "integer",
-              "item_optional": False,
-              "item_default": 0,
-              "item_title": "IPv4 notifies",
-              "item_description": "Number of IPv4 notifies per zone name sent out"
-            },
-            {
-              "item_name": "notifyoutv6",
-              "item_type": "integer",
-              "item_optional": False,
-              "item_default": 0,
-              "item_title": "IPv6 notifies",
-              "item_description": "Number of IPv6 notifies per zone name sent out"
-            }
-          ]
-        }
-      }
-    ]
-
-class Counter():
-    """A module for holding all statistics counters of modules. The
-    counter numbers can be accessed by the accesseers defined
-    according to a spec file. In this class, the structure of per-zone
-    counters is assumed to be like this:
-
-        zones/example.com./notifyoutv4
-        zones/example.com./notifyoutv6
-        zones/example.com./xfrrej
-        zones/example.com./xfrreqdone
-        zones/example.com./soaoutv4
-        zones/example.com./soaoutv6
-        zones/example.com./axfrreqv4
-        zones/example.com./axfrreqv6
-        zones/example.com./ixfrreqv4
-        zones/example.com./ixfrreqv6
-        zones/example.com./xfrsuccess
-        zones/example.com./xfrfail
-        zones/example.com./time_to_ixfr
-        zones/example.com./time_to_axfr
-        ixfr_running
-        axfr_running
-        socket/unixdomain/open
-        socket/unixdomain/openfail
-        socket/unixdomain/close
-        socket/unixdomain/bindfail
-        socket/unixdomain/acceptfail
-        socket/unixdomain/accept
-        socket/unixdomain/senderr
-        socket/unixdomain/recverr
-        socket/ipv4/tcp/open
-        socket/ipv4/tcp/openfail
-        socket/ipv4/tcp/close
-        socket/ipv4/tcp/connfail
-        socket/ipv4/tcp/conn
-        socket/ipv4/tcp/senderr
-        socket/ipv4/tcp/recverr
-        socket/ipv6/tcp/open
-        socket/ipv6/tcp/openfail
-        socket/ipv6/tcp/close
-        socket/ipv6/tcp/connfail
-        socket/ipv6/tcp/conn
-        socket/ipv6/tcp/senderr
-        socket/ipv6/tcp/recverr
-    """
-
-    # '_SERVER_' is a special zone name representing an entire
-    # count. It doesn't mean a specific zone, but it means an
-    # entire count in the server.
-    _entire_server = '_SERVER_'
-    # zone names are contained under this dirname in the spec file.
-    _perzone_prefix = 'zones'
-    # default statistics data set
-    _statistics = _Statistics()
-
-    def __init__(self, spec_file_name=None):
-        self._zones_item_list = []
-        self._start_time = {}
-        self._disabled = False
-        self._rlock = threading.RLock()
-        if not spec_file_name: return
-        # change the default statistics spec
-        self._statistics._spec = \
-            isc.config.module_spec_from_file(spec_file_name).\
-            get_statistics_spec()
-        if self._perzone_prefix in \
-                isc.config.spec_name_list(self._statistics._spec):
-            self._zones_item_list = isc.config.spec_name_list(
-                isc.config.find_spec_part(
-                    self._statistics._spec, self._perzone_prefix)\
-                    ['named_set_item_spec']['map_item_spec'])
-
-    def clear_counters(self):
-        """clears all statistics data"""
-        with self._rlock:
-            self._statistics._data = {}
-
-    def disable(self):
-        """disables incrementing/decrementing counters"""
-        self._disabled = True
-
-    def enable(self):
-        """enables incrementing/decrementing counters"""
-        self._disabled = False
-
-    def inc(self, *args):
-        """A incrementer for per-zone counter. Locks the thread
-        because it is considered to be invoked by a multi-threading
-        caller. isc.cc.data.DataNotFoundError is raised when
-        incrementing the counter of the item undefined in the spec
-        file."""
-        identifier = '/'.join(args)
-        step = 1
-        if self._disabled: return
-        with self._rlock:
-            _inc_counter(self._statistics._data,
-                         self._statistics._spec,
-                         identifier, step)
-
-    def dec(self, *args):
-        """A decrementer for axfr or ixfr running. Locks the thread
-        because it is considered to be invoked by a multi-threading
-        caller. isc.cc.data.DataNotFoundError is raised when
-        decrementing the counter of the item undefined in the spec
-        file."""
-        identifier = '/'.join(args)
-        step = -1
-        if self._disabled: return
-        with self._rlock:
-            _inc_counter(self._statistics._data,
-                         self._statistics._spec,
-                         identifier, step)
-
-    def get(self, *args):
-        """A getter method for counters. It returns the current number
-        of the specified counter.  isc.cc.data.DataNotFoundError is
-        raised when the counter doesn't have a number yet."""
-        identifier = '/'.join(args)
-        return _get_counter(self._statistics._data, identifier)
-
-    def start(self, *args):
-        """Sets the value returned from _start_timer() as a value of
-        the identifier in the self._start_time which is dict-type"""
-        identifier = '/'.join(args)
-        isc.cc.data.set(self._start_time, identifier, _start_timer())
-
-    def stop(self, *args):
-        """Sets duration time between corresponding time in
-        self._start_time and current time into the value of the
-        identifier. It deletes corresponding time in self._start_time
-        after setting is successfully done. In case of stopping the
-        timer which has never been started, it raises and does
-        nothing. But in case of stopping the time which isn't defined
-        in the spec file, it raises DataNotFoundError"""
-        identifier = '/'.join(args)
-        try:
-            start_time = isc.cc.data.find(self._start_time,
-                                          identifier)
-        except isc.cc.data.DataNotFoundError:
-            # do not set the end time if the timer isn't started
-            pass
-        else:
-            # set the end time
-            _stop_timer(
-                start_time,
-                self._statistics._data,
-                self._statistics._spec,
-                identifier)
-            # delete the started timer
-            del isc.cc.data.find(
-                self._start_time,
-                '/'.join(identifier.split('/')[0:-1]))\
-                [identifier.split('/')[-1]]
-
-    def dump_statistics(self):
-        """Calculates an entire server counts, and returns statistics
-        data format to send out the stats module including each
-        counter. If there is no counts, then it returns an empty
-        dictionary."""
-        # entire copy
-        statistics_data = self._statistics._data.copy()
-        # If self.statistics_data contains nothing of zone name, it
-        # returns an empty dict.
-        if self._perzone_prefix not in statistics_data:
-            return statistics_data
-        zones = statistics_data[self._perzone_prefix]
-        # Start calculation for '_SERVER_' counts
-        zones_spec = isc.config.find_spec_part(self._statistics._spec,
-                                               self._perzone_prefix)
-        zones_attrs = zones_spec['item_default'][self._entire_server]
-        zones_data = {}
-        for attr in zones_attrs:
-            id_str = '%s/%s' % (self._entire_server, attr)
-            sum_ = 0
-            for name in zones:
-                if attr in zones[name]:
-                    sum_ += zones[name][attr]
-            if  sum_ > 0:
-                _set_counter(zones_data, zones_spec,
-                             id_str, sum_)
-        # insert entire-sever counts
-        statistics_data[self._perzone_prefix] = dict(
-            statistics_data[self._perzone_prefix],
-            **zones_data)
-        return statistics_data
-
diff --git a/src/lib/python/isc/statistics/counters.py b/src/lib/python/isc/statistics/counters.py
new file mode 100644
index 0000000..8da0b1e
--- /dev/null
+++ b/src/lib/python/isc/statistics/counters.py
@@ -0,0 +1,399 @@
+# Copyright (C) 2012  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.
+
+"""BIND 10 statistics counters module
+
+This module handles the statistics counters for BIND 10 modules.  For
+using the module `counter.py`, first a counters object should be created
+in each module (like b10-xfrin or b10-xfrout) after importing this
+module. A spec file can be specified as an argument when creating the
+counters object:
+
+  from isc.statistics import Counters
+  self.counters = Counters("/path/to/foo.spec")
+
+The first argument of Counters() can be specified, which is the location
+of the specification file (like src/bin/xfrout/xfrout.spec). If Counters
+is constructed this way, statistics counters can be accessed from each
+module. For example, in case that the item `xfrreqdone` is defined in
+statistics_spec in xfrout.spec, the following methods are
+callable. Since these methods require the string of the zone name in the
+first argument, if we have the following code in b10-xfrout:
+
+  self.counters.inc('zones', zone_name, 'xfrreqdone')
+
+then the counter for xfrreqdone corresponding to zone_name is
+incremented. For getting the current number of this counter, we can use
+the following code:
+
+  number = self.counters.get('zones', zone_name, 'xfrreqdone')
+
+then the current count is obtained and set in the variable
+`number`. Such a getter method would be mainly used for unit-testing.
+As other example, for the item `axfr_running`, the decrementer method is
+also callable.  This method is used for decrementing a counter.  For the
+item `axfr_running`, an argument like zone name is not required:
+
+  self.counters.dec('axfr_running')
+
+These methods are effective in other modules. For example, in case that
+this module `counter.py` is once imported in a main module such as
+b10-xfrout, then for the item `notifyoutv4`, the `inc()` method can be
+invoked in another module such as notify_out.py, which is firstly
+imported in the main module.
+
+  self.counters.inc('zones', zone_name, 'notifyoutv4')
+
+In this example this is for incrementing the counter of the item
+`notifyoutv4`. Thus, such statement can be also written in another
+library like isc.notify.notify_out. If this module `counter.py` isn't
+imported in the main module but imported in such a library module as
+isc.notify.notify_out, in this example, empty methods would be invoked,
+which is directly defined in `counter.py`.
+"""
+
+import threading
+import isc.config
+from datetime import datetime
+
+# static internal functions
+def _add_counter(element, spec, identifier):
+    """Returns value of the identifier if the identifier is in the
+    element. Otherwise, sets a default value from the spec and
+    returns it. If the top-level type of the identifier is named_set
+    and the second-level type is map, it sets a set of default values
+    under the level and then returns the default value of the
+    identifier. This method raises DataNotFoundError if the element is
+    invalid for spec."""
+    try:
+        return isc.cc.data.find(element, identifier)
+    except isc.cc.data.DataNotFoundError:
+        pass
+    # check whether spec and identifier are correct
+    isc.config.find_spec_part(spec, identifier)
+    # examine spec of the top-level item first
+    spec_ = isc.config.find_spec_part(spec, identifier.split('/')[0])
+    if spec_['item_type'] == 'named_set' and \
+            spec_['named_set_item_spec']['item_type'] ==  'map':
+        map_spec = spec_['named_set_item_spec']['map_item_spec']
+        for name in isc.config.spec_name_list(map_spec):
+            spec_ = isc.config.find_spec_part(map_spec, name)
+            id_str = '%s/%s/%s' % \
+                tuple(identifier.split('/')[0:2] + [name])
+            isc.cc.data.set(element, id_str, spec_['item_default'])
+    else:
+        spec_ = isc.config.find_spec_part(spec, identifier)
+        isc.cc.data.set(element, identifier, spec_['item_default'])
+    return isc.cc.data.find(element, identifier)
+
+def _set_counter(element, spec, identifier, value):
+    """Invokes _add_counter() for checking whether the identifier is
+    in the element. If not, it creates a new identifier in the element
+    and set the default value from the spec. After that, it sets the
+    value specified in the arguments."""
+    _add_counter(element, spec, identifier)
+    isc.cc.data.set(element, identifier, value)
+
+def _get_counter(element, identifier):
+    """Returns the value of the identifier in the element"""
+    return isc.cc.data.find(element, identifier)
+
+def _inc_counter(element, spec, identifier, step=1):
+    """Increments the value of the identifier in the element to the
+    step from the current value. If the identifier isn't in the
+    element, it creates a new identifier in the element."""
+    isc.cc.data.set(element, identifier,
+                    _add_counter(element, spec, identifier) + step)
+
+def _start_timer():
+    """Returns the current datetime as a datetime object."""
+    return datetime.now()
+
+def _stop_timer(start_time, element, spec, identifier):
+    """Sets duration time in seconds as a value of the identifier in
+    the element, which is in seconds between start_time and the
+    current time and is float-type."""
+    delta = datetime.now() - start_time
+    sec = round(delta.days * 86400 + delta.seconds + \
+                    delta.microseconds * 1E-6, 6)
+    _set_counter(element, spec, identifier, sec)
+
+def _concat(*args, sep='/'):
+    """A helper function that is used to generate an identifier for
+    statistics item names. It concatenates words in args with a
+    separator('/')
+    """
+    return sep.join(args)
+
+class _Statistics():
+    """Statistics data set"""
+    # default statistics data
+    _data = {}
+    # default statistics spec used in case the specfile is omitted when
+    # constructing a Counters() object
+    _spec = [
+      {
+        "item_name": "zones",
+        "item_type": "named_set",
+        "item_optional": False,
+        "item_default": {
+          "_SERVER_" : {
+            "notifyoutv4" : 0,
+            "notifyoutv6" : 0
+          }
+        },
+        "item_title": "Zone names",
+        "item_description": "Zone names",
+        "named_set_item_spec": {
+          "item_name": "zonename",
+          "item_type": "map",
+          "item_optional": False,
+          "item_default": {},
+          "item_title": "Zone name",
+          "item_description": "Zone name",
+          "map_item_spec": [
+            {
+              "item_name": "notifyoutv4",
+              "item_type": "integer",
+              "item_optional": False,
+              "item_default": 0,
+              "item_title": "IPv4 notifies",
+              "item_description": "Number of IPv4 notifies per zone name sent out"
+            },
+            {
+              "item_name": "notifyoutv6",
+              "item_type": "integer",
+              "item_optional": False,
+              "item_default": 0,
+              "item_title": "IPv6 notifies",
+              "item_description": "Number of IPv6 notifies per zone name sent out"
+            }
+          ]
+        }
+      }
+    ]
+
+class Counters():
+    """A class for holding and manipulating all statistics counters
+    for a module.  A Counters object may be created by specifying a spec
+    file of the module in argument.  According to statistics
+    specification in the spec file, a counter value can be incremented,
+    decremented or obtained. Methods such as inc(), dec() and get() are
+    useful for this.  Counters objects also have timer functionality.
+    The timer can be started and stopped, and the duration between
+    start and stop can be obtained. Methods such as start_timer(),
+    stop_timer() and get() are useful for this. Saved counters can be
+    cleared by the method clear_all(). Manipulating counters and
+    timers can be temporarily disabled.  If disabled, counter values are
+    not changed even if methods to update them are invoked.  Including
+    per-zone counters, a list of counters which can be handled in the
+    class are like the following:
+
+        zones/example.com./notifyoutv4
+        zones/example.com./notifyoutv6
+        zones/example.com./xfrrej
+        zones/example.com./xfrreqdone
+        zones/example.com./soaoutv4
+        zones/example.com./soaoutv6
+        zones/example.com./axfrreqv4
+        zones/example.com./axfrreqv6
+        zones/example.com./ixfrreqv4
+        zones/example.com./ixfrreqv6
+        zones/example.com./xfrsuccess
+        zones/example.com./xfrfail
+        zones/example.com./time_to_ixfr
+        zones/example.com./time_to_axfr
+        ixfr_running
+        axfr_running
+        socket/unixdomain/open
+        socket/unixdomain/openfail
+        socket/unixdomain/close
+        socket/unixdomain/bindfail
+        socket/unixdomain/acceptfail
+        socket/unixdomain/accept
+        socket/unixdomain/senderr
+        socket/unixdomain/recverr
+        socket/ipv4/tcp/open
+        socket/ipv4/tcp/openfail
+        socket/ipv4/tcp/close
+        socket/ipv4/tcp/connfail
+        socket/ipv4/tcp/conn
+        socket/ipv4/tcp/senderr
+        socket/ipv4/tcp/recverr
+        socket/ipv6/tcp/open
+        socket/ipv6/tcp/openfail
+        socket/ipv6/tcp/close
+        socket/ipv6/tcp/connfail
+        socket/ipv6/tcp/conn
+        socket/ipv6/tcp/senderr
+        socket/ipv6/tcp/recverr
+    """
+
+    # '_SERVER_' is a special zone name representing an entire
+    # count. It doesn't mean a specific zone, but it means an
+    # entire count in the server.
+    _entire_server = '_SERVER_'
+    # zone names are contained under this dirname in the spec file.
+    _perzone_prefix = 'zones'
+    # default statistics data set
+    _statistics = _Statistics()
+
+    def __init__(self, spec_file_name=None):
+        """A constructor for the Counters class. A path to the spec file
+        can be specified in spec_file_name. Statistics data based on
+        statistics spec can be accumulated if spec_file_name is
+        specified. If omitted, a default statistics spec is used. The
+        default statistics spec is defined in a hidden class named
+        _Statistics().
+        """
+        self._zones_item_list = []
+        self._start_time = {}
+        self._disabled = False
+        self._rlock = threading.RLock()
+        if not spec_file_name: return
+        # change the default statistics spec
+        self._statistics._spec = \
+            isc.config.module_spec_from_file(spec_file_name).\
+            get_statistics_spec()
+        if self._perzone_prefix in \
+                isc.config.spec_name_list(self._statistics._spec):
+            self._zones_item_list = isc.config.spec_name_list(
+                isc.config.find_spec_part(
+                    self._statistics._spec, self._perzone_prefix)\
+                    ['named_set_item_spec']['map_item_spec'])
+
+    def clear_all(self):
+        """clears all statistics data"""
+        with self._rlock:
+            self._statistics._data = {}
+
+    def disable(self):
+        """disables incrementing/decrementing counters"""
+        with self._rlock:
+            self._disabled = True
+
+    def enable(self):
+        """enables incrementing/decrementing counters"""
+        with self._rlock:
+            self._disabled = False
+
+    def _incdec(self, *args, step=1):
+        """A common helper function for incrementing or decrementing a
+        counter. It acquires a lock to support multi-threaded
+        use. isc.cc.data.DataNotFoundError is raised when incrementing
+        the counter of the item undefined in the spec file."""
+        identifier = _concat(*args)
+        with self._rlock:
+            if self._disabled: return
+            _inc_counter(self._statistics._data,
+                         self._statistics._spec,
+                         identifier, step)
+
+    def inc(self, *args):
+        """An incrementer for a counter. It acquires a lock to support
+        multi-threaded use. isc.cc.data.DataNotFoundError is raised when
+        incrementing the counter of the item undefined in the spec file."""
+        return self._incdec(*args)
+
+    def dec(self, *args):
+        """A decrementer for a counter. It acquires a lock to support
+        multi-threaded use. isc.cc.data.DataNotFoundError is raised when
+        decrementing the counter of the item undefined in the spec file."""
+        return self._incdec(*args, step=-1)
+
+    def get(self, *args):
+        """A getter method for counters. It returns the current number
+        of the specified counter.  isc.cc.data.DataNotFoundError is
+        raised when the counter doesn't have a number yet."""
+        identifier = _concat(*args)
+        return _get_counter(self._statistics._data, identifier)
+
+    def start_timer(self, *args):
+        """Starts a timer which is identified by args and keeps it
+        running until stop_timer() is called. It acquires a lock to
+        support multi-threaded use."""
+        identifier = _concat(*args)
+        with self._rlock:
+            if self._disabled: return
+            isc.cc.data.set(self._start_time, identifier, _start_timer())
+
+    def stop_timer(self, *args):
+        """Stops a timer which is identified by args. It acquires a lock
+        to support multi-threaded use. If the timer isn't started by
+        start_timer() yet, it raises no exception. However if args
+        aren't defined in the spec file, it raises DataNotFoundError.
+        """
+        identifier = _concat(*args)
+        with self._rlock:
+            if self._disabled: return
+            try:
+                start_time = isc.cc.data.find(self._start_time,
+                                              identifier)
+            except isc.cc.data.DataNotFoundError:
+                # do not set the end time if the timer isn't started
+                return
+            # set the end time
+            _stop_timer(
+                start_time,
+                self._statistics._data,
+                self._statistics._spec,
+                identifier)
+            # A datetime value of once used timer should be deleted
+            # for a future use.
+            # Here, names of branch and leaf are obtained from a
+            # string of identifier. The branch name is equivalent to
+            # the position of datetime to be deleted and the leaf name
+            # is equivalent to the value of datetime to be deleted.
+            (branch, leaf) = identifier.rsplit('/', 1)
+            # Then map of branch is obtained from self._start_time by
+            # using isc.cc.data.find().
+            branch_map = isc.cc.data.find(self._start_time, branch)
+            # Finally a value of the leaf name is deleted from the
+            # map.
+            del branch_map[leaf]
+
+    def get_statistics(self):
+        """Calculates an entire server's counts, and returns statistics
+        data in a format to send out to the stats module, including each
+        counter. If nothing is counted yet, then it returns an empty
+        dictionary."""
+        # entire copy
+        statistics_data = self._statistics._data.copy()
+        # If there is no 'zones' found in statistics_data,
+        # i.e. statistics_data contains no per-zone counter, it just
+        # returns statistics_data because calculating total counts
+        # across the zone names isn't necessary.
+        if self._perzone_prefix not in statistics_data:
+            return statistics_data
+        zones = statistics_data[self._perzone_prefix]
+        # Start calculation for '_SERVER_' counts
+        zones_spec = isc.config.find_spec_part(self._statistics._spec,
+                                               self._perzone_prefix)
+        zones_attrs = zones_spec['item_default'][self._entire_server]
+        zones_data = {}
+        for attr in zones_attrs:
+            id_str = '%s/%s' % (self._entire_server, attr)
+            sum_ = 0
+            for name in zones:
+                if attr in zones[name]:
+                    sum_ += zones[name][attr]
+            if  sum_ > 0:
+                _set_counter(zones_data, zones_spec,
+                             id_str, sum_)
+        # insert entire-server counts
+        statistics_data[self._perzone_prefix] = dict(
+            statistics_data[self._perzone_prefix],
+            **zones_data)
+        return statistics_data
diff --git a/src/lib/python/isc/statistics/tests/Makefile.am b/src/lib/python/isc/statistics/tests/Makefile.am
index 7e2252b..8dcc296 100644
--- a/src/lib/python/isc/statistics/tests/Makefile.am
+++ b/src/lib/python/isc/statistics/tests/Makefile.am
@@ -1,5 +1,5 @@
 PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
-PYTESTS = counter_test.py
+PYTESTS = counters_test.py
 EXTRA_DIST = $(PYTESTS)
 EXTRA_DIST += testdata/test_spec1.spec
 EXTRA_DIST += testdata/test_spec2.spec
diff --git a/src/lib/python/isc/statistics/tests/counter_test.py b/src/lib/python/isc/statistics/tests/counter_test.py
deleted file mode 100644
index 090188a..0000000
--- a/src/lib/python/isc/statistics/tests/counter_test.py
+++ /dev/null
@@ -1,301 +0,0 @@
-# Copyright (C) 2012  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.
-
-'''Tests for isc.statistics.counter'''
-
-import unittest
-import threading
-from datetime import timedelta
-import os
-import imp
-import isc.config
-
-TEST_ZONE_NAME_STR = "example.com."
-TESTDATA_SRCDIR = os.getenv("TESTDATASRCDIR")
-
-from isc.statistics import counter
-
-def setup_functor(event, cycle, functor, *args):
-    """Waits until the event is started, and then invokes the functor
-    by times of the cycle with args."""
-    event.wait()
-    for i in range(cycle): functor(*args)
-
-def start_functor(concurrency, number, functor, *args):
-    """Creates the threads of the number and makes them start. Sets
-    the event and waits until these threads are finished."""
-    threads = []
-    event = threading.Event()
-    for i in range(concurrency):
-        threads.append(threading.Thread(\
-                target=setup_functor, \
-                    args=(event, number, functor,) + args))
-    for th in threads: th.start()
-    event.set()
-    for th in threads: th.join()
-
-class TestBasicMethods(unittest.TestCase):
-    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec1.spec'
-
-    def setUp(self):
-        self.counter = counter.Counter(self.TEST_SPECFILE_LOCATION)
-
-    def tearDown(self):
-        self.counter.clear_counters()
-
-    def test_clear_counters(self):
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.counter.get, 'counter')
-        self.counter.inc('counter')
-        self.assertEqual(self.counter.get('counter'), 1)
-        self.counter.clear_counters()
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.counter.get, 'counter')
-
-    def test_enablediable(self):
-        self.assertFalse(self.counter._disabled)
-        self.counter.disable()
-        self.assertTrue(self.counter._disabled)
-        self.counter.enable()
-        self.assertFalse(self.counter._disabled)
-
-    def test_add_counter_normal(self):
-        element = {'counter' : 1}
-        self.assertEqual(\
-            counter._add_counter(element, [], 'counter'), 1)
-
-    def test_add_counter_wrongspec(self):
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          counter._add_counter,
-                          {}, [], 'counter')
-
-    def test_add_counter_empty(self):
-        self.assertEqual(\
-            counter._add_counter(
-                {},
-                [ { 'item_name' : 'counter',
-                    'item_type' : 'integer',
-                    'item_default' : 0 } ],
-                'counter'), 0)
-
-    def test_add_counter_empty_namedset(self):
-        elem = {}
-        spec = [ { 'item_name': 'dirs',
-                    'item_type': 'named_set',
-                    'named_set_item_spec': {
-                            'item_name': 'dir',
-                            'item_type': 'map',
-                            'map_item_spec': [
-                                { 'item_name': 'counter1',
-                                  'item_type': 'integer',
-                                  'item_default': 0 },
-                                { 'item_name': 'counter2',
-                                  'item_type': 'integer',
-                                  'item_default': 0 } ]}
-                   }]
-        self.assertEqual(\
-            counter._add_counter(elem, spec, 'dirs/foo/counter1'), 0)
-        self.assertEqual(\
-            counter._add_counter(elem, spec, 'dirs/bar/counter2'), 0)
-
-    def test_timer(self):
-        t1 = counter._start_timer()
-        t2 = t1 - timedelta(seconds=1)
-        self.assertEqual((t1 - t2).seconds, 1)
-        elem = {}
-        spec = [{ 'item_name': 'time',
-                  'item_type': 'real',
-                  'item_default': 0.0 }]
-        counter._stop_timer(t2, elem, spec, 'time')
-        self.assertGreater(counter._get_counter(elem,'time'), 1)
-
-    def test_rasing_incrementers(self):
-        """ use Thread"""
-        concurrency = 3    # number of the threads
-        number = 10000     # number of counting per thread
-        counter_name = "counter"
-        timer_name = "seconds"
-        start_time = counter._start_timer()
-        start_functor(concurrency, number, self.counter.inc,
-                      counter_name)
-        counter._stop_timer(start_time,
-                            self.counter._statistics._data,
-                            self.counter._statistics._spec,
-                            timer_name)
-        self.assertEqual(
-            counter._get_counter(self.counter._statistics._data,
-                                 counter_name),
-            concurrency * number)
-        self.assertGreater(
-            counter._get_counter(self.counter._statistics._data,
-                                 timer_name), 0)
-
-class BaseTestCounter():
-
-    def setUp(self):
-        self._statistics_data = {}
-        self.counter = counter.Counter(self.TEST_SPECFILE_LOCATION)
-        self._entire_server    = self.counter._entire_server
-        self._perzone_prefix   = self.counter._perzone_prefix
-
-    def tearDown(self):
-        self.counter.clear_counters()
-
-    def check_dump_statistics(self):
-        """Checks no differences between the value returned from
-        dump_statistics() and locally collected statistics data. Also
-        checks the result isn't changed even after the method is
-        invoked twice. Finally checks it is valid for the the
-        statistics spec."""
-        self.assertEqual(self.counter.dump_statistics(),
-                         self._statistics_data)
-        # Idempotency check
-        self.assertEqual(self.counter.dump_statistics(),
-                         self._statistics_data)
-        if self.TEST_SPECFILE_LOCATION:
-            self.assertTrue(isc.config.module_spec_from_file(
-                    self.TEST_SPECFILE_LOCATION).validate_statistics(
-                    False, self._statistics_data))
-        else:
-            self.assertTrue(isc.config.ModuleSpec(
-                    {'module_name': 'Foo',
-                     'statistics': self.counter._statistics._spec}
-                    ).validate_statistics(
-                    False, self._statistics_data))
-
-    def test_perzone_counters(self):
-        # for per-zone counters
-        for name in self.counter._zones_item_list:
-            args = (self._perzone_prefix, TEST_ZONE_NAME_STR, name)
-            if name.find('time_to_') == 0:
-                self.counter.start(*args)
-                self.counter.stop(*args)
-                self.assertGreater(self.counter.get(*args), 0)
-                sec = self.counter.get(*args)
-                for zone_str in (self._entire_server, TEST_ZONE_NAME_STR):
-                    isc.cc.data.set(self._statistics_data,
-                                    '%s/%s/%s' % (args[0], zone_str, name), sec)
-                # twice exec stopper, then second is not changed
-                self.counter.stop(*args)
-                self.assertEqual(self.counter.get(*args), sec)
-            else:
-                self.counter.inc(*args)
-                self.assertEqual(self.counter.get(*args), 1)
-                # checks disable/enable
-                self.counter.disable()
-                self.counter.inc(*args)
-                self.assertEqual(self.counter.get(*args), 1)
-                self.counter.enable()
-                self.counter.inc(*args)
-                self.assertEqual(self.counter.get(*args), 2)
-                for zone_str in (self._entire_server, TEST_ZONE_NAME_STR):
-                    isc.cc.data.set(self._statistics_data,
-                                    '%s/%s/%s' % (args[0], zone_str, name), 2)
-        self.check_dump_statistics()
-
-    def test_xfrrunning_counters(self):
-        # for counters of xfer running
-        _suffix = 'xfr_running'
-        _xfrrunning_names = \
-            isc.config.spec_name_list(self.counter._statistics._spec,
-                                      "", True)
-        for name in _xfrrunning_names:
-            if name.find(_suffix) != 1: continue
-            args = name.split('/')
-            self.counter.inc(*args)
-            self.assertEqual(self.counter.get(*args), 1)
-            self.counter.dec(*args)
-            self.assertEqual(self.counter.get(*args), 0)
-            # checks disable/enable
-            self.counter.disable()
-            self.counter.inc(*args)
-            self.assertEqual(self.counter.get(*args), 0)
-            self.counter.enable()
-            self.counter.inc(*args)
-            self.assertEqual(self.counter.get(*args), 1)
-            self.counter.disable()
-            self.counter.dec(*args)
-            self.assertEqual(self.counter.get(*args), 1)
-            self.counter.enable()
-            self.counter.dec(*args)
-            self.assertEqual(self.counter.get(*args), 0)
-            self._statistics_data[name] = 0
-        self.check_dump_statistics()
-
-    def test_socket_counters(self):
-        # for ipsocket/unixsocket counters
-        _prefix = 'socket/'
-        _socket_names = \
-            isc.config.spec_name_list(self.counter._statistics._spec,
-                                      "", True)
-        for name in _socket_names:
-            if name.find(_prefix) != 0: continue
-            args = name.split('/')
-            self.counter.inc(*args)
-            self.assertEqual(self.counter.get(*args), 1)
-            # checks disable/enable
-            self.counter.disable()
-            self.counter.inc(*args)
-            self.assertEqual(self.counter.get(*args), 1)
-            self.counter.enable()
-            self.counter.inc(*args)
-            self.assertEqual(self.counter.get(*args), 2)
-            isc.cc.data.set(
-                self._statistics_data, '/'.join(args), 2)
-        self.check_dump_statistics()
-
-    def test_undefined_item(self):
-        # test DataNotFoundError raising when specifying item defined
-        # in the specfile
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.counter.inc, '__undefined__')
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.counter.dec, '__undefined__')
-        self.counter.start('__undefined__')
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.counter.stop, '__undefined__')
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.counter.get, '__undefined__')
-
-class TestCounter0(unittest.TestCase, BaseTestCounter):
-    TEST_SPECFILE_LOCATION = None
-    def setUp(self):
-        BaseTestCounter.setUp(self)
-    def tearDown(self):
-        BaseTestCounter.tearDown(self)
-
-class TestCounter1(unittest.TestCase, BaseTestCounter):
-    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec1.spec'
-    def setUp(self):
-        BaseTestCounter.setUp(self)
-    def tearDown(self):
-        BaseTestCounter.tearDown(self)
-
-class TestCounter2(unittest.TestCase, BaseTestCounter):
-    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec2.spec'
-    def setUp(self):
-        BaseTestCounter.setUp(self)
-    def tearDown(self):
-        BaseTestCounter.tearDown(self)
-
-class TestCounter3(unittest.TestCase, BaseTestCounter):
-    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec3.spec'
-    def setUp(self):
-        BaseTestCounter.setUp(self)
-    def tearDown(self):
-        BaseTestCounter.tearDown(self)
-
-if __name__== "__main__":
-    unittest.main()
diff --git a/src/lib/python/isc/statistics/tests/counters_test.py b/src/lib/python/isc/statistics/tests/counters_test.py
new file mode 100644
index 0000000..ff15efc
--- /dev/null
+++ b/src/lib/python/isc/statistics/tests/counters_test.py
@@ -0,0 +1,416 @@
+# Copyright (C) 2012  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.
+
+'''Tests for isc.statistics.counter'''
+
+import unittest
+import threading
+from datetime import timedelta
+import os
+import imp
+import isc.config
+
+TEST_ZONE_NAME_STR = "example.com."
+TESTDATA_SRCDIR = os.getenv("TESTDATASRCDIR")
+
+from isc.statistics import counters
+
+def setup_functor(event, cycle, functor, *args):
+    """Waits until the event is started, and then invokes the functor
+    by times of the cycle with args."""
+    event.wait()
+    for i in range(cycle): functor(*args)
+
+def start_functor(concurrency, number, functor, *args):
+    """Creates the threads of the number and makes them start. Sets
+    the event and waits until these threads are finished."""
+    threads = []
+    event = threading.Event()
+    for i in range(concurrency):
+        threads.append(threading.Thread(\
+                target=setup_functor, \
+                    args=(event, number, functor,) + args))
+    for th in threads: th.start()
+    event.set()
+    for th in threads: th.join()
+
+class TestBasicMethods(unittest.TestCase):
+    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec1.spec'
+
+    def setUp(self):
+        imp.reload(counters)
+        self.counters = counters.Counters(self.TEST_SPECFILE_LOCATION)
+
+    def tearDown(self):
+        self.counters.clear_all()
+
+    def test_clear_counters(self):
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          self.counters.get, 'counter')
+        self.counters.inc('counter')
+        self.assertEqual(self.counters.get('counter'), 1)
+        self.counters.clear_all()
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          self.counters.get, 'counter')
+
+    def test_enablediable(self):
+        self.assertFalse(self.counters._disabled)
+        self.counters.disable()
+        self.assertTrue(self.counters._disabled)
+        self.counters.enable()
+        self.assertFalse(self.counters._disabled)
+
+    def test_add_counter_normal(self):
+        element = {'counter' : 1}
+        self.assertEqual(\
+            counters._add_counter(element, [], 'counter'), 1)
+
+    def test_add_counter_wrongspec(self):
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counters._add_counter,
+                          {}, [], 'counter')
+
+    def test_add_counter_empty(self):
+        self.assertEqual(\
+            counters._add_counter(
+                {},
+                [ { 'item_name' : 'counter',
+                    'item_type' : 'integer',
+                    'item_default' : 0 } ],
+                'counter'), 0)
+
+    def test_add_counter_empty_namedset(self):
+        elem = {}
+        spec = [ { 'item_name': 'dirs',
+                    'item_type': 'named_set',
+                    'named_set_item_spec': {
+                            'item_name': 'dir',
+                            'item_type': 'map',
+                            'map_item_spec': [
+                                { 'item_name': 'counter1',
+                                  'item_type': 'integer',
+                                  'item_default': 0 },
+                                { 'item_name': 'counter2',
+                                  'item_type': 'integer',
+                                  'item_default': 0 } ]}
+                   }]
+        self.assertEqual(\
+            counters._add_counter(elem, spec, 'dirs/foo/counter1'), 0)
+        self.assertEqual(\
+            counters._add_counter(elem, spec, 'dirs/bar/counter2'), 0)
+
+    def test_timer(self):
+        t1 = counters._start_timer()
+        t2 = t1 - timedelta(seconds=1)
+        self.assertEqual((t1 - t2).seconds, 1)
+        elem = {}
+        spec = [{ 'item_name': 'time',
+                  'item_type': 'real',
+                  'item_default': 0.0 }]
+        counters._stop_timer(t2, elem, spec, 'time')
+        self.assertGreater(counters._get_counter(elem,'time'), 1)
+
+    def test_rasing_incrementers(self):
+        """ use Thread"""
+        concurrency = 3    # number of the threads
+        number = 10000     # number of counting per thread
+        counter_name = "counter"
+        timer_name = "seconds"
+        start_time = counters._start_timer()
+        start_functor(concurrency, number, self.counters.inc,
+                      counter_name)
+        counters._stop_timer(start_time,
+                            self.counters._statistics._data,
+                            self.counters._statistics._spec,
+                            timer_name)
+        self.assertEqual(
+            counters._get_counter(self.counters._statistics._data,
+                                 counter_name),
+            concurrency * number)
+        self.assertGreater(
+            counters._get_counter(self.counters._statistics._data,
+                                 timer_name), 0)
+
+    def test_concat(self):
+        # only strings
+        a = ( 'a','b','c','d' )
+        self.assertEqual('a/b/c/d', counters._concat(*a))
+        self.assertEqual('aTbTcTd', counters._concat(*a, sep='T'))
+        self.assertEqual('a\\b\\c\\d', counters._concat(*a, sep='\\'))
+        # mixed with other types
+        b = a + (1,)
+        self.assertRaises(TypeError, counters._concat, *b)
+        b = a + (1.1,)
+        self.assertRaises(TypeError, counters._concat, *b)
+        b = a + ([],)
+        self.assertRaises(TypeError, counters._concat, *b)
+        b = a + ({},)
+        self.assertRaises(TypeError, counters._concat, *b)
+
+class BaseTestCounters():
+
+    def setUp(self):
+        imp.reload(counters)
+        self._statistics_data = {}
+        self.counters = counters.Counters(self.TEST_SPECFILE_LOCATION)
+        self._entire_server    = self.counters._entire_server
+        self._perzone_prefix   = self.counters._perzone_prefix
+
+    def tearDown(self):
+        self.counters.clear_all()
+
+    def check_get_statistics(self):
+        """Checks no differences between the value returned from
+        get_statistics() and locally collected statistics data. Also
+        checks the result isn't changed even after the method is
+        invoked twice. Finally checks it is valid for the the
+        statistics spec."""
+        self.assertEqual(self.counters.get_statistics(),
+                         self._statistics_data)
+        # Idempotency check
+        self.assertEqual(self.counters.get_statistics(),
+                         self._statistics_data)
+        if self.TEST_SPECFILE_LOCATION:
+            self.assertTrue(isc.config.module_spec_from_file(
+                    self.TEST_SPECFILE_LOCATION).validate_statistics(
+                    False, self._statistics_data))
+        else:
+            self.assertTrue(isc.config.ModuleSpec(
+                    {'module_name': 'Foo',
+                     'statistics': self.counters._statistics._spec}
+                    ).validate_statistics(
+                    False, self._statistics_data))
+
+    def test_perzone_counters(self):
+        # for per-zone counters
+        for name in self.counters._zones_item_list:
+            args = (self._perzone_prefix, TEST_ZONE_NAME_STR, name)
+            if name.find('time_to_') == 0:
+                self.counters.start_timer(*args)
+                self.counters.stop_timer(*args)
+                self.assertGreater(self.counters.get(*args), 0)
+                sec = self.counters.get(*args)
+                for zone_str in (self._entire_server, TEST_ZONE_NAME_STR):
+                    isc.cc.data.set(self._statistics_data,
+                                    '%s/%s/%s' % (args[0], zone_str, name), sec)
+                # twice exec stopper, then second is not changed
+                self.counters.stop_timer(*args)
+                self.assertEqual(self.counters.get(*args), sec)
+            else:
+                self.counters.inc(*args)
+                self.assertEqual(self.counters.get(*args), 1)
+                # checks disable/enable
+                self.counters.disable()
+                self.counters.inc(*args)
+                self.assertEqual(self.counters.get(*args), 1)
+                self.counters.enable()
+                self.counters.inc(*args)
+                self.assertEqual(self.counters.get(*args), 2)
+                for zone_str in (self._entire_server, TEST_ZONE_NAME_STR):
+                    isc.cc.data.set(self._statistics_data,
+                                    '%s/%s/%s' % (args[0], zone_str, name), 2)
+        self.check_get_statistics()
+
+    def test_xfrrunning_counters(self):
+        # for counters of xfer running
+        _suffix = 'xfr_running'
+        _xfrrunning_names = \
+            isc.config.spec_name_list(self.counters._statistics._spec,
+                                      "", True)
+        for name in _xfrrunning_names:
+            if name.find(_suffix) != 1: continue
+            args = name.split('/')
+            self.counters.inc(*args)
+            self.assertEqual(self.counters.get(*args), 1)
+            self.counters.dec(*args)
+            self.assertEqual(self.counters.get(*args), 0)
+            # checks disable/enable
+            self.counters.disable()
+            self.counters.inc(*args)
+            self.assertEqual(self.counters.get(*args), 0)
+            self.counters.enable()
+            self.counters.inc(*args)
+            self.assertEqual(self.counters.get(*args), 1)
+            self.counters.disable()
+            self.counters.dec(*args)
+            self.assertEqual(self.counters.get(*args), 1)
+            self.counters.enable()
+            self.counters.dec(*args)
+            self.assertEqual(self.counters.get(*args), 0)
+            self._statistics_data[name] = 0
+        self.check_get_statistics()
+
+    def test_socket_counters(self):
+        # for ipsocket/unixsocket counters
+        _prefix = 'socket/'
+        _socket_names = \
+            isc.config.spec_name_list(self.counters._statistics._spec,
+                                      "", True)
+        for name in _socket_names:
+            if name.find(_prefix) != 0: continue
+            args = name.split('/')
+            self.counters.inc(*args)
+            self.assertEqual(self.counters.get(*args), 1)
+            # checks disable/enable
+            self.counters.disable()
+            self.counters.inc(*args)
+            self.assertEqual(self.counters.get(*args), 1)
+            self.counters.enable()
+            self.counters.inc(*args)
+            self.assertEqual(self.counters.get(*args), 2)
+            isc.cc.data.set(
+                self._statistics_data, '/'.join(args), 2)
+        self.check_get_statistics()
+
+    def test_undefined_item(self):
+        # test DataNotFoundError raising when specifying item defined
+        # in the specfile
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          self.counters.inc, '__undefined__')
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          self.counters.dec, '__undefined__')
+        self.counters.start_timer('__undefined__')
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          self.counters.stop_timer, '__undefined__')
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          self.counters.get, '__undefined__')
+
+class TestCounters0(unittest.TestCase, BaseTestCounters):
+    TEST_SPECFILE_LOCATION = None
+    def setUp(self):
+        BaseTestCounters.setUp(self)
+    def tearDown(self):
+        BaseTestCounters.tearDown(self)
+
+class TestCounters1(unittest.TestCase, BaseTestCounters):
+    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec1.spec'
+    def setUp(self):
+        BaseTestCounters.setUp(self)
+    def tearDown(self):
+        BaseTestCounters.tearDown(self)
+
+class TestCounters2(unittest.TestCase, BaseTestCounters):
+    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec2.spec'
+    def setUp(self):
+        BaseTestCounters.setUp(self)
+    def tearDown(self):
+        BaseTestCounters.tearDown(self)
+
+class TestCounters3(unittest.TestCase, BaseTestCounters):
+    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec3.spec'
+    @classmethod
+    def setUpClass(cls):
+        imp.reload(counters)
+    def setUp(self):
+        BaseTestCounters.setUp(self)
+    def tearDown(self):
+        BaseTestCounters.tearDown(self)
+
+class BaseDummyModule():
+    """A base dummy class"""
+    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec2.spec'
+    def __init__(self):
+        self.counters = counters.Counters(self.TEST_SPECFILE_LOCATION)
+
+    def get_counters(self):
+        return self.counters.get_statistics()
+
+    def clear_counters(self):
+        self.counters.clear_all()
+
+class DummyNotifyOut(BaseDummyModule):
+    """A dummy class equivalent to notify.notify_out.NotifyOut"""
+    def __init__(self):
+        self.counters = counters.Counters()
+
+    def inc_counters(self):
+        """increments counters"""
+        self.counters.inc('zones', TEST_ZONE_NAME_STR, 'notifyoutv4')
+        self.counters.inc('zones', TEST_ZONE_NAME_STR, 'notifyoutv6')
+
+class DummyXfroutSession(BaseDummyModule):
+    """A dummy class equivalent to XfroutSession in b10-xfrout"""
+    def inc_counters(self):
+        """increments counters"""
+        self.counters.inc('zones', TEST_ZONE_NAME_STR, 'xfrreqdone')
+        self.counters.inc('zones', TEST_ZONE_NAME_STR, 'xfrrej')
+        self.counters.inc('axfr_running')
+        self.counters.inc('ixfr_running')
+        self.counters.dec('axfr_running')
+        self.counters.dec('ixfr_running')
+
+class DummyUnixSockServer(BaseDummyModule):
+    """A dummy class equivalent to UnixSockServer in b10-xfrout"""
+    def inc_counters(self):
+        """increments counters"""
+        self.counters.inc('socket', 'unixdomain', 'open')
+        self.counters.inc('socket', 'unixdomain', 'close')
+
+class DummyXfroutServer(BaseDummyModule):
+    """A dummy class equivalent to XfroutServer in b10-xfrout"""
+    def __init__(self):
+        super().__init__()
+        self.xfrout_sess = DummyXfroutSession()
+        self.unix_socket_server = DummyUnixSockServer()
+        self.notifier = DummyNotifyOut()
+
+    def inc_counters(self):
+        self.xfrout_sess.inc_counters()
+        self.unix_socket_server.inc_counters()
+        self.notifier.inc_counters()
+
+class TestDummyNotifyOut(unittest.TestCase):
+    """Tests counters are incremented in which the spec file is not
+    loaded"""
+    def setUp(self):
+        imp.reload(counters)
+        self.notifier = DummyNotifyOut()
+        self.notifier.inc_counters()
+
+    def tearDown(self):
+        self.notifier.clear_counters()
+
+    def test_counters(self):
+        self.assertEqual(
+            {'zones': {'_SERVER_': {'notifyoutv4': 1, 'notifyoutv6': 1},
+                       TEST_ZONE_NAME_STR: {'notifyoutv4': 1, 'notifyoutv6': 1}}},
+            self.notifier.get_counters())
+
+class TestDummyXfroutServer(unittest.TestCase):
+    """Tests counters are incremented or decremented in which the same
+    spec file is multiply loaded in each child class"""
+    def setUp(self):
+        imp.reload(counters)
+        self.xfrout_server = DummyXfroutServer()
+        self.xfrout_server.inc_counters()
+
+    def tearDown(self):
+        self.xfrout_server.clear_counters()
+
+    def test_counters(self):
+        self.assertEqual(
+            {'axfr_running': 0, 'ixfr_running': 0,
+             'socket': {'unixdomain': {'open': 1, 'close': 1}},
+             'zones': {'_SERVER_': {'notifyoutv4': 1,
+                                    'notifyoutv6': 1,
+                                    'xfrrej': 1, 'xfrreqdone': 1},
+                       TEST_ZONE_NAME_STR: {'notifyoutv4': 1,
+                                        'notifyoutv6': 1,
+                                        'xfrrej': 1,
+                                        'xfrreqdone': 1}}},
+            self.xfrout_server.get_counters())
+
+if __name__== "__main__":
+    unittest.main()



More information about the bind10-changes mailing list