BIND 10 trac2225_statistics, updated. c6aa9a4c2e17c51b28b91cef5b773b935caf317e [2225_statistics] remove unused paths

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Nov 26 09:59:48 UTC 2012


The branch, trac2225_statistics has been updated
  discards  22d6e85f4df97b8ffcfbea8b5ca81edd2df219d4 (commit)
       via  c6aa9a4c2e17c51b28b91cef5b773b935caf317e (commit)
       via  7dee66ffe8b7e3f5c49c20608f0f38508d861ced (commit)
       via  117645fa11500c467045a380dc41d6999518c5dd (commit)
       via  0ca61cffc9fb7f55789f1db88a41a9a5c1f5d34f (commit)
       via  83e4b764a988e7774312ff75e0623bcff66f7009 (commit)
       via  69bc301dec66ffd80960a45c882fd50c498121cc (commit)
       via  2ba2f0269087e5dae4640091e711e4f2964d2fa3 (commit)
       via  2f29fad03bb3c9885d0bcf84d39102e6ee902830 (commit)
       via  a52d10a93a24f736ed4112ea76778a61407a0a03 (commit)
       via  123f5a29a7d5c40b0ca7a6ebe8af3b3790c29eca (commit)
       via  525ca6149da521a00d02895a5184deef7f8359f9 (commit)
       via  889dc09ad441f3e5a3ce2170fba402db258c2a08 (commit)
       via  23818a5f2f8e5c68300b11ba8e71178dee8ad794 (commit)
       via  949f8945514ac7d422a68f34d7cbf097c864bef8 (commit)
       via  57e46e4378c4d8b8dd39cca093500672fa124e42 (commit)
       via  b89a21c32f1dbea865f632cf517cc335b9b70919 (commit)
       via  e0098c29f519e84214d012cd5d0ae7f25aa40f73 (commit)
       via  977568b91a6595c7d2fd8a618d5f15783962d908 (commit)
       via  e5e001e23347199841f14f2c0880e2f5f304bd0f (commit)
       via  8f73baf041ffda0351e5b9072e1ea43401ce497e (commit)
       via  c38d780b1390e3dc4c3bf702f6c059a8c3de3406 (commit)
       via  5cc65af294ab05bba59614684d71d450eed57c37 (commit)
       via  74aa99552605bb7639719501807a13c393e560b9 (commit)
       via  f950449fc2ffc2e31672ab99d0e432c3b3efc4bc (commit)
       via  62c7075662a25c06ee6d877404b8ddad16dd41ee (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 (22d6e85f4df97b8ffcfbea8b5ca81edd2df219d4)
            \
             N -- N -- N (c6aa9a4c2e17c51b28b91cef5b773b935caf317e)

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 c6aa9a4c2e17c51b28b91cef5b773b935caf317e
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 16:49:45 2012 +0900

    [2225_statistics] remove unused paths

commit 7dee66ffe8b7e3f5c49c20608f0f38508d861ced
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 14:12:09 2012 +0900

    [2225_statistics] update counter class names in docstring

commit 117645fa11500c467045a380dc41d6999518c5dd
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 13:35:11 2012 +0900

    [2225_statistics] move init() into the Counter class

commit 0ca61cffc9fb7f55789f1db88a41a9a5c1f5d34f
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Nov 22 17:39:39 2012 +0900

    [2225_statistics] move constants which are used in test_rasing_incrementers()

commit 83e4b764a988e7774312ff75e0623bcff66f7009
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Nov 22 17:32:45 2012 +0900

    [2225_statistics] add tearDown()
    
    clear statistics data when every test is finished

commit 69bc301dec66ffd80960a45c882fd50c498121cc
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 17:03:16 2012 +0900

    [2225_statistics] reload counter module in each testcase

commit 2ba2f0269087e5dae4640091e711e4f2964d2fa3
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 17:09:38 2012 +0900

    [2225_statistics] add B10_FROM_SOURCE

commit 2f29fad03bb3c9885d0bcf84d39102e6ee902830
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 17:09:16 2012 +0900

    [2225_statistics] rename class name and add TEST_SPECFILE_LOCATION

commit a52d10a93a24f736ed4112ea76778a61407a0a03
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 16:56:56 2012 +0900

    [2225_statistics] add some test specfiles

commit 123f5a29a7d5c40b0ca7a6ebe8af3b3790c29eca
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Nov 22 17:14:21 2012 +0900

    [2225_statistics] merge TestXfroutCounter and TestXfrinCounter into BaseTestCounter

commit 525ca6149da521a00d02895a5184deef7f8359f9
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Nov 22 14:15:53 2012 +0900

    [2225_statistics] open specfile in Counter class

commit 889dc09ad441f3e5a3ce2170fba402db258c2a08
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Nov 22 13:34:18 2012 +0900

    [2225_statistics] add _parse_stats_spec() to get each list of names on statistics spec

commit 23818a5f2f8e5c68300b11ba8e71178dee8ad794
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Nov 21 11:48:16 2012 +0900

    [2225_statistics] set methods in Counter

commit 949f8945514ac7d422a68f34d7cbf097c864bef8
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Nov 21 11:39:06 2012 +0900

    [2225_statistics] merge two concrete methods and parameters into _Counter()

commit 57e46e4378c4d8b8dd39cca093500672fa124e42
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Nov 26 13:59:57 2012 +0900

    [2225_statistics] make Counter class hidden(rename Counter to _Counter), add Counter class, and move empty methods in it.

commit b89a21c32f1dbea865f632cf517cc335b9b70919
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Sep 28 16:04:00 2012 +0900

    [2300] added a test method test_ipsocket_counters() for testing the incrementers of the socket counters

commit e0098c29f519e84214d012cd5d0ae7f25aa40f73
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Sep 28 16:02:38 2012 +0900

    [2300] added a method _create_ipsocket_functors() for creating incrementers of the socket counters

commit 977568b91a6595c7d2fd8a618d5f15783962d908
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Sep 19 17:45:37 2012 +0900

    [2274] updated the BaseTestXfrCounter class for testing new statistics items
    
    - moved up test_xfrrunning_counters() to the BaseTestXfrCounter class
    
    - added a new variable holding a name list from target counter class

commit e5e001e23347199841f14f2c0880e2f5f304bd0f
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Sep 19 17:51:23 2012 +0900

    [2274] updated the XfrinCounter class for adding new statistics items
    
    - moved up _create_xfrrunning_functors() to the Counter class for sharing
    
    - added a name list for new statistics items

commit 8f73baf041ffda0351e5b9072e1ea43401ce497e
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Sep 28 11:47:55 2012 +0900

    [2252] corrected the wrong comment of the methods

commit c38d780b1390e3dc4c3bf702f6c059a8c3de3406
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Sep 28 11:46:26 2012 +0900

    [2225] removed duplicate assignment

commit 5cc65af294ab05bba59614684d71d450eed57c37
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Sep 28 11:46:00 2012 +0900

    [2252] corrected the order

commit 74aa99552605bb7639719501807a13c393e560b9
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Sep 12 16:30:55 2012 +0900

    [2252] added tests for the XfrinCounter class
    
     - added a test class TestXfroutCounter for the XfrinCounter class
     - Common methods were moved out of the test class
     - added tests for the base class Counter
     - added a base class BaseTestXfrCounter for handling common tests
       between Xfrin and Xfrout

commit f950449fc2ffc2e31672ab99d0e432c3b3efc4bc
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Sep 12 16:30:39 2012 +0900

    [2252] added path of xfrin into PYTHONPATH and removed unnecessary TESTDATASRCDIR

commit 62c7075662a25c06ee6d877404b8ddad16dd41ee
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Sep 12 16:30:00 2012 +0900

    [2252] added XfrinCounter class
    
     - added XfrinCounter class
     - Common methods between Xfrout and Xfrin are gotten rid of out of
       each class, which is incrementer, decrementer, etc.
     - added an abstract class for concrete XfroutCounter and  XfrinCounter
       classes, in which common methods were defined
     - added per-zone counters into XfrinCounter
     - added per-zone timer handlers into XfrinCounter, which can start or
       stop a timer

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

Summary of changes:
 src/bin/xfrout/xfrout.spec.pre.in                  |  104 ----
 src/lib/python/isc/statistics/counter.py           |  553 ++++++++++++--------
 src/lib/python/isc/statistics/tests/Makefile.am    |    8 +-
 .../python/isc/statistics/tests/counter_test.py    |  360 +++++++++----
 .../isc/statistics/tests/testdata/test_spec1.spec  |   26 +
 .../isc/statistics/tests/testdata/test_spec2.spec  |  187 +++++++
 .../isc/statistics/tests/testdata/test_spec3.spec  |  382 ++++++++++++++
 7 files changed, 1188 insertions(+), 432 deletions(-)
 create mode 100644 src/lib/python/isc/statistics/tests/testdata/test_spec1.spec
 create mode 100644 src/lib/python/isc/statistics/tests/testdata/test_spec2.spec
 create mode 100644 src/lib/python/isc/statistics/tests/testdata/test_spec3.spec

-----------------------------------------------------------------------
diff --git a/src/bin/xfrout/xfrout.spec.pre.in b/src/bin/xfrout/xfrout.spec.pre.in
index efca403..1d24be2 100644
--- a/src/bin/xfrout/xfrout.spec.pre.in
+++ b/src/bin/xfrout/xfrout.spec.pre.in
@@ -188,110 +188,6 @@
           "item_default": 0,
           "item_title": "AXFR running",
           "item_description": "Number of AXFRs in progress"
-        },
-        {
-          "item_name": "socket",
-          "item_type": "map",
-          "item_optional": false,
-          "item_default": {
-            "unixdomain": {
-              "open": 0,
-              "openfail": 0,
-              "close": 0,
-              "bindfail": 0,
-              "acceptfail": 0,
-              "accept": 0,
-              "senderr": 0,
-              "recverr": 0
-            }
-          },
-          "item_title": "Socket",
-          "item_description": "Socket",
-          "map_item_spec": [
-            {
-              "item_name": "unixdomain",
-              "item_type": "map",
-              "item_optional": false,
-              "item_default": {
-                "open": 0,
-                "openfail": 0,
-                "close": 0,
-                "bindfail": 0,
-                "acceptfail": 0,
-                "accept": 0,
-                "senderr": 0,
-                "recverr": 0
-              },
-              "item_title": "Unix Domain",
-              "item_description": "Unix Domain",
-              "map_item_spec": [
-                {
-                  "item_name": "open",
-                  "item_type": "integer",
-                  "item_optional": false,
-                  "item_default": 0,
-                  "item_title": "Open",
-                  "item_description": "Unix Domain sockets opened successfully"
-                },
-                {
-                  "item_name": "openfail",
-                  "item_type": "integer",
-                  "item_optional": false,
-                  "item_default": 0,
-                  "item_title": "Open failures",
-                  "item_description": "Unix Domain sockets open failures"
-                },
-                {
-                  "item_name": "close",
-                  "item_type": "integer",
-                  "item_optional": false,
-                  "item_default": 0,
-                  "item_title": "Close",
-                  "item_description": "Unix Domain sockets closed"
-                },
-                {
-                  "item_name": "bindfail",
-                  "item_type": "integer",
-                  "item_optional": false,
-                  "item_default": 0,
-                  "item_title": "Bind failures",
-                  "item_description": "Unix Domain sockets bind failures"
-                },
-                {
-                  "item_name": "acceptfail",
-                  "item_type": "integer",
-                  "item_optional": false,
-                  "item_default": 0,
-                  "item_title": "Accept failures",
-                  "item_description": "Unix Domain sockets incoming accept failures"
-                },
-                {
-                  "item_name": "accept",
-                  "item_type": "integer",
-                  "item_optional": false,
-                  "item_default": 0,
-                  "item_title": "Accept",
-                  "item_description": "Unix Domain sockets incoming connections successfully accepted"
-                },
-                {
-                  "item_name": "senderr",
-                  "item_type": "integer",
-                  "item_optional": false,
-                  "item_default": 0,
-                  "item_title": "Send errors",
-                  "item_description": "Unix Domain sockets send errors"
-                },
-                {
-                  "item_name": "recverr",
-                  "item_type": "integer",
-                  "item_optional": false,
-                  "item_default": 0,
-                  "item_title": "Receive errors",
-                  "item_description": "Unix Domain sockets receive errors"
-                }
-              ]
-            }
-          ]
         }
       ]
   }
