Browse Source

[2225] removed obsoleted classes from xfrout.py and xfrout_test.py

XfroutCounter class and TestXfroutCounter are removed
Naoki Kambe 12 years ago
parent
commit
c06c560406
2 changed files with 197 additions and 393 deletions
  1. 137 195
      src/bin/xfrout/tests/xfrout_test.py.in
  2. 60 198
      src/bin/xfrout/xfrout.py.in

+ 137 - 195
src/bin/xfrout/tests/xfrout_test.py.in

@@ -270,7 +270,6 @@ class TestXfroutSessionBase(unittest.TestCase):
 
 
     def setUp(self):
     def setUp(self):
         self.sock = MySocket(socket.AF_INET,socket.SOCK_STREAM)
         self.sock = MySocket(socket.AF_INET,socket.SOCK_STREAM)
-        self.setup_counters()
         self.xfrsess = MyXfroutSession(self.sock, None, Dbserver(),
         self.xfrsess = MyXfroutSession(self.sock, None, Dbserver(),
                                        TSIGKeyRing(),
                                        TSIGKeyRing(),
                                        (socket.AF_INET, socket.SOCK_STREAM,
                                        (socket.AF_INET, socket.SOCK_STREAM,
@@ -278,8 +277,7 @@ class TestXfroutSessionBase(unittest.TestCase):
                                        # When not testing ACLs, simply accept
                                        # When not testing ACLs, simply accept
                                        isc.acl.dns.REQUEST_LOADER.load(
                                        isc.acl.dns.REQUEST_LOADER.load(
                                            [{"action": "ACCEPT"}]),
                                            [{"action": "ACCEPT"}]),
-                                       {},
-                                       **self._counters)
+                                       {})
         self.set_request_type(RRType.AXFR()) # test AXFR by default
         self.set_request_type(RRType.AXFR()) # test AXFR by default
         self.mdata = self.create_request_data()
         self.mdata = self.create_request_data()
         self.soa_rrset = create_soa(SOA_CURRENT_VERSION)
         self.soa_rrset = create_soa(SOA_CURRENT_VERSION)
@@ -287,52 +285,13 @@ class TestXfroutSessionBase(unittest.TestCase):
         # original is used elsewhere.
         # original is used elsewhere.
         self.orig_get_rrset_len = xfrout.get_rrset_len
         self.orig_get_rrset_len = xfrout.get_rrset_len
 
 
-    def setup_counters(self):
-        self._statistics_data = {
-            'zones' : {
-                TEST_ZONE_NAME_STR : {
-                    'xfrrej': 0,
-                    'xfrreqdone': 0
-                    }
-                },
-            'axfr_started': 0,
-            'ixfr_started': 0,
-            'axfr_ended': 0,
-            'ixfr_ended': 0
-            }
-        def _counter_xfrrej(zone_name):
-            self._statistics_data['zones'][zone_name]['xfrrej'] += 1
-        def _counter_xfrreqdone(zone_name):
-            self._statistics_data['zones'][zone_name]['xfrreqdone'] += 1
-        def _inc_ixfr_running():
-            self._statistics_data['ixfr_started'] += 1
-        def _dec_ixfr_running():
-            self._statistics_data['ixfr_ended'] += 1
-        def _inc_axfr_running():
-            self._statistics_data['axfr_started'] += 1
-        def _dec_axfr_running():
-            self._statistics_data['axfr_ended'] += 1
-        self._counters = {
-            'counter_xfrrej': _counter_xfrrej,
-            'counter_xfrreqdone': _counter_xfrreqdone,
-            'inc_ixfr_running': _inc_ixfr_running,
-            'dec_ixfr_running': _dec_ixfr_running,
-            'inc_axfr_running': _inc_axfr_running,
-            'dec_axfr_running': _dec_axfr_running
-            }
-
-    def get_counter(self, name):
-        if name.find('ixfr_') == 0 or name.find('axfr_') == 0:
-            return self._statistics_data[name]
-        else:
-            return \
-                self._statistics_data['zones'][TEST_ZONE_NAME_STR][name]
-
     def tearDown(self):
     def tearDown(self):
         xfrout.get_rrset_len = self.orig_get_rrset_len
         xfrout.get_rrset_len = self.orig_get_rrset_len
         # transfer_counter must be always be reset no matter happens within
         # transfer_counter must be always be reset no matter happens within
         # the XfroutSession object.  We check the condition here.
         # the XfroutSession object.  We check the condition here.
         self.assertEqual(0, self.xfrsess._server.transfer_counter)
         self.assertEqual(0, self.xfrsess._server.transfer_counter)
+        # clear statistics counters
+        counter.clear_counters()
 
 
 class TestXfroutSession(TestXfroutSessionBase):
 class TestXfroutSession(TestXfroutSessionBase):
     def test_quota_error(self):
     def test_quota_error(self):
@@ -420,7 +379,8 @@ class TestXfroutSession(TestXfroutSessionBase):
             }
             }
         ]))
         ]))
         # check the 'xfrrej' counter initially
         # check the 'xfrrej' counter initially
-        self.assertEqual(self.get_counter('xfrrej'), 0)
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_xfrrej, TEST_ZONE_NAME_STR)
         # Localhost (the default in this test) is accepted
         # Localhost (the default in this test) is accepted
         rcode, msg = self.xfrsess._parse_query_message(self.mdata)
         rcode, msg = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "NOERROR")
         self.assertEqual(rcode.to_text(), "NOERROR")