diff --git a/src/lib/python/isc/statistics/counter.py b/src/lib/python/isc/statistics/counter.py
index bb1fb98..5654542 100644
--- a/src/lib/python/isc/statistics/counter.py
+++ b/src/lib/python/isc/statistics/counter.py
@@ -20,36 +20,35 @@ 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.
 
-  import counter
-  counter.init(SPECFILE_LOCATION)
+  from isc.statistics import Counter
+  Counter.init(SPECFILE_LOCATION)
 
-The first argument of counter.init() is required, which is the
+The first argument of Counter.init() is required, 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 can
-be dynamically created: counter.inc_xfrreqdone(),
-counter.get_xfrreqdone(). Since these methods requires the string of
+be dynamically created: Counter.inc_xfrreqdone(),
+Counter.get_xfrreqdone(). Since these methods requires the string of
 the zone name in the first argument, in the b10-xfrout,
 
-  counter.inc_xfrreqdone(zone_name)
+  Counter.inc_xfrreqdone(zone_name)
 
 then the xfrreqdone counter corresponding to zone_name was
 incremented. For getting the current number of this counter, we can do
 this,
 
-  number = counter.get_xfrreqdone(zone_name)
+  number = Counter.get_xfrreqdone(zone_name)
 
 then the current number was obtained and set in the above variable
 `number`. Such a getter method would be mainly used for unittesting.
-These dynamic accessor are defined in detail in the concrete class
-XfroutCounter. In other example, regarding the item `axfr_running`,
+In other example, regarding the item `axfr_running`,
 the decrementer method is also created:
-counter.dec_axfr_running(). This method is used for decrementing the
+Counter.dec_axfr_running(). This method is used for decrementing the
 counter number.  Regarding the item `axfr_running`, an argument like
 zone name is not required.
 
-  counter.dec_axfr_running()
+  Counter.dec_axfr_running()
 
 These accessors are effective in other module. For example, in case
 that this module `counter.py` is once imported in such a main module
@@ -57,7 +56,7 @@ as b10-xfrout, Regarding the item `notifyoutv4`, the incrementer
 inc_notifyoutv4() can be invoked via other module like notify_out.py,
 which is firstly imported in the main module.
 
-  counter.inc_notifyoutv4(zone_name)
+  Counter.inc_notifyoutv4(zone_name)
 
 In this example this is for incrementing the counter of the item
 notifyoutv4. Thus, such statement can be also written in the other