@@ -435,7 +395,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         rcode, msg = self.xfrsess._parse_query_message(self.mdata)
         rcode, msg = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "REFUSED")
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.get_counter('xfrrej'), 1)
+        self.assertEqual(counter.get_xfrrej(TEST_ZONE_NAME_STR), 1)
 
 
         # TSIG signed request
         # TSIG signed request
         request_data = self.create_request_data(with_tsig=True)
         request_data = self.create_request_data(with_tsig=True)
@@ -465,7 +425,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         [rcode, msg] = self.xfrsess._parse_query_message(request_data)
         [rcode, msg] = self.xfrsess._parse_query_message(request_data)
         self.assertEqual(rcode.to_text(), "REFUSED")
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.get_counter('xfrrej'), 2)
+        self.assertEqual(counter.get_xfrrej(TEST_ZONE_NAME_STR), 2)
 
 
         # ACL using TSIG: no TSIG; should be rejected
         # ACL using TSIG: no TSIG; should be rejected
         acl_setter(isc.acl.dns.REQUEST_LOADER.load([
         acl_setter(isc.acl.dns.REQUEST_LOADER.load([
@@ -474,7 +434,7 @@ class TestXfroutSession(TestXfroutSessionBase):
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "REFUSED")
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.get_counter('xfrrej'), 3)
+        self.assertEqual(counter.get_xfrrej(TEST_ZONE_NAME_STR), 3)
 
 
         #
         #
         # ACL using IP + TSIG: both should match
         # ACL using IP + TSIG: both should match
@@ -495,21 +455,21 @@ class TestXfroutSession(TestXfroutSessionBase):
         [rcode, msg] = self.xfrsess._parse_query_message(request_data)
         [rcode, msg] = self.xfrsess._parse_query_message(request_data)
         self.assertEqual(rcode.to_text(), "REFUSED")
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.get_counter('xfrrej'), 4)
+        self.assertEqual(counter.get_xfrrej(TEST_ZONE_NAME_STR), 4)
         # Address matches, but TSIG doesn't (not included)
         # Address matches, but TSIG doesn't (not included)
         self.xfrsess._remote = (socket.AF_INET, socket.SOCK_STREAM,
         self.xfrsess._remote = (socket.AF_INET, socket.SOCK_STREAM,
                                 ('192.0.2.1', 12345))
                                 ('192.0.2.1', 12345))
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "REFUSED")
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.get_counter('xfrrej'), 5)
+        self.assertEqual(counter.get_xfrrej(TEST_ZONE_NAME_STR), 5)
         # Neither address nor TSIG matches
         # Neither address nor TSIG matches
         self.xfrsess._remote = (socket.AF_INET, socket.SOCK_STREAM,
         self.xfrsess._remote = (socket.AF_INET, socket.SOCK_STREAM,
                                 ('192.0.2.2', 12345))
                                 ('192.0.2.2', 12345))
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         [rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
         self.assertEqual(rcode.to_text(), "REFUSED")
         self.assertEqual(rcode.to_text(), "REFUSED")
         # check the 'xfrrej' counter after incrementing
         # check the 'xfrrej' counter after incrementing
-        self.assertEqual(self.get_counter('xfrrej'), 6)
+        self.assertEqual(counter.get_xfrrej(TEST_ZONE_NAME_STR), 6)
 
 
     def test_transfer_acl(self):
     def test_transfer_acl(self):
         # ACL checks only with the default ACL
         # ACL checks only with the default ACL
@@ -517,14 +477,6 @@ class TestXfroutSession(TestXfroutSessionBase):
             self.xfrsess._acl = acl
             self.xfrsess._acl = acl
         self.check_transfer_acl(acl_setter)
         self.check_transfer_acl(acl_setter)
 
 
-    def test_transfer_acl_with_notcallable_xfrrej(self):
-        # ACL checks only with the default ACL and not callable xfrrej
-        # counter
-        def acl_setter(acl):
-            self.xfrsess._acl = acl
-        self.xfrsess._counter_xfrrej = 'NOT CALLABLE'
-        self.assertRaises(TypeError,
-                          self.check_transfer_acl, acl_setter)
 
 
     def test_transfer_zoneacl(self):
     def test_transfer_zoneacl(self):
         # ACL check with a per zone ACL + default ACL.  The per zone ACL
         # ACL check with a per zone ACL + default ACL.  The per zone ACL
@@ -889,21 +841,23 @@ class TestXfroutSession(TestXfroutSessionBase):
         self.xfrsess.dns_xfrout_start(self.sock, self.mdata)
         self.xfrsess.dns_xfrout_start(self.sock, self.mdata)
         self.assertEqual(self.sock.read_msg().get_rcode(), Rcode.SERVFAIL())
         self.assertEqual(self.sock.read_msg().get_rcode(), Rcode.SERVFAIL())
 
 
-    def test_dns_xfrout_start_noerror(self):
+    def test_dns_xfrout_start_unixsocketsenderr(self):
+        """This test is for a counter senderr of unixsocket."""
+
         def noerror(msg, name, rrclass):
         def noerror(msg, name, rrclass):
             return Rcode.NOERROR()
             return Rcode.NOERROR()
         self.xfrsess._xfrout_setup = noerror
         self.xfrsess._xfrout_setup = noerror
 
 
         def myreply(msg, sock):
         def myreply(msg, sock):
-            self.sock.send(b"success")
+            raise Exception
 
 
-        self.assertEqual(self.get_counter('xfrreqdone'), 0)
         self.xfrsess._reply_xfrout_query = myreply
         self.xfrsess._reply_xfrout_query = myreply
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_unixsocket_senderr)
         self.xfrsess.dns_xfrout_start(self.sock, self.mdata)
         self.xfrsess.dns_xfrout_start(self.sock, self.mdata)
-        self.assertEqual(self.sock.readsent(), b"success")
-        self.assertGreater(self.get_counter('xfrreqdone'), 0)
+        self.assertEqual(counter.get_unixsocket_senderr(), 1)
 
 
-    def test_dns_xfrout_start_with_notcallable_xfrreqdone(self):
+    def test_dns_xfrout_start_noerror(self):
         def noerror(msg, name, rrclass):
         def noerror(msg, name, rrclass):
             return Rcode.NOERROR()
             return Rcode.NOERROR()
         self.xfrsess._xfrout_setup = noerror
         self.xfrsess._xfrout_setup = noerror
@@ -911,11 +865,13 @@ class TestXfroutSession(TestXfroutSessionBase):
         def myreply(msg, sock):
         def myreply(msg, sock):
             self.sock.send(b"success")
             self.sock.send(b"success")
 
 
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+            counter.get_xfrreqdone, TEST_ZONE_NAME_STR)
         self.xfrsess._reply_xfrout_query = myreply
         self.xfrsess._reply_xfrout_query = myreply