@@ -72,63 +71,104 @@ future. For adding or modifying such accessor, we need to implement in
 """
 import threading
 import isc.config
+from datetime import datetime
 
+# container of a counter object
 _COUNTER = None
 
-def init(spec_file_name):
-    """A creator method for a counter class. It creates a counter
-    object by the module name of the given spec file. An argument is a
-    specification file name."""
-    module_spec = isc.config.module_spec_from_file(spec_file_name)
-    class_name = '%sCounter' % module_spec.get_module_name()
-    global _COUNTER
-    if issubclass(_COUNTER.__class__, Counter):
-        # already loaded
-        return _COUNTER
-    # create an instance once
-    _COUNTER = globals()[class_name](module_spec)
-    # make globals
-    globals().update(_COUNTER._to_global)
-    return _COUNTER
-
-# These method are dummies for notify_out in case XfroutCounter is not
-# loaded.
-def inc_notifyoutv4(self, arg):
-    """An empty method to be disclosed"""
-    pass
-def inc_notifyoutv6(self, arg):
-    """An empty method to be disclosed"""
-    pass
+# 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 Counter():
-    """A basic counter class for concrete classes"""
-    _statistics_spec = {}
-    _statistics_data = {}
-    _disabled = False
-    _rlock = threading.RLock()
-    _to_global = {}
-
-    def __init__(self, module_spec):
-        self._statistics_spec = module_spec.get_statistics_spec()
-        self._to_global['clear_counters'] = self.clear_counters
-        self._to_global['disable'] = self.disable
-        self._to_global['enable'] = self.enable
-
-    def clear_counters(self):
-        """clears all statistics data"""
-        with self._rlock:
-            self._statistics_data = {}
-
-    def disable(self):
-        """disables incrementing/decrementing counters"""
-        self._disabled = True
+    """A counter class"""
+    def init(spec_file_name):
+        """A creator method for a counter class. It creates a counter
+        object by the module name of the given spec file. An argument is a
+        specification file name."""
+        global _COUNTER
+        if isinstance(_COUNTER, _Counter):
+            # already loaded
+            return _COUNTER
+        # create an instance once
+        _COUNTER = _Counter(spec_file_name)
+        # set methods in Counter
+        for (k, v) in _COUNTER._to_global.items():
+            setattr(Counter, k, v)
+        return _COUNTER
 
-    def enable(self):
-        """enables incrementing/decrementing counters"""
-        self._disabled = False
+    # These method are dummies for isc.notify.notify_out.
+    def inc_notifyoutv4(arg):
+        """An empty method to be disclosed"""
+        pass
+    def inc_notifyoutv6(arg):
+        """An empty method to be disclosed"""
+        pass
 
-class XfroutCounter(Counter):
-    """A module for holding all statistics counters of Xfrout. The
+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:
@@ -137,6 +177,16 @@ class XfroutCounter(Counter):
         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
@@ -147,6 +197,20 @@ class XfroutCounter(Counter):
         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
@@ -155,209 +219,252 @@ class XfroutCounter(Counter):
     _entire_server = '_SERVER_'
     # zone names are contained under this dirname in the spec file.
     _perzone_prefix = 'zones'
-    _xfrrunning_names = []
-    _unixsocket_names = []
-
-    def __init__(self, module_spec):
-        Counter.__init__(self, module_spec)
-        self._xfrrunning_names = [ \
-            n for n in \
-                isc.config.spec_name_list(self._statistics_spec) \
-                if 'xfr_running' in n ]
-        self._unixsocket_names = [ \
-            n.split('/')[-1] for n in \
-                isc.config.spec_name_list(\
-                self._statistics_spec, "", True) \
-                if n.find('socket/unixdomain/') == 0 ]
+
+    def __init__(self, spec_file_name):
+        # for exporting to the global scope
+        self._to_global = {}
+        self._statistics_spec = {}
+        self._statistics_data = {}
+        self._zones_item_list = []
+        self._xfrrunning_names = []
+        self._unixsocket_names = []
+        self._start_time = {}
+        self._disabled = False
+        self._rlock = threading.RLock()
+        self._module_spec = \
+            isc.config.module_spec_from_file(spec_file_name)
+        self._statistics_spec = \
+            self._module_spec.get_statistics_spec()
+        self._parse_stats_spec()
         self._create_perzone_functors()
+        self._create_perzone_timer_functors()
         self._create_xfrrunning_functors()
         self._create_unixsocket_functors()
-        self._to_global['dump_default_statistics'] = \
-            self.dump_default_statistics
+        self._create_ipsocket_functors()
+        self._to_global['clear_counters'] = self.clear_counters
+        self._to_global['disable'] = self.disable
+        self._to_global['enable'] = self.enable
         self._to_global['dump_statistics'] = self.dump_statistics
 
+    def _parse_stats_spec(self):
+        """Gets each list of names on 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'])
+        self._xfrrunning_names = [
+            n for n in isc.config.spec_name_list\
+                (self._statistics_spec) \
+                if n.find('xfr_running') == 1 \
+                or n.find('xfr_deferred') == 1 \
+                or n.find('soa_in_progress') == 0 ]
+        self._unixsocket_names = [ \
+            n.split('/')[-1] for n in \
+                isc.config.spec_name_list(
+                self._statistics_spec, "", True) \
+                if n.find('socket/unixdomain/') == 0 ]
+        self._ipsocket_names = [ \
+            (n.split('/')[-3], n.split('/')[-1]) for n in \
+                isc.config.spec_name_list(
+                self._statistics_spec, "", True) \
+                if n.find('socket/ipv4/tcp/') == 0 \
+                or n.find('socket/ipv6/tcp/') == 0 ]
+
+    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 _incrementer(self, identifier, step=1):
+        """A per-zone incrementer for counter_name. Locks the
+        thread because it is considered to be invoked by a
+        multi-threading caller."""
+        if self._disabled: return
+        with self._rlock:
+            _inc_counter(self._statistics_data,
+                         self._statistics_spec,
+                         identifier, step)
+
+    def _decrementer(self, identifier, step=-1):
+        """A decrementer for axfr or ixfr running. Locks the
+        thread because it is considered to be invoked by a
+        multi-threading caller."""
+        self._incrementer(identifier, step)
+
+    def _getter(self, identifier):
+        """A getter method for perzone counters"""
+        return _get_counter(self._statistics_data, identifier)
+
+    def _starttimer(self, identifier):
+        """Sets the value returned from _start_timer() as a value of
+        the identifier in the self._start_time which is dict-type"""
+        isc.cc.data.set(self._start_time, identifier, _start_timer())
+
+    def _stoptimer(self, identifier):
+        """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. If DataNotFoundError is
+        raised while invoking _stop_timer(), it stops setting and
+        ignores the exception."""
+        try:
+            _stop_timer(
+                isc.cc.data.find(self._start_time, identifier),
+                self._statistics_data,
+                self._statistics_spec,
+                identifier)
+            del isc.cc.data.find(
+                self._start_time,
+                '/'.join(identifier.split('/')[0:-1]))\
+                [identifier.split('/')[-1]]
+        except isc.cc.data.DataNotFoundError:
+            # do not set end time if it's not started
+            pass
+
     def _create_perzone_functors(self):
         """Creates increment method of each per-zone counter based on
         the spec file. Incrementer can be accessed by name
         "inc_${item_name}".Incrementers are passed to the
-        XfroutSession and NotifyOut class as counter handlers."""
-        # add a new element under the named_set item for the zone
-        zones_spec = isc.config.find_spec_part(
-            self._statistics_spec, self._perzone_prefix)
-        item_list =  isc.config.spec_name_list(\
-            zones_spec['named_set_item_spec']['map_item_spec'])
-        # can be accessed by the name 'inc_xxx'
-        for item in item_list:
+        XfrinConnection class as counter handlers."""
+        for item in self._zones_item_list:
+            if item.find('time_to_') == 0: continue
             def __incrementer(zone_name, counter_name=item, step=1):
-                """A per-zone incrementer for counter_name. Locks the
-                thread because it is considered to be invoked by a
-                multi-threading caller."""
-                if self._disabled: return
-                with self._rlock:
-                    self._add_perzone_counter(zone_name)
-                    self._statistics_data[self._perzone_prefix]\
-                        [zone_name][counter_name] += step
+                """A per-zone incrementer for counter_name."""
+                self._incrementer(
+                    '%s/%s/%s' % \
+                        (self._perzone_prefix, zone_name, counter_name),
+                    step)
             def __getter(zone_name, counter_name=item):
                 """A getter method for perzone counters"""