-        self.xfrsess._counter_xfrreqdone = 'NOT CALLABLE'
-        self.assertRaises(TypeError,
-                          self.xfrsess.dns_xfrout_start, self.sock,
-                          self.mdata)
+        self.xfrsess.dns_xfrout_start(self.sock, self.mdata)
+        self.assertEqual(self.sock.readsent(), b"success")
+        self.assertGreater(\
+            counter.get_xfrreqdone(TEST_ZONE_NAME_STR), 0)
 
 
     def test_reply_xfrout_query_axfr(self):
     def test_reply_xfrout_query_axfr(self):
         self.xfrsess._soa = self.soa_rrset
         self.xfrsess._soa = self.soa_rrset
@@ -1171,20 +1127,18 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
             self.assertTrue(rrsets_equal(expected_rr, actual_rr))
             self.assertTrue(rrsets_equal(expected_rr, actual_rr))
 
 
     def test_axfr_normal_session(self):
     def test_axfr_normal_session(self):
-        self.assertEqual(self.get_counter('axfr_started'), 0)
-        self.assertEqual(self.get_counter('axfr_ended'), 0)
-        self.assertEqual(self.get_counter('ixfr_started'), 0)
-        self.assertEqual(self.get_counter('ixfr_ended'), 0)
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_axfr_running)
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_ixfr_running)
         XfroutSession._handle(self.xfrsess)
         XfroutSession._handle(self.xfrsess)
         response = self.sock.read_msg(Message.PRESERVE_ORDER);
         response = self.sock.read_msg(Message.PRESERVE_ORDER);
         self.assertEqual(Rcode.NOERROR(), response.get_rcode())
         self.assertEqual(Rcode.NOERROR(), response.get_rcode())
         self.check_axfr_stream(response)
         self.check_axfr_stream(response)
         self.assertEqual(self.xfrsess._request_type, RRType.AXFR())
         self.assertEqual(self.xfrsess._request_type, RRType.AXFR())
         self.assertNotEqual(self.xfrsess._request_type, RRType.IXFR())
         self.assertNotEqual(self.xfrsess._request_type, RRType.IXFR())
-        self.assertEqual(self.get_counter('axfr_started'), 1)
-        self.assertEqual(self.get_counter('axfr_ended'), 1)
-        self.assertEqual(self.get_counter('ixfr_started'), 0)
-        self.assertEqual(self.get_counter('ixfr_ended'), 0)
+        self.assertEqual(counter.get_ixfr_running(), 0)
+        self.assertEqual(counter.get_axfr_running(), 0)
 
 
     def test_ixfr_to_axfr(self):
     def test_ixfr_to_axfr(self):
         self.xfrsess._request_data = \
         self.xfrsess._request_data = \
@@ -1203,10 +1157,10 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
         # two beginning and trailing SOAs.
         # two beginning and trailing SOAs.
         self.xfrsess._request_data = \
         self.xfrsess._request_data = \
             self.create_request_data(ixfr=IXFR_OK_VERSION)
             self.create_request_data(ixfr=IXFR_OK_VERSION)
-        self.assertEqual(self.get_counter('axfr_started'), 0)
-        self.assertEqual(self.get_counter('axfr_ended'), 0)
-        self.assertEqual(self.get_counter('ixfr_started'), 0)
-        self.assertEqual(self.get_counter('ixfr_ended'), 0)
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_axfr_running)
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_ixfr_running)
         XfroutSession._handle(self.xfrsess)
         XfroutSession._handle(self.xfrsess)
         response = self.sock.read_msg(Message.PRESERVE_ORDER)
         response = self.sock.read_msg(Message.PRESERVE_ORDER)
         actual_records = response.get_section(Message.SECTION_ANSWER)
         actual_records = response.get_section(Message.SECTION_ANSWER)