-                return isc.cc.data.find(
-                    self._statistics_data,
-                    '%s/%s/%s' % ( self._perzone_prefix,
-                                   zone_name,
-                                   counter_name )
-                    )
+                return self._getter(
+                    '%s/%s/%s' % \
+                        (self._perzone_prefix, zone_name, counter_name))
             self._to_global['inc_%s' % item] = __incrementer
             self._to_global['get_%s' % item] = __getter
 
+    def _create_perzone_timer_functors(self):
+        """Creates timer method of each per-zone counter based on the
+        spec file. Starter of the timer can be accessed by the name
+        "start_${item_name}".  Stopper of the timer can be accessed by
+        the name "stop_${item_name}".  These starter and stopper are
+        passed to the XfrinConnection class as timer handlers."""
+        for item in self._zones_item_list:
+            if item.find('time_to_') == -1: continue
+            def __getter(zone_name, counter_name=item):
+                """A getter method for perzone timer. A zone name in
+                string is required in argument."""
+                return self._getter(
+                    '%s/%s/%s' % \
+                        (self._perzone_prefix, zone_name, counter_name))
+            def __starttimer(zone_name, counter_name=item):
+                """A starter method for perzone timer. A zone name in
+                string is required in argument."""
+                self._starttimer(
+                    '%s/%s/%s' % \
+                        (self._perzone_prefix, zone_name, counter_name))
+            def __stoptimer(zone_name, counter_name=item):
+                """A stopper method for perzone timer. A zone name in
+                string is required in argument."""
+                self._stoptimer(
+                    '%s/%s/%s' % \
+                        (self._perzone_prefix, zone_name, counter_name))
+            self._to_global['start_%s' % item] = __starttimer
+            self._to_global['stop_%s' % item] = __stoptimer
+            self._to_global['get_%s' % item] = __getter
+
     def _create_xfrrunning_functors(self):
         """Creates increment/decrement method of (a|i)xfr_running
         based on the spec file. Incrementer can be accessed by name
         "inc_${item_name}". Decrementer can be accessed by name
         "dec_${item_name}". Both of them are passed to the
         XfroutSession as counter handlers."""
-        # can be accessed by the name 'inc_xxx' or 'dec_xxx'
         for item in self._xfrrunning_names:
             def __incrementer(counter_name=item, step=1):
-                """A incrementer for axfr or ixfr running. Locks the
-                thread because it is considered to be invoked by a
-                multi-threading caller."""
-                if self._disabled: return
-                with self._rlock:
-                    self._add_xfrrunning_counter(counter_name)
-                    self._statistics_data[counter_name] += step
+                """A incrementer for axfr or ixfr running."""
+                self._incrementer(counter_name, step)
             def __decrementer(counter_name=item, step=-1):
-                """A decrementer for axfr or ixfr running. Locks the
-                thread because it is considered to be invoked by a
-                multi-threading caller."""
-                if self._disabled: return
-                with self._rlock:
-                    self._statistics_data[counter_name] += step
+                """A decrementer for axfr or ixfr running."""
+                self._decrementer(counter_name, step)
             def __getter(counter_name=item):
                 """A getter method for xfr_running counters"""
-                return isc.cc.data.find(
-                        self._statistics_data, counter_name )
+                return self._getter(counter_name)
             self._to_global['inc_%s' % item] = __incrementer
             self._to_global['dec_%s' % item] = __decrementer
             self._to_global['get_%s' % item] = __getter
 
-    def _create_unixsocket_functors(self):
-        """Creates increment/decrement method of (a|i)xfr_running
-        based on the spec file. Incrementer can be accessed by name
-        "inc_${item_name}". Decrementer can be accessed by name
-        "dec_${item_name}". Both of them are passed to the
-        XfroutSession as counter handlers."""
-        # can be accessed by the name 'inc_xxx' or 'dec_xxx'
-        for item in self._unixsocket_names:
-            def __incrementer(counter_name=item, step=1):
-                """A incrementer for axfr or ixfr running. Locks the
-                thread because it is considered to be invoked by a
-                multi-threading caller."""
-                if self._disabled: return
-                with self._rlock:
-                    self._add_unixsocket_counter(counter_name)
-                    self._statistics_data['socket']['unixdomain']\
-                       [counter_name] += step
-            def __getter(counter_name=item):
-                """A getter method for unixsockets counters"""
-                return isc.cc.data.find(
-                    self._statistics_data,
-                    'socket/unixdomain/%s' % counter_name )
-            self._to_global['inc_unixsocket_%s' % item] = __incrementer
-            self._to_global['get_unixsocket_%s' % item] = __getter
-
-    def _add_perzone_counter(self, zone):
-        """Adds a named_set-type counter for each zone name."""
-        try:
-            self._statistics_data[self._perzone_prefix][zone]
-        except KeyError:
-            # add a new element under the named_set item for the zone
-            map_spec = isc.config.find_spec_part(
-                self._statistics_spec, '%s/%s' % \
-                    (self._perzone_prefix, zone))['map_item_spec']
-            id_list =  isc.config.spec_name_list(map_spec)
-            for id_ in id_list:
-                spec = isc.config.find_spec_part(map_spec, id_)
-                isc.cc.data.set(self._statistics_data,
-                                '%s/%s/%s' % \
-                                    (self._perzone_prefix, zone, id_),
-                                spec['item_default'])
-
-    def _add_xfrrunning_counter(self, counter_name):
-        """Adds a counter for counting (a|i)xfr_running"""
-        try:
-            self._statistics_data[counter_name]
-        except KeyError:
-            # examines the names of xfer running
-            for n in self._xfrrunning_names:
-                spec = isc.config.find_spec_part\
-                    (self._statistics_spec, n)
-                isc.cc.data.set(self._statistics_data, n, \
-                                spec['item_default'])
-
-    def _add_unixsocket_counter(self, counter_name):
-        """Adds a counter for counting unix sockets"""
-        try:
-            self._statistics_data['socket']['unixdomain'][counter_name]
-        except KeyError:
-            # examines the name of unixsocket
-            name = 'socket/unixdomain/%s' % counter_name
-            spec = isc.config.find_spec_part\
-                (self._statistics_spec, name)
-            isc.cc.data.set(self._statistics_data, name, \
-                                spec['item_default'])
-
-    def dump_default_statistics(self):
-        """Returns default statistics data from the spec file"""
-        statistics_data = {}
-        for id_ in isc.config.spec_name_list(self._statistics_spec):
-            spec = isc.config.find_spec_part(\
-                self._statistics_spec, id_)
-            if 'item_default' in spec:
-                statistics_data.update({id_: spec['item_default']})
-        return statistics_data
-
     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 len(self._statistics_data) == 0: return {}
-        # for per-zone counter
-        zones = self._statistics_data[self._perzone_prefix]
+        if self._perzone_prefix not in statistics_data:
+            return statistics_data
+        zones = statistics_data[self._perzone_prefix]
         # Start calculation for '_SERVER_' counts
-        attrs = self.dump_default_statistics()\
-            [self._perzone_prefix][self._entire_server]
-        statistics_data = {self._perzone_prefix: {}}
-        for attr in attrs:
+        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 name == self._entire_server: continue
                 if attr in zones[name]:
-                    if  name not in \
-                            statistics_data[self._perzone_prefix]:
-                        statistics_data[self._perzone_prefix][name]\
-                            = {}
-                    statistics_data[self._perzone_prefix][name].\
-                        update({attr: zones[name][attr]})
                     sum_ += zones[name][attr]
             if  sum_ > 0:
-                if self._entire_server not in \
-                        statistics_data[self._perzone_prefix]:
-                    statistics_data[self._perzone_prefix][self._entire_server]\
-                        = {}
-                statistics_data[self._perzone_prefix][self._entire_server]\
-                    .update({attr:sum_})
-
-        # for xfrrunning incrementer/decrementer
-        for name in self._xfrrunning_names:
-            if name in self._statistics_data:
-                statistics_data[name] = self._statistics_data[name]
-
-        # for unixsocket incrementer/decrementer
-        if 'socket' in self._statistics_data:
-            statistics_data['socket'] = \
-                self._statistics_data['socket']
-
+                _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
 
+    def _create_unixsocket_functors(self):
+        """Creates increment method of unixsocket socket. Incrementer
+        can be accessed by name "inc_unixsocket_${item_name}"."""
+        for item in self._unixsocket_names:
+            def __incrementer(counter_name=item, step=1):
+                """A incrementer for unix socket counter"""
+                self._incrementer(
+                    'socket/unixdomain/%s' % counter_name,
+                    step)
+            def __getter(counter_name=item):
+                """A getter method for unix socket counter"""
+                return self._getter(
+                    'socket/unixdomain/%s' % counter_name)
+            self._to_global['inc_unixsocket_%s' % item] = __incrementer
+            self._to_global['get_unixsocket_%s' % item] = __getter
+
+    def _create_ipsocket_functors(self):
+        """Creates increment method of ip socket. Incrementer can be
+        accessed by name "inc_ipv4socket_${item_name}" for ipv4 or
+        "inc_ipv6socket_${item_name}" for ipv6."""
+        for item in self._ipsocket_names:
+            # item should be tuple-type
+            def __incrementer(counter_name=item, step=1):
+                """A incrementer for ip socket counter"""
+                self._incrementer(
+                    'socket/%s/tcp/%s' % counter_name,
+                    step)
+            def __getter(counter_name=item):
+                """A getter method for ip socket counter"""
+                return self._getter(
+                    'socket/%s/tcp/%s' % counter_name)
+            self._to_global['inc_%ssocket_%s' % item] = __incrementer
+            self._to_global['get_%ssocket_%s' % item] = __getter
+
diff --git a/src/lib/python/isc/statistics/tests/Makefile.am b/src/lib/python/isc/statistics/tests/Makefile.am
index 0c2a01d..7e2252b 100644
--- a/src/lib/python/isc/statistics/tests/Makefile.am
+++ b/src/lib/python/isc/statistics/tests/Makefile.am
@@ -1,6 +1,9 @@
 PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
 PYTESTS = counter_test.py
 EXTRA_DIST = $(PYTESTS)
+EXTRA_DIST += testdata/test_spec1.spec
+EXTRA_DIST += testdata/test_spec2.spec
+EXTRA_DIST += testdata/test_spec3.spec
 
 # If necessary (rare cases), explicitly specify paths to dynamic libraries
 # required by loadable python modules.
@@ -21,9 +24,10 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
-	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/bin/xfrout:$(abs_top_builddir)/src/lib/dns/python/.libs \
+	PYTHONPATH=$(COMMON_PYTHON_PATH) \
 	$(LIBRARY_PATH_PLACEHOLDER) \
-	TESTDATASRCDIR=$(abs_top_srcdir)/src/lib/python/isc/statistics/tests/testdata/ \
 	B10_FROM_BUILD=$(abs_top_builddir) \
+	B10_FROM_SOURCE=$(abs_top_srcdir) \
+	TESTDATASRCDIR=$(abs_top_srcdir)/src/lib/python/isc/statistics/tests/testdata \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/lib/python/isc/statistics/tests/counter_test.py b/src/lib/python/isc/statistics/tests/counter_test.py
index 4023118..0837190 100644
--- a/src/lib/python/isc/statistics/tests/counter_test.py
+++ b/src/lib/python/isc/statistics/tests/counter_test.py
@@ -17,19 +17,43 @@
 
 import unittest
 import threading
+from datetime import timedelta
+import os
+import imp
 import isc.config
-import xfrout
 
 TEST_ZONE_NAME_STR = "example.com."
+TESTDATA_SRCDIR = os.getenv("TESTDATASRCDIR")
 
 from isc.statistics import counter
 