@@ -1224,10 +1178,8 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
             self.assertTrue(rrsets_equal(expected_rr, actual_rr))
             self.assertTrue(rrsets_equal(expected_rr, actual_rr))
         self.assertNotEqual(self.xfrsess._request_type, RRType.AXFR())
         self.assertNotEqual(self.xfrsess._request_type, RRType.AXFR())
         self.assertEqual(self.xfrsess._request_type, RRType.IXFR())
         self.assertEqual(self.xfrsess._request_type, RRType.IXFR())
-        self.assertEqual(self.get_counter('axfr_started'), 0)
-        self.assertEqual(self.get_counter('axfr_ended'), 0)
-        self.assertEqual(self.get_counter('ixfr_started'), 1)
-        self.assertEqual(self.get_counter('ixfr_ended'), 1)
+        self.assertEqual(counter.get_axfr_running(), 0)
+        self.assertEqual(counter.get_ixfr_running(), 0)
 
 
     def ixfr_soa_only_common_checks(self, request_serial):
     def ixfr_soa_only_common_checks(self, request_serial):
         self.xfrsess._request_data = \
         self.xfrsess._request_data = \
@@ -1561,6 +1513,106 @@ class TestUnixSockServer(unittest.TestCase):
         self.unix._select_loop(self.__select_return_redable[0])
         self.unix._select_loop(self.__select_return_redable[0])
         self.assertEqual(1, self.__select_count)
         self.assertEqual(1, self.__select_count)
 
 
+class DummyBaseSocketserver():
+    def shutdown(self): pass
+    def send(self, arg): pass
+    def get_request(self): pass
+
+class DummySocketserver(DummyBaseSocketserver):
+    def __init__(self, *args): pass
+
+class DummySocketserverException(DummyBaseSocketserver):
+    def __init__(self, *args): raise Exception
+
+class TestUnixSockServerForCounter(unittest.TestCase):
+
+    def setUp(self):
+        (self.orig_remove_unused_sock_file,
+         self.orig_update_config_data,
+         self.orig_socket_socketpair,
+         self.orig_NoPollMixIn,
+         self.orig_ThreadingUnixStreamServer ) = \
+         ( UnixSockServer._remove_unused_sock_file,
+           UnixSockServer.update_config_data,
+           xfrout.socket.socketpair,
+           xfrout.socketserver_mixin.NoPollMixIn,
+           xfrout.ThreadingUnixStreamServer )
+        UnixSockServer._remove_unused_sock_file = lambda x,y: None
+        UnixSockServer.update_config_data = lambda x,y: None
+        xfrout.socket.socketpair = \
+            lambda : (DummySocketserver(), DummySocketserver())
+        xfrout.socketserver_mixin.NoPollMixIn = DummySocketserver
+        xfrout.ThreadingUnixStreamServer = DummySocketserver
+        xfrout.super = lambda : DummySocketserver()
+        self.unix = UnixSockServer(None, None, None, None, None)
+
+    def tearDown(self):
+        ( UnixSockServer._remove_unused_sock_file,
+          UnixSockServer.update_config_data,
+          xfrout.socket.socketpair,
+          xfrout.socketserver_mixin.NoPollMixIn,
+          xfrout.ThreadingUnixStreamServer,
+          xfrout.super ) = \
+          ( self.orig_remove_unused_sock_file,
+            self.orig_update_config_data,
+            self.orig_socket_socketpair,
+            self.orig_NoPollMixIn,
+            self.orig_ThreadingUnixStreamServer,
+            super )
+        counter.clear_counters()
+
+    def test_open(self):
+        # open
+        self.assertEqual(counter.get_unixsocket_open(), 1)
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_unixsocket_openfail)
+        xfrout.ThreadingUnixStreamServer = DummySocketserverException
+        self.unix = UnixSockServer(None, None, None, None, None)
+        self.assertEqual(counter.get_unixsocket_open(), 1)
+        self.assertEqual(counter.get_unixsocket_openfail(), 1)
+
+    def test_close(self):
+        # close
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_unixsocket_close)
+        self.unix.shutdown()
+        self.assertEqual(counter.get_unixsocket_close(), 1)
+
+    def test_bindfail(self):
+        # bindfail
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_unixsocket_bindfail)
+        self.assertRaises(Exception, self.unix.server_bind)
+        self.assertEqual(counter.get_unixsocket_bindfail(), 1)
+
+    def test_accept(self):
+        # accept
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_unixsocket_accept)
+        self.unix.get_request()
+        self.assertEqual(counter.get_unixsocket_accept(), 1)
+        # acceptfail
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_unixsocket_acceptfail)
+        xfrout.super = lambda : DummyClassException()
+        self.unix = UnixSockServer(None, None, None, None, None)
+        self.assertRaises(Exception, self.unix.get_request)
+        self.assertEqual(counter.get_unixsocket_acceptfail(), 1)
+
+    def test_senderr(self):
+        # do inside of above TestXfroutSession
+        pass
+
+    def test_recverr(self):
+        # recverr
+        self.assertRaises(isc.cc.data.DataNotFoundError,
+                          counter.get_unixsocket_recverr)
+        def raise_socketerror():
+            raise socket.error
+        self.unix.get_request = raise_socketerror
+        self.unix.handle_request()
+        self.assertEqual(counter.get_unixsocket_recverr(), 1)
+
 class TestInitialization(unittest.TestCase):
 class TestInitialization(unittest.TestCase):
     def setEnv(self, name, value):
     def setEnv(self, name, value):
         if value is None:
         if value is None:
@@ -1609,116 +1661,6 @@ class MyXfroutServer(XfroutServer):
         self._wait_for_threads = lambda : None
         self._wait_for_threads = lambda : None
         self._cc.get_module_spec = lambda:\
         self._cc.get_module_spec = lambda:\
             isc.config.module_spec_from_file(xfrout.SPECFILE_LOCATION)
             isc.config.module_spec_from_file(xfrout.SPECFILE_LOCATION)
-        # setup an XfroutCount object
-        self._counter = XfroutCounter(
-            self._cc.get_module_spec().get_statistics_spec())
-
-class TestXfroutCounter(unittest.TestCase):
-    def setUp(self):
-        self._module_spec = isc.config.module_spec_from_file(\
-            xfrout.SPECFILE_LOCATION)
-        statistics_spec = self._module_spec.get_statistics_spec()
-        self.xfrout_counter = XfroutCounter(statistics_spec)
-        self._counters = isc.config.spec_name_list(\
-            isc.config.find_spec_part(\
-                statistics_spec, XfroutCounter.perzone_prefix)\
-                ['named_set_item_spec']['map_item_spec'])
-        self._started = threading.Event()
-        self._number = 3 # number of the threads
-        self._cycle = 10000 # number of counting per thread
-
-    def test_get_default_statistics_data(self):
-        self.assertTrue(\
-            self._module_spec.validate_statistics(\
-                True,
-                self.xfrout_counter._get_default_statistics_data(),
-                )
-            )
-
-    def setup_incrementer(self, incrementer, *args):
-        self._started.wait()
-        for i in range(self._cycle): incrementer(*args)
-
-    def start_incrementer(self, incrementer, *args):
-        threads = []
-        for i in range(self._number):
-            threads.append(threading.Thread(\
-                    target=self.setup_incrementer, \
-                        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(\
-            self.xfrout_counter.get_statistics(),\
-                '%s/%s/%s' % (XfroutCounter.perzone_prefix,\
-                                  zone_name, counter_name))
-
-    def test_incdecrementers(self):
-        # for per-zone counters
-        result = { XfroutCounter.entire_server: {},
-                   TEST_ZONE_NAME_STR: {} }
-        for counter_name in self._counters:
-            cntrs_xfrss = \
-                self.xfrout_counter.get_counters_for_xfroutsession()
-            cntrs_notfy = \
-                self.xfrout_counter.get_counters_for_notifyout()
-            cnt_name = 'counter_%s' % counter_name
-            incrementer = None
-            if cnt_name in cntrs_xfrss:
-                incrementer = cntrs_xfrss[cnt_name]
-            else:
-                incrementer = cntrs_notfy[cnt_name]
-            self.start_incrementer(incrementer, TEST_ZONE_NAME_STR)
-            self.assertEqual(self.get_count(\
-                        TEST_ZONE_NAME_STR, counter_name), \
-                                 self._number * self._cycle)
-            self.assertEqual(self.get_count(\
-                    XfroutCounter.entire_server, counter_name), \
-                                 self._number * self._cycle)
-            result[XfroutCounter.entire_server][counter_name] = \
-                result[TEST_ZONE_NAME_STR][counter_name] = \
-                self._number * self._cycle
-        statistics_data = {XfroutCounter.perzone_prefix: result}
-
-        # for {a|i}xfrrunning counters
-        for counter_name in self.xfrout_counter._xfrrunning_names:
-            incrementer = \
-                dict(self.xfrout_counter.get_counters_for_xfroutsession(), \
-                         **self.xfrout_counter.get_counters_for_notifyout())\
-                         ['inc_%s' % counter_name]
-            self.start_incrementer(incrementer)
-            self.assertEqual(
-                self.xfrout_counter.get_statistics()[counter_name],
-                self._number * self._cycle
-                )
-            decrementer = \
-                dict(self.xfrout_counter.get_counters_for_xfroutsession(), \
-                         **self.xfrout_counter.get_counters_for_notifyout())\
-                         ['dec_%s' % counter_name]
-            self.start_incrementer(decrementer)
-            self.assertEqual(
-                self.xfrout_counter.get_statistics()[counter_name],
-                0)
-            statistics_data[counter_name] = 0
-        self.assertEqual(
-            self.xfrout_counter.get_statistics(),
-            statistics_data)
-        self.assertTrue(\
-            self._module_spec.validate_statistics(\
-                True, statistics_data
-                )
-            )
-
-    def test_add_perzone_counter(self):
-        for counter_name in self._counters:
-            self.assertRaises(isc.cc.data.DataNotFoundError,\
-                                  self.get_count, TEST_ZONE_NAME_STR, counter_name)
-        self.xfrout_counter._add_perzone_counter(TEST_ZONE_NAME_STR)
-        for counter_name in self._counters:
-            self.assertEqual(self.get_count(TEST_ZONE_NAME_STR, counter_name), 0)
 
 
 class TestXfroutServer(unittest.TestCase):
 class TestXfroutServer(unittest.TestCase):
     def setUp(self):
     def setUp(self):

+ 60 - 198
src/bin/xfrout/xfrout.py.in

@@ -27,6 +27,7 @@ from socketserver import *
 import os
 import os
 from isc.config.ccsession import *
 from isc.config.ccsession import *
 from isc.cc import SessionError, SessionTimeout
 from isc.cc import SessionError, SessionTimeout
+from isc.statistics import counter
 from isc.notify import notify_out
 from isc.notify import notify_out
 import isc.util.process
 import isc.util.process
 import socket
 import socket
@@ -108,6 +109,9 @@ VERBOSE_MODE = False
 XFROUT_DNS_HEADER_SIZE = 12     # protocol constant
 XFROUT_DNS_HEADER_SIZE = 12     # protocol constant
 XFROUT_MAX_MESSAGE_SIZE = 65535 # ditto
 XFROUT_MAX_MESSAGE_SIZE = 65535 # ditto
 
 
+# setup statistics counter
+counter.init(SPECFILE_LOCATION)
+
 # borrowed from xfrin.py @ #1298.  We should eventually unify it.
 # borrowed from xfrin.py @ #1298.  We should eventually unify it.
 def format_zone_str(zone_name, zone_class):
 def format_zone_str(zone_name, zone_class):
     """Helper function to format a zone name and class as a string of
     """Helper function to format a zone name and class as a string of
@@ -153,8 +157,7 @@ def get_soa_serial(soa_rdata):
 
 
 class XfroutSession():
 class XfroutSession():
     def __init__(self, sock_fd, request_data, server, tsig_key_ring, remote,
     def __init__(self, sock_fd, request_data, server, tsig_key_ring, remote,
-                 default_acl, zone_config, client_class=DataSourceClient,
-                 **counters):
+                 default_acl, zone_config, client_class=DataSourceClient):
         self._sock_fd = sock_fd
         self._sock_fd = sock_fd
         self._request_data = request_data
         self._request_data = request_data
         self._server = server
         self._server = server
@@ -169,13 +172,6 @@ class XfroutSession():
         self.ClientClass = client_class # parameterize this for testing
         self.ClientClass = client_class # parameterize this for testing
         self._soa = None # will be set in _xfrout_setup or in tests
         self._soa = None # will be set in _xfrout_setup or in tests
         self._jnl_reader = None # will be set to a reader for IXFR
         self._jnl_reader = None # will be set to a reader for IXFR
-        # Extract counter handler from the `counters` argument and add
-        # it to the class attribute of the name whose prefix is
-        # '_counter_' '_inc_' or '_dec_'
-        for (k, v) in counters.items():
-            if k.find('counter_') == 0 or k.find('inc_') == 0 \
-                    or k.find('dec_') == 0:
-                setattr(self, "_%s" % k, v)
         self._handle()
         self._handle()
 
 
     def create_tsig_ctx(self, tsig_record, tsig_key_ring):
     def create_tsig_ctx(self, tsig_record, tsig_key_ring):
@@ -279,7 +275,7 @@ class XfroutSession():
             return None, None
             return None, None
         elif acl_result == REJECT:
         elif acl_result == REJECT:
             # count rejected Xfr request by each zone name
             # count rejected Xfr request by each zone name
-            self._counter_xfrrej(zone_name.to_text())
+            counter.inc_xfrrej(zone_name.to_text())
             logger.debug(DBG_XFROUT_TRACE, XFROUT_QUERY_REJECTED,
             logger.debug(DBG_XFROUT_TRACE, XFROUT_QUERY_REJECTED,
                          self._request_type, format_addrinfo(self._remote),
                          self._request_type, format_addrinfo(self._remote),
                          format_zone_str(zone_name, zone_class))
                          format_zone_str(zone_name, zone_class))
@@ -531,23 +527,25 @@ class XfroutSession():
         try:
         try:
             # increment Xfr starts by RRType
             # increment Xfr starts by RRType
             if self._request_type == RRType.AXFR():
             if self._request_type == RRType.AXFR():
-                self._inc_axfr_running()
+                counter.inc_axfr_running()
             else:
             else:
-                self._inc_ixfr_running()
+                counter.inc_ixfr_running()
             logger.info(XFROUT_XFR_TRANSFER_STARTED, self._request_typestr,
             logger.info(XFROUT_XFR_TRANSFER_STARTED, self._request_typestr,
                         format_addrinfo(self._remote), zone_str)
                         format_addrinfo(self._remote), zone_str)
             self._reply_xfrout_query(msg, sock_fd)
             self._reply_xfrout_query(msg, sock_fd)
         except Exception as err:
         except Exception as err:
+            # count unixsockets send errors
+            counter.inc_unixsocket_senderr()
             logger.error(XFROUT_XFR_TRANSFER_ERROR, self._request_typestr,
             logger.error(XFROUT_XFR_TRANSFER_ERROR, self._request_typestr,
                     format_addrinfo(self._remote), zone_str, err)
                     format_addrinfo(self._remote), zone_str, err)
         finally:
         finally:
             # decrement Xfr starts by RRType
             # decrement Xfr starts by RRType
             if self._request_type == RRType.AXFR():
             if self._request_type == RRType.AXFR():
-                self._dec_axfr_running()
+                counter.dec_axfr_running()
             else:
             else:
-                self._dec_ixfr_running()
+                counter.dec_ixfr_running()
         # count done Xfr requests by each zone name
         # count done Xfr requests by each zone name
-        self._counter_xfrreqdone(zone_name.to_text())
+        counter.inc_xfrreqdone(zone_name.to_text())
         logger.info(XFROUT_XFR_TRANSFER_DONE, self._request_typestr,
         logger.info(XFROUT_XFR_TRANSFER_DONE, self._request_typestr,
                     format_addrinfo(self._remote), zone_str)
                     format_addrinfo(self._remote), zone_str)
 
 
@@ -657,18 +655,51 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
     '''The unix domain socket server which accept xfr query sent from auth server.'''
     '''The unix domain socket server which accept xfr query sent from auth server.'''
 
 
     def __init__(self, sock_file, handle_class, shutdown_event, config_data,
     def __init__(self, sock_file, handle_class, shutdown_event, config_data,
-                 cc, **counters):
+                 cc):
         self._remove_unused_sock_file(sock_file)
         self._remove_unused_sock_file(sock_file)
         self._sock_file = sock_file
         self._sock_file = sock_file
         socketserver_mixin.NoPollMixIn.__init__(self)
         socketserver_mixin.NoPollMixIn.__init__(self)
-        ThreadingUnixStreamServer.__init__(self, sock_file, handle_class)
+        try:
+            ThreadingUnixStreamServer.__init__(self, sock_file, \
+                                                   handle_class)
+        except:
+            counter.inc_unixsocket_openfail()
+        else:
+            counter.inc_unixsocket_open()
         self._shutdown_event = shutdown_event
         self._shutdown_event = shutdown_event
         self._write_sock, self._read_sock = socket.socketpair()
         self._write_sock, self._read_sock = socket.socketpair()
         self._common_init()
         self._common_init()
         self._cc = cc
         self._cc = cc
         self.update_config_data(config_data)
         self.update_config_data(config_data)
-        # handlers for statistics use
-        self._counters = counters
+
+    def server_bind(self):
+        """server_bind() overridden for counting bind failed
+        unixsockets
+        """
+        try:
+            # call the server_bind() of class
+            # ThreadingUnixStreamServer
+            return super().server_bind()
+        except:
+            # count bind failed unixsockets
+            counter.inc_unixsocket_bindfail()
+            raise
+
+    def get_request(self):
+        """get_request() overridden for counting successfully accepted
+       unixsockets or failed accepted unixsockets
+        """
+        try:
+            # call the get_request() of class
+            # ThreadingUnixStreamServer
+            ret = super().get_request()
+            # count successfully accepted unixsockets
+            counter.inc_unixsocket_accept()
+            return ret
+        except:
+            # count failed accepted unixsockets
+            counter.inc_unixsocket_acceptfail()
+            raise
 
 
     def _common_init(self):
     def _common_init(self):
         '''Initialization shared with the mock server class used for tests'''
         '''Initialization shared with the mock server class used for tests'''
@@ -701,6 +732,8 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
         try:
         try:
             request, client_address = self.get_request()
             request, client_address = self.get_request()
         except socket.error:
         except socket.error:
+            # count unixsockets receive errors
+            counter.inc_unixsocket_recverr()
             logger.error(XFROUT_FETCH_REQUEST_ERROR)
             logger.error(XFROUT_FETCH_REQUEST_ERROR)
             return
             return
         self._select_loop(request)
         self._select_loop(request)
@@ -823,8 +856,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
         self._lock.release()
         self._lock.release()
         self.RequestHandlerClass(sock_fd, request_data, self,
         self.RequestHandlerClass(sock_fd, request_data, self,
                                  isc.server_common.tsig_keyring.get_keyring(),
                                  isc.server_common.tsig_keyring.get_keyring(),
-                                 self._guess_remote(sock_fd), acl, zone_config,
-                                 **self._counters)
+                                 self._guess_remote(sock_fd), acl, zone_config)
 
 
     def _remove_unused_sock_file(self, sock_file):
     def _remove_unused_sock_file(self, sock_file):
         '''Try to remove the socket file. If the file is being used
         '''Try to remove the socket file. If the file is being used
@@ -862,6 +894,8 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
         self._write_sock.send(b"shutdown") #terminate the xfrout session thread
         self._write_sock.send(b"shutdown") #terminate the xfrout session thread
         super().shutdown() # call the shutdown() of class socketserver_mixin.NoPollMixIn
         super().shutdown() # call the shutdown() of class socketserver_mixin.NoPollMixIn
         try:
         try:
+            # count closed unixsockets
+            counter.inc_unixsocket_close()
             os.unlink(self._sock_file)
             os.unlink(self._sock_file)
         except Exception as e:
         except Exception as e:
             logger.error(XFROUT_REMOVE_UNIX_SOCKET_FILE_ERROR, self._sock_file, str(e))
             logger.error(XFROUT_REMOVE_UNIX_SOCKET_FILE_ERROR, self._sock_file, str(e))
@@ -952,172 +986,6 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
         self._transfers_counter -= 1
         self._transfers_counter -= 1
         self._lock.release()
         self._lock.release()
 
 
-class XfroutCounter:
-    """A class for handling all statistics counters of Xfrout.  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
-        ixfr_running
-        axfr_running
-    """
-    # '_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'
-    def __init__(self, statistics_spec):
-        self._statistics_spec = statistics_spec
-        # holding statistics data for Xfrout module
-        self._statistics_data = {}
-        self._counters_for_xfroutsession = {}
-        self._counters_for_notifyout = {}
-        self._xfrrunning_names = [
-            n for n in isc.config.spec_name_list\
-                (self._statistics_spec) \
-                if n.find('xfr_running') == 1 ]
-        self._lock = threading.RLock()
-        self._create_perzone_incrementers()
-        self._create_xfrrunning_incdecrementers()
-
-    def get_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. Locks the thread because it is considered to be
-        invoked by a multi-threading caller."""
-        # 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 = {}
-        zones = self._statistics_data[self.perzone_prefix]
-        # Start calculation for '_SERVER_' counts
-        attrs = self._get_default_statistics_data()[self.perzone_prefix][self.entire_server]
-        statistics_data = {self.perzone_prefix: {}}
-        for attr in attrs:
-            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]
-        return statistics_data
-
-    def _get_default_statistics_data(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_)
-            statistics_data.update({id_: spec['item_default']})
-        return statistics_data
-
-    def _create_perzone_incrementers(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:
-            def __perzone_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."""
-                with self._lock:
-                    self._add_perzone_counter(zone_name)
-                    self._statistics_data[self.perzone_prefix][zone_name][counter_name] += step
-            if 'notifyout' in item:
-                self._counters_for_notifyout['counter_%s' % item] \
-                    = __perzone_incrementer
-            else:
-                self._counters_for_xfroutsession['counter_%s' % item] \
-                    = __perzone_incrementer
-
-    def _create_xfrrunning_incdecrementers(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 __xfrrunning_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."""
-                with self._lock:
-                    self._add_xfrrunning_counter(counter_name)
-                    self._statistics_data[counter_name] += step
-            def __xfrrunning_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."""
-                with self._lock:
-                    self._statistics_data[counter_name] += step
-            self._counters_for_xfroutsession['inc_%s' % item] \
-                = __xfrrunning_incrementer
-            self._counters_for_xfroutsession['dec_%s' % item] \
-                = __xfrrunning_decrementer
-
-    def get_counters_for_xfroutsession(self):
-        """Returns counters, incrementers, and decrementers to be
-        passed to XfroutSession/UnixSockServer class."""
-        return self._counters_for_xfroutsession
-
-    def get_counters_for_notifyout(self):
-        """Returns counters handlers to be passed to NotifyOut
-        class."""
-        return self._counters_for_notifyout
-
-    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'])
-
 class XfroutServer:
 class XfroutServer:
     def __init__(self):
     def __init__(self):
         self._unix_socket_server = None
         self._unix_socket_server = None
@@ -1125,8 +993,6 @@ class XfroutServer:
         self._shutdown_event = threading.Event()
         self._shutdown_event = threading.Event()
         self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler)
         self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler)
         self._config_data = self._cc.get_full_config()
         self._config_data = self._cc.get_full_config()
-        self._counter = XfroutCounter(
-            self._cc.get_module_spec().get_statistics_spec())
         self._cc.start()
         self._cc.start()
         self._cc.add_remote_config(AUTH_SPECFILE_LOCATION)
         self._cc.add_remote_config(AUTH_SPECFILE_LOCATION)
         isc.server_common.tsig_keyring.init_keyring(self._cc)
         isc.server_common.tsig_keyring.init_keyring(self._cc)
@@ -1140,18 +1006,13 @@ class XfroutServer:
             XfroutSession,
             XfroutSession,
             self._shutdown_event,
             self._shutdown_event,
             self._config_data,
             self._config_data,
-            self._cc,
-            **self._counter.get_counters_for_xfroutsession()
-            )
+            self._cc)
         listener = threading.Thread(target=self._unix_socket_server.serve_forever)
         listener = threading.Thread(target=self._unix_socket_server.serve_forever)
         listener.start()
         listener.start()
 
 
     def _start_notifier(self):
     def _start_notifier(self):
         datasrc = self._unix_socket_server.get_db_file()
         datasrc = self._unix_socket_server.get_db_file()
-        self._notifier = notify_out.NotifyOut(
-            datasrc,
-            **self._counter.get_counters_for_notifyout()
-            )
+        self._notifier = notify_out.NotifyOut(datasrc)
         if 'also_notify' in self._config_data:
         if 'also_notify' in self._config_data:
             for slave in self._config_data['also_notify']:
             for slave in self._config_data['also_notify']:
                 self._notifier.add_slave(slave['address'], slave['port'])
                 self._notifier.add_slave(slave['address'], slave['port'])
@@ -1232,9 +1093,10 @@ class XfroutServer:
             # The log level is here set to debug in order to avoid
             # The log level is here set to debug in order to avoid
             # that a log becomes too verbose. Because the b10-stats
             # that a log becomes too verbose. Because the b10-stats
             # daemon is periodically asking to the b10-xfrout daemon.
             # daemon is periodically asking to the b10-xfrout daemon.
+            answer = create_answer(0, counter.dump_statistics())
             logger.debug(DBG_XFROUT_TRACE, \
             logger.debug(DBG_XFROUT_TRACE, \
-                             XFROUT_RECEIVED_GETSTATS_COMMAND)
-            answer = create_answer(0, self._counter.get_statistics())
+                             XFROUT_RECEIVED_GETSTATS_COMMAND, \
+                             str(answer))
 
 
         else:
         else:
             answer = create_answer(1, "Unknown command:" + str(cmd))
             answer = create_answer(1, "Unknown command:" + str(cmd))