-class TestCounter(unittest.TestCase):
+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(number, cycle, 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(number):
+        threads.append(threading.Thread(\
+                target=setup_functor, \
+                    args=(event, cycle, 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):
-        module_spec = isc.config.module_spec_from_file(\
-            xfrout.SPECFILE_LOCATION)
-        self.counter = counter.Counter(module_spec)
+        self.counter = counter.Counter.init(self.TEST_SPECFILE_LOCATION)
+
+    def tearDown(self):
+        self.counter.clear_counters()
 
     def test_clear_counters(self):
         self.counter._statistics_data = {'counter': 1}
@@ -44,128 +68,258 @@ class TestCounter(unittest.TestCase):
         self.counter.enable()
         self.assertFalse(self.counter._disabled)
 
-class TestXfroutCounter(unittest.TestCase):
-    _number = 3 # number of the threads
-    _cycle = 10000 # number of counting per thread
+    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"""
+        number = 3    # number of the threads
+        cycle = 10000 # number of counting per thread
+        statistics_data = {}
+        counter_name = "counter"
+        timer_name = "seconds"
+        statistics_spec = \
+            isc.config.module_spec_from_file(self.TEST_SPECFILE_LOCATION)\
+            .get_statistics_spec()
+        self.counter._statistics_data = statistics_data
+        self.counter._statistics_spec = statistics_spec
+        start_time = counter._start_timer()
+        start_functor(number, cycle, self.counter._incrementer,
+                      counter_name)
+        counter._stop_timer(start_time,
+                            statistics_data,
+                            statistics_spec,
+                            timer_name)
+        self.assertEqual(
+            counter._get_counter(statistics_data,
+                                 counter_name),
+            number * cycle)
+        self.assertGreater(
+            counter._get_counter(statistics_data,
+                                 timer_name), 0)
+
+class BaseTestCounter():
+    imp.reload(counter)
     def setUp(self):
-        self._module_spec = isc.config.module_spec_from_file(\
-            xfrout.SPECFILE_LOCATION)
-        self._statistics_spec = \
-            self._module_spec.get_statistics_spec()
-        self.xfrout_counter = \
-            counter.init(xfrout.SPECFILE_LOCATION)
-        self._entire_server    = self.xfrout_counter._entire_server
-        self._perzone_prefix   = self.xfrout_counter._perzone_prefix
-        self._xfrrunning_names = self.xfrout_counter._xfrrunning_names
-        self._unixsocket_names = self.xfrout_counter._unixsocket_names
+        self._module_spec = isc.config.module_spec_from_file(
+            self.TEST_SPECFILE_LOCATION)
+        self.counter = counter.Counter.init(self.TEST_SPECFILE_LOCATION)
+        self._statistics_data = {}
+        self._entire_server    = self.counter._entire_server
+        self._perzone_prefix   = self.counter._perzone_prefix
+        self._xfrrunning_names = self.counter._xfrrunning_names
+        self._unixsocket_names = self.counter._unixsocket_names
+        self._ipsocket_names = self.counter._ipsocket_names
+        self._zones_item_list   = self.counter._zones_item_list
         self._started = threading.Event()
 
-    def test_dump_default_statistics(self):
-        self.assertTrue(\
-            self._module_spec.validate_statistics(\
-                True,
-                counter.dump_default_statistics(),
-                )
-            )
-
-    def setup_functor(self, incrementer, *args):
-        self._started.wait()
-        for i in range(self._cycle): incrementer(*args)
-
-    def start_functor(self, incrementer, *args):
-        threads = []
-        for i in range(self._number):
-            threads.append(threading.Thread(\
-                    target=self.setup_functor, \
-                        args=(incrementer,) + args \
-                        ))
-        for th in threads: th.start()
-        self._started.set()
-        for th in threads: th.join()
-
-    def get_count(self, zone_name, counter_name):
-        return isc.cc.data.find(\
-            counter.dump_statistics(),\
-                '%s/%s/%s' % (self._perzone_prefix,\
-                                  zone_name, counter_name))
-
-    def test_functors(self):
+    def test_perzone_counters(self):
         # for per-zone counters
-        result = { self._entire_server: {},
-                   TEST_ZONE_NAME_STR: {} }
-        self._perzone_counters = isc.config.spec_name_list(\
-            isc.config.find_spec_part(\
-                self._statistics_spec, self._perzone_prefix)\
-                ['named_set_item_spec']['map_item_spec'])
-        for counter_name in self._perzone_counters:
-            incrementer = getattr(counter,'inc_%s' % counter_name)
-            self.start_functor(incrementer, TEST_ZONE_NAME_STR)
-            getter = getattr(counter,'get_%s' % counter_name)
-            self.assertEqual(getter(TEST_ZONE_NAME_STR),
-                             self._number * self._cycle)
-            self.assertEqual(self.get_count(self._entire_server,
-                        counter_name), self._number * self._cycle)
+        for counter_name in self._zones_item_list:
+            if counter_name.find('time_to_') == 0:
+                isc.cc.data.set(\
+                    self._statistics_data,
+                    '%s/%s/%s' % (self._perzone_prefix,
+                                  TEST_ZONE_NAME_STR,
+                                  counter_name), 0.0)
+                continue
+            incrementer = self.counter._to_global\
+                ['inc_%s' % counter_name]
+            getter = self.counter._to_global\
+                ['get_%s' % counter_name]
+            incrementer(TEST_ZONE_NAME_STR)
+            self.assertEqual(getter(TEST_ZONE_NAME_STR), 1)
             # checks disable/enable
-            counter.disable()
+            self.counter.disable()
             incrementer(TEST_ZONE_NAME_STR)
-            self.assertEqual(getter(TEST_ZONE_NAME_STR),
-                             self._number * self._cycle)
-            counter.enable()
+            self.assertEqual(getter(TEST_ZONE_NAME_STR), 1)
+            self.counter.enable()
             incrementer(TEST_ZONE_NAME_STR)
-            self.assertEqual(getter(TEST_ZONE_NAME_STR),
-                             self._number * self._cycle + 1)
-            result[self._entire_server][counter_name] = \
-                result[TEST_ZONE_NAME_STR][counter_name] = \
-                self._number * self._cycle + 1
+            self.assertEqual(getter(TEST_ZONE_NAME_STR), 2)
+            for zone_str in (self._entire_server, TEST_ZONE_NAME_STR):
+                isc.cc.data.set(\
+                    self._statistics_data,
+                    '%s/%s/%s' % (self._perzone_prefix,
+                                  zone_str,
+                                  counter_name), 2)
+            # checks other counters
+            for counter_name in self._zones_item_list:
+                getter = self.counter._to_global\
+                    ['get_%s' % counter_name]
+                self.assertGreaterEqual(getter(TEST_ZONE_NAME_STR), 0)
+        self.check_dump_statistics()
 
-        statistics_data = {self._perzone_prefix: result}
-
-        # for {a|i}xfrrunning counters
+    def test_xfrrunning_counters(self):
+        # for counters of xfer running
         for counter_name in self._xfrrunning_names:
-            incrementer = getattr(counter,'inc_%s' % counter_name)
-            self.start_functor(incrementer)
-            getter = getattr(counter,'get_%s' % counter_name)
-            self.assertEqual(getter(), self._number * self._cycle)
-            decrementer = getattr(counter,'dec_%s' % counter_name)
-            self.start_functor(decrementer)
+            incrementer = self.counter._to_global\
+                ['inc_%s' % counter_name]
+            getter = self.counter._to_global\
+                ['get_%s' % counter_name]
+            decrementer = self.counter._to_global\
+                ['dec_%s' % counter_name]
+            incrementer()
+            self.assertEqual(getter(), 1)
+            decrementer()
             self.assertEqual(getter(), 0)
             # checks disable/enable
-            counter.disable()
+            self.counter.disable()
             incrementer()
             self.assertEqual(getter(), 0)
-            counter.enable()
+            self.counter.enable()
             incrementer()
-            self.assertGreater(getter(), 0)
-            counter.disable()
+            self.assertEqual(getter(), 1)
+            self.counter.disable()
             decrementer()
-            self.assertGreater(getter(), 0)
-            counter.enable()
+            self.assertEqual(getter(), 1)
+            self.counter.enable()
             decrementer()
             self.assertEqual(getter(), 0)
-            statistics_data[counter_name] = 0
+            self._statistics_data[counter_name] = 0
+        self.check_dump_statistics()
 
+    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)
+        self.assertTrue(self._module_spec.validate_statistics(
+                False, self._statistics_data))
+
+    def test_unixsocket_counters(self):
         # for unixsocket counters
-        statistics_data.update({'socket': {'unixdomain': {}}})
         for counter_name in self._unixsocket_names:
-            incrementer = getattr(counter, 'inc_unixsocket_%s' % counter_name)
-            self.start_functor(incrementer)
-            getter = getattr(counter, 'get_unixsocket_%s' % counter_name)
-            self.assertEqual(getter(), self._number * self._cycle)
+            incrementer = self.counter._to_global\
+                ['inc_unixsocket_%s' % counter_name]
+            getter = self.counter._to_global\
+                ['get_unixsocket_%s' % counter_name]
+            incrementer()
+            self.assertEqual(getter(), 1)
+            # checks disable/enable
+            self.counter.disable()
+            incrementer()
+            self.assertEqual(getter(), 1)
+            self.counter.enable()
+            incrementer()
+            self.assertEqual(getter(), 2)
+            isc.cc.data.set(
+                self._statistics_data,
+                'socket/unixdomain/%s' % counter_name, 2)
+        self.check_dump_statistics()
+
+    def test_perzone_timers(self):
+        # for timer counters
+        for counter_name in self._zones_item_list:
+            if counter_name.find('time_to_') == -1:
+                isc.cc.data.set(\
+                    self._statistics_data,
+                    '%s/%s/%s' % (self._perzone_prefix,
+                                  TEST_ZONE_NAME_STR,
+                                  counter_name), 0)
+                continue
+            starter = self.counter._to_global\
+                ['start_%s' % counter_name]
+            stopper = self.counter._to_global\
+                ['stop_%s' % counter_name]
+            getter = self.counter._to_global\
+                ['get_%s' % counter_name]
+            starter(TEST_ZONE_NAME_STR)
+            stopper(TEST_ZONE_NAME_STR)
+            self.assertGreater(getter(TEST_ZONE_NAME_STR), 0)
+            sec = getter(TEST_ZONE_NAME_STR)
+            for zone_str in (self._entire_server, TEST_ZONE_NAME_STR):
+                isc.cc.data.set(\
+                    self._statistics_data,
+                    '%s/%s/%s' % (self._perzone_prefix,
+                                  zone_str,
+                                  counter_name), sec)
+            # twice exec stopper, then second is not changed
+            stopper(TEST_ZONE_NAME_STR)
+            self.assertEqual(getter(TEST_ZONE_NAME_STR), sec)
+        self.check_dump_statistics()
+
+    def test_ipsocket_counters(self):
+        # for unixsocket counters
+        for counter_name in self._ipsocket_names:
+            incrementer = self.counter._to_global\
+                ['inc_%ssocket_%s' % counter_name]
+            getter = self.counter._to_global\
+                ['get_%ssocket_%s' % counter_name]
+            incrementer()
+            self.assertEqual(getter(), 1)
             # checks disable/enable
-            counter.disable()
+            self.counter.disable()
             incrementer()
-            self.assertEqual(getter(), self._number * self._cycle)
-            counter.enable()
+            self.assertEqual(getter(), 1)
+            self.counter.enable()
             incrementer()
-            self.assertEqual(getter(), self._number * self._cycle + 1)
-            statistics_data['socket']['unixdomain'][counter_name] = \
-                self._number * self._cycle + 1
-
-        # totally chacking
-        self.assertEqual(counter.dump_statistics(), statistics_data)
-        self.assertTrue(self._module_spec.validate_statistics(\
-                True, statistics_data))
+            self.assertEqual(getter(), 2)
+            isc.cc.data.set(
+                self._statistics_data,
+                'socket/%s/tcp/%s' % counter_name, 2)
+        self.check_dump_statistics()
+
+class TestCounter1(BaseTestCounter, unittest.TestCase):
+    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec1.spec'
+
+class TestCounter2(BaseTestCounter, unittest.TestCase):
+    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec2.spec'
+
+class TestCounter3(BaseTestCounter, unittest.TestCase):
+    TEST_SPECFILE_LOCATION = TESTDATA_SRCDIR + os.sep + 'test_spec3.spec'
 
 if __name__== "__main__":
     unittest.main()
diff --git a/src/lib/python/isc/statistics/tests/testdata/test_spec1.spec b/src/lib/python/isc/statistics/tests/testdata/test_spec1.spec
new file mode 100644
index 0000000..dbe7c6c
--- /dev/null
+++ b/src/lib/python/isc/statistics/tests/testdata/test_spec1.spec
@@ -0,0 +1,26 @@
+{
+  "module_spec": {
+    "module_name": "Simple",
+    "config_data": [],
+    "commands": [],
+    "statistics": [
+      {
+        "item_name": "counter",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_title": "Counter",
+        "item_description": "Counter",
+        "item_default": 0
+      },
+      {
+        "item_name": "seconds",
+        "item_type": "real",
+        "item_optional": false,
+        "item_title": "Seconds",
+        "item_description": "Seconds",
+        "item_default": 0.0
+      }
+    ]
+  }
+}
+
diff --git a/src/lib/python/isc/statistics/tests/testdata/test_spec2.spec b/src/lib/python/isc/statistics/tests/testdata/test_spec2.spec
new file mode 100644
index 0000000..11b8706
--- /dev/null
+++ b/src/lib/python/isc/statistics/tests/testdata/test_spec2.spec
@@ -0,0 +1,187 @@
+{
+  "module_spec": {
+    "module_name": "XfroutLike",
+    "config_data": [],
+    "commands": [],
+    "statistics": [
+      {
+        "item_name": "zones",
+        "item_type": "named_set",
+        "item_optional": false,
+        "item_default": {
+          "_SERVER_" : {
+            "notifyoutv4" : 0,
+            "notifyoutv6" : 0,
+            "xfrrej" : 0,
+            "xfrreqdone" : 0
+          }
+        },
+        "item_title": "Zone names",
+        "item_description": "Zone names for Xfrout statistics",
+        "named_set_item_spec": {
+          "item_name": "zonename",
+          "item_type": "map",
+          "item_optional": false,
+          "item_default": {},
+          "item_title": "Zone name",
+          "item_description": "Zone name for Xfrout statistics",
+          "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 from Xfrout"
+            },
+            {
+              "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 from Xfrout"
+            },
+            {
+              "item_name": "xfrrej",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "XFR rejected requests",
+              "item_description": "Number of XFR requests per zone name rejected by Xfrout"
+            },
+            {
+              "item_name": "xfrreqdone",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "Requested zone transfers",
+              "item_description": "Number of requested zone transfers completed per zone name"
+            }
+          ]
+        }
+      },
+      {
+        "item_name": "ixfr_running",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "IXFR running",
+        "item_description": "Number of IXFRs in progress"
+      },
+      {
+        "item_name": "axfr_running",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "AXFR running",
+        "item_description": "Number of AXFRs in progress"
+      },
+      {
+        "item_name": "socket",
+        "item_type": "map",
+        "item_optional": false,
+        "item_default": {
+          "unixdomain": {
+            "open": 0,
+            "openfail": 0,
+            "close": 0,
+            "bindfail": 0,
+            "acceptfail": 0,
+            "accept": 0,
+            "senderr": 0,
+            "recverr": 0
+          }
+        },
+        "item_title": "Socket",
+        "item_description": "Socket",
+        "map_item_spec": [
+          {
+            "item_name": "unixdomain",
+            "item_type": "map",
+            "item_optional": false,
+            "item_default": {
+              "open": 0,
+              "openfail": 0,
+              "close": 0,
+              "bindfail": 0,
+              "acceptfail": 0,
+              "accept": 0,
+              "senderr": 0,
+              "recverr": 0
+            },
+            "item_title": "Unix Domain",
+            "item_description": "Unix Domain",
+            "map_item_spec": [
+              {
+                "item_name": "open",
+                "item_type": "integer",
+                "item_optional": false,
+                "item_default": 0,
+                "item_title": "Open",
+                "item_description": "Unix Domain sockets opened successfully"
+              },
+              {
+                "item_name": "openfail",
+                "item_type": "integer",
+                "item_optional": false,
+                "item_default": 0,
+                "item_title": "Open failures",
+                "item_description": "Unix Domain sockets open failures"
+              },
+              {
+                "item_name": "close",
+                "item_type": "integer",
+                "item_optional": false,
+                "item_default": 0,
+                "item_title": "Close",
+                "item_description": "Unix Domain sockets closed"
+              },
+              {
+                "item_name": "bindfail",
+                "item_type": "integer",
+                "item_optional": false,
+                "item_default": 0,
+                "item_title": "Bind failures",
+                "item_description": "Unix Domain sockets bind failures"
+              },
+              {
+                "item_name": "acceptfail",
+                "item_type": "integer",
+                "item_optional": false,
+                "item_default": 0,
+                "item_title": "Accept failures",
+                "item_description": "Unix Domain sockets incoming accept failures"
+              },
+              {
+                "item_name": "accept",
+                "item_type": "integer",
+                "item_optional": false,
+                "item_default": 0,
+                "item_title": "Accept",
+                "item_description": "Unix Domain sockets incoming connections successfully accepted"
+              },
+              {
+                "item_name": "senderr",
+                "item_type": "integer",
+                "item_optional": false,
+                "item_default": 0,
+                "item_title": "Send errors",
+                "item_description": "Unix Domain sockets send errors"
+              },
+              {
+                "item_name": "recverr",
+                "item_type": "integer",
+                "item_optional": false,
+                "item_default": 0,
+                "item_title": "Receive errors",
+                "item_description": "Unix Domain sockets receive errors"
+              }
+            ]
+          }
+        ]
+      }
+    ]
+  }
+}
+
diff --git a/src/lib/python/isc/statistics/tests/testdata/test_spec3.spec b/src/lib/python/isc/statistics/tests/testdata/test_spec3.spec
new file mode 100644
index 0000000..c97a09a
--- /dev/null
+++ b/src/lib/python/isc/statistics/tests/testdata/test_spec3.spec
@@ -0,0 +1,382 @@
+{
+  "module_spec": {
+    "module_name": "XfrinLike",
+    "module_description": "XFR in daemon",
+    "config_data": [],
+    "commands": [],
+    "statistics": [
+      {
+        "item_name": "zones",
+        "item_type": "named_set",
+        "item_optional": false,
+        "item_default": {
+          "_SERVER_" : {
+	    "soaoutv4": 0,
+	    "soaoutv6": 0,
+	    "axfrreqv4": 0,
+	    "axfrreqv6": 0,
+	    "ixfrreqv4": 0,
+	    "ixfrreqv6": 0,
+	    "xfrsuccess": 0,
+	    "xfrfail": 0,
+	    "time_to_ixfr": 0.0,
+	    "time_to_axfr": 0.0
+          }
+        },
+        "item_title": "Zone names",
+        "item_description": "Zone names for Xfrout statistics",
+        "named_set_item_spec": {
+          "item_name": "zonename",
+          "item_type": "map",
+          "item_optional": false,
+          "item_default": {},
+          "item_title": "Zone name",
+          "item_description": "Zone name for Xfrout statistics",
+          "map_item_spec": [
+            {
+              "item_name": "soaoutv4",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "SOAOutv4",
+              "item_description": "Number of IPv4 SOA queries sent from Xfrin"
+            },
+            {
+              "item_name": "soaoutv6",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "SOAOutv6",
+              "item_description": "Number of IPv6 SOA queries sent from Xfrin"
+            },
+            {
+              "item_name": "axfrreqv4",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "AXFRReqv4",
+              "item_description": "Number of IPv4 AXFR requests sent from Xfrin"
+            },
+            {
+              "item_name": "axfrreqv6",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "AXFRReqv6",
+              "item_description": "Number of IPv6 AXFR requests sent from Xfrin"
+            },
+            {
+              "item_name": "ixfrreqv4",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "IXFRReqv4",
+              "item_description": "Number of IPv4 IXFR requests sent from Xfrin"
+            },
+            {
+              "item_name": "ixfrreqv6",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "IXFRReqv6",
+              "item_description": "Number of IPv6 IXFR requests sent from Xfrin"
+            },
+            {
+              "item_name": "xfrsuccess",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "XfrSuccess",
+              "item_description": "Number of zone transfer requests succeeded"
+            },
+            {
+              "item_name": "xfrfail",
+              "item_type": "integer",
+              "item_optional": false,
+              "item_default": 0,
+              "item_title": "XfrFail",
+              "item_description": "Number of zone transfer requests failed"
+            },
+            {
+              "item_name": "time_to_ixfr",
+              "item_type": "real",
+              "item_optional": false,
+              "item_default": 0.0,
+              "item_title": "Time to IXFR",
+              "item_description": "Elapsed time in seconds to do the last IXFR"
+            },
+            {
+              "item_name": "time_to_axfr",
+              "item_type": "real",
+              "item_optional": false,
+              "item_default": 0.0,
+              "item_title": "Time to AXFR",
+              "item_description": "Elapsed time in seconds to do the last AXFR"
+            }
+          ]
+        }
+      },
+      {
+        "item_name": "ixfr_running",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "IXFRs running",
+        "item_description": "Number of IXFRs in progress"
+      },
+      {
+        "item_name": "axfr_running",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "AXFRs running",
+        "item_description": "Number of AXFRs in progress"
+      },
+      {
+        "item_name": "ixfr_deferred",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "IXFRs deferred",
+        "item_description": "Number of deferred IXFRs"
+      },
+      {
+        "item_name": "axfr_deferred",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "AXFRs deferred",
+        "item_description": "Number of deferred AXFRs"
+      },
+      {
+        "item_name": "soa_in_progress",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "SOA queries",
+        "item_description": "Number of SOA queries in progress"
+      },
+      {
+        "item_name": "socket",
+        "item_type": "map",
+        "item_optional": false,
+        "item_default": {
+          "ipv4": {
+            "tcp": {
+              "open": 0,
+              "openfail": 0,
+              "close": 0,
+              "connfail": 0,
+              "conn": 0,
+              "senderr": 0,
+              "recverr": 0
+            }
+          },
+          "ipv6": {
+            "tcp": {
+              "open": 0,
+              "openfail": 0,
+              "close": 0,
+              "connfail": 0,
+              "conn": 0,
+              "senderr": 0,
+              "recverr": 0
+            }
+          }
+        },
+        "item_title": "Socket",
+        "item_description": "Socket",
+        "map_item_spec": [
+          {
+            "item_name": "ipv4",
+            "item_type": "map",
+            "item_optional": false,
+            "item_default": {
+              "tcp": {
+                "open": 0,
+                "openfail": 0,
+                "close": 0,
+                "connfail": 0,
+                "conn": 0,
+                "senderr": 0,
+                "recverr": 0
+              }
+            },
+            "item_title": "IPv4",
+            "item_description": "IPv4",
+            "map_item_spec": [
+              {
+                "item_name": "tcp",
+                "item_type": "map",
+                "item_optional": false,
+                "item_default": {
+                  "open": 0,
+                  "openfail": 0,
+                  "close": 0,
+                  "connfail": 0,
+                  "conn": 0,
+                  "senderr": 0,
+                  "recverr": 0
+                },
+                "item_title": "TCP",
+                "item_description": "TCP/IP",
+                "map_item_spec": [
+                  {
+                    "item_name": "open",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Open",
+                    "item_description": "IPv4 TCP sockets opened successfully"
+                  },
+                  {
+                    "item_name": "openfail",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Open failures",
+                    "item_description": "IPv4 TCP sockets open failures"
+                  },
+                  {
+                    "item_name": "close",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Close",
+                    "item_description": "IPv4 TCP sockets closed"
+                  },
+                  {
+                    "item_name": "connfail",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Connect failures",
+                    "item_description": "IPv4 TCP sockets connection failures"
+                  },
+                  {
+                    "item_name": "conn",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Connect",
+                    "item_description": "IPv4 TCP connections established successfully"
+                  },
+                  {
+                    "item_name": "senderr",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Send errors",
+                    "item_description": "IPv4 TCP sockets send errors"
+                  },
+                  {
+                    "item_name": "recverr",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Receive errors",
+                    "item_description": "IPv4 TCP sockets receive errors"
+                  }
+                ]
+              }
+            ]
+          },
+          {
+            "item_name": "ipv6",
+            "item_type": "map",
+            "item_optional": false,
+            "item_default": {
+              "tcp": {
+                "open": 0,
+                "openfail": 0,
+                "close": 0,
+                "connfail": 0,
+                "conn": 0,
+                "senderr": 0,
+                "recverr": 0
+              }
+            },
+            "item_title": "IPv6",
+            "item_description": "IPv6",
+            "map_item_spec": [
+              {
+                "item_name": "tcp",
+                "item_type": "map",
+                "item_optional": false,
+                "item_default": {
+                  "open": 0,
+                  "openfail": 0,
+                  "close": 0,
+                  "connfail": 0,
+                  "conn": 0,
+                  "senderr": 0,
+                  "recverr": 0
+                },
+                "item_title": "TCP",
+                "item_description": "TCP/IP",
+                "map_item_spec": [
+                  {
+                    "item_name": "open",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Open",
+                    "item_description": "IPv6 TCP sockets opened successfully"
+                  },
+                  {
+                    "item_name": "openfail",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Open failures",
+                    "item_description": "IPv6 TCP sockets open failures"
+                  },
+                  {
+                    "item_name": "close",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Close",
+                    "item_description": "IPv6 TCP sockets closed"
+                  },
+                  {
+                    "item_name": "connfail",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Connect failures",
+                    "item_description": "IPv6 TCP sockets connection failures"
+                  },
+                  {
+                    "item_name": "conn",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Connect",
+                    "item_description": "IPv6 TCP connections established successfully"
+                  },
+                  {
+                    "item_name": "senderr",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Send errors",
+                    "item_description": "IPv6 TCP sockets send errors"
+                  },
+                  {
+                    "item_name": "recverr",
+                    "item_type": "integer",
+                    "item_optional": false,
+                    "item_default": 0,
+                    "item_title": "Receive errors",
+                    "item_description": "IPv6 TCP sockets receive errors"
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+      }
+    ]
+  }
+}



More information about the bind10-changes mailing list