Browse Source

[master] Merge branch 'trac2274'

Naoki Kambe 11 years ago
parent
commit
ca691626a2

+ 21 - 0
src/bin/xfrin/b10-xfrin.xml

@@ -337,6 +337,27 @@ operation
         </listitem>
       </varlistentry><!-- end of zones -->
 
+      <varlistentry>
+        <term>ixfr_running</term>
+        <listitem><simpara>
+          Number of IXFRs in progress
+        </simpara></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>axfr_running</term>
+        <listitem><simpara>
+          Number of AXFRs in progress
+        </simpara></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>soa_in_progress</term>
+        <listitem><simpara>
+          Number of SOA queries in progress
+        </simpara></listitem>
+      </varlistentry>
+
     </variablelist>
 
     <para>

+ 122 - 35
src/bin/xfrin/tests/xfrin_test.py

@@ -2144,16 +2144,19 @@ class TestStatisticsXfrinConn(TestXfrinConnection):
         self._const_sec = round(delta.days * 86400 + delta.seconds +
                                 delta.microseconds * 1E-6, 6)
         # List of statistics counter names and expected initial values
-        self.__name_to_counter = (('axfrreqv4', 0),
-                                 ('axfrreqv6', 0),
-                                 ('ixfrreqv4', 0),
-                                 ('ixfrreqv6', 0),
-                                 ('last_axfr_duration', 0.0),
-                                 ('last_ixfr_duration', 0.0),
-                                 ('soaoutv4', 0),
-                                 ('soaoutv6', 0),
-                                 ('xfrfail', 0),
-                                 ('xfrsuccess', 0))
+        self.__name_to_perzone_counter = (('axfrreqv4', 0),
+                                          ('axfrreqv6', 0),
+                                          ('ixfrreqv4', 0),
+                                          ('ixfrreqv6', 0),
+                                          ('last_axfr_duration', 0.0),
+                                          ('last_ixfr_duration', 0.0),
+                                          ('soaoutv4', 0),
+                                          ('soaoutv6', 0),
+                                          ('xfrfail', 0),
+                                          ('xfrsuccess', 0))
+        self.__name_to_counter = ('soa_in_progress',
+                                  'ixfr_running',
+                                  'axfr_running')
         self.__zones = 'zones'
 
     def tearDown(self):
@@ -2168,25 +2171,41 @@ class TestStatisticsXfrinConn(TestXfrinConnection):
     def _check_init_statistics(self):
         '''checks exception being raised if not incremented statistics
         counter gotten'''
-        for (name, exp) in self.__name_to_counter:
+        for (name, exp) in self.__name_to_perzone_counter:
             self.assertRaises(isc.cc.data.DataNotFoundError,
                               self.conn._counters.get, self.__zones,
                               TEST_ZONE_NAME_STR, name)
+        for name in self.__name_to_counter:
+            self.assertRaises(isc.cc.data.DataNotFoundError,
+                              self.conn._counters.get, name)
 
-    def _check_updated_statistics(self, overwrite):
+    def _check_updated_perzone_statistics(self, overwrite):
         '''checks getting expect values after updating the pairs of
-        statistics counter name and value on to the "overwrite"
+        per-zone statistics counter name and value on to the "overwrite"
         dictionary'''
-        name2count = dict(self.__name_to_counter)
+        name2count = dict(self.__name_to_perzone_counter)
         name2count.update(overwrite)
         for (name, exp) in name2count.items():
             act = self.conn._counters.get(self.__zones,
                                           TEST_RRCLASS_STR,
                                           TEST_ZONE_NAME_STR,
                                           name)
-            msg = '%s is expected %s but actually %s' % (name, exp, act)
+            msg = '%s: expected %s but actually got %s' % (name, exp, act)
             self.assertEqual(exp, act, msg=msg)
 
+    def _check_updated_statistics(self, expects):
+        '''checks counters in expects are incremented. also checks other
+        counters which are not in expects are not incremented.'''
+        for name in self.__name_to_counter:
+            if name in expects:
+                exp = expects[name]
+                act = self.conn._counters.get(name)
+                msg = '%s: expected %s but actually got %s' % (name, exp, act)
+                self.assertEqual(exp, act, msg=msg)
+            else:
+                self.assertRaises(isc.cc.data.DataNotFoundError,
+                                  self.conn._counters.get, name)
+
 class TestStatisticsXfrinAXFRv4(TestStatisticsXfrinConn):
     '''Xfrin AXFR tests for IPv4 to check statistics counters'''
     def test_soaout(self):
@@ -2195,7 +2214,7 @@ class TestStatisticsXfrinAXFRv4(TestStatisticsXfrinConn):
         self.conn.response_generator = self._create_soa_response_data
         self._check_init_statistics()
         self.assertEqual(self.conn._check_soa_serial(), XFRIN_OK)
-        self._check_updated_statistics({'soaout' + self._ipver: 1})
+        self._check_updated_perzone_statistics({'soaout' + self._ipver: 1})
 
     def test_axfrreq_xfrsuccess_last_axfr_duration(self):
         '''tests that axfrreqv4 or axfrreqv6 and xfrsuccess counters
@@ -2203,9 +2222,10 @@ class TestStatisticsXfrinAXFRv4(TestStatisticsXfrinConn):
         self.conn.response_generator = self._create_normal_response_data
         self._check_init_statistics()
         self.assertEqual(self.conn.do_xfrin(False), XFRIN_OK)
-        self._check_updated_statistics({'axfrreq' + self._ipver: 1,
-                                        'xfrsuccess': 1,
-                                        'last_axfr_duration': self._const_sec})
+        self._check_updated_perzone_statistics({'axfrreq' + self._ipver: 1,
+                                                'xfrsuccess': 1,
+                                                'last_axfr_duration':
+                                                    self._const_sec})
 
     def test_axfrreq_xfrsuccess_last_axfr_duration2(self):
         '''tests that axfrreqv4 or axfrreqv6 and xfrsuccess counters
@@ -2216,10 +2236,10 @@ class TestStatisticsXfrinAXFRv4(TestStatisticsXfrinConn):
         self.conn._handle_xfrin_responses = exception_raiser
         self._check_init_statistics()
         self.assertEqual(self.conn.do_xfrin(False), XFRIN_OK)
-        self._check_updated_statistics({'axfrreq' + self._ipver: 1,
-                                        'xfrsuccess': 1,
-                                        'last_axfr_duration':
-                                            self._const_sec})
+        self._check_updated_perzone_statistics({'axfrreq' + self._ipver: 1,
+                                                'xfrsuccess': 1,
+                                                'last_axfr_duration':
+                                                    self._const_sec})
 
     def test_axfrreq_xfrfail(self):
         '''tests that axfrreqv4 or axfrreqv6 and xfrfail counters are
@@ -2235,8 +2255,47 @@ class TestStatisticsXfrinAXFRv4(TestStatisticsXfrinConn):
             self.conn._handle_xfrin_responses = exception_raiser
             self.assertEqual(self.conn.do_xfrin(False), XFRIN_FAIL)
             count += 1
-            self._check_updated_statistics({'axfrreq' + self._ipver: count,
-                                            'xfrfail': count})
+            self._check_updated_perzone_statistics({'axfrreq' + self._ipver:
+                                                        count,
+                                                    'xfrfail': count})
+
+    def test_soa_in_progress1(self):
+        '''tests that an soa_in_progress counter is incremented and decremented
+        when an soa query succeeds'''
+        self.conn.response_generator = self._create_soa_response_data
+        self._check_init_statistics()
+        self.assertEqual(self.conn._check_soa_serial(), XFRIN_OK)
+        self._check_updated_statistics({'soa_in_progress': 0})
+
+    def test_soa_in_progress2(self):
+        '''tests that an soa_in_progress counter is incremented and decremented
+        even if socket.error is raised from XfrinConnection._send_query()'''
+        def exception_raiser(x):
+            raise socket.error()
+        self.conn._send_query = exception_raiser
+        self._check_init_statistics()
+        self.assertRaises(socket.error, self.conn._check_soa_serial)
+        self._check_updated_statistics({'soa_in_progress': 0})
+
+    def test_axfr_running1(self):
+        '''tests that axfr_running counter is incremented and decremented'''
+        self.conn.response_generator = self._create_normal_response_data
+        self._check_init_statistics()
+        self.assertEqual(self.conn.do_xfrin(False), XFRIN_OK)
+        self._check_updated_statistics({'axfr_running': 0})
+
+    def test_axfr_running2(self):
+        '''tests that axfr_running counter is incremented and decremented even
+        if some failure exceptions are expected to be raised inside do_xfrin():
+        XfrinZoneError, XfrinProtocolError, XfrinException, and Exception'''
+        self._check_init_statistics()
+        for ex in [XfrinZoneError, XfrinProtocolError, XfrinException,
+                   Exception]:
+            def exception_raiser():
+                raise ex()
+            self.conn._handle_xfrin_responses = exception_raiser
+            self.assertEqual(self.conn.do_xfrin(False), XFRIN_FAIL)
+            self._check_updated_statistics({'axfr_running': 0})
 
 class TestStatisticsXfrinIXFRv4(TestStatisticsXfrinConn):
     '''Xfrin IXFR tests for IPv4 to check statistics counters'''
@@ -2251,10 +2310,10 @@ class TestStatisticsXfrinIXFRv4(TestStatisticsXfrinConn):
         self.conn.response_generator = create_ixfr_response
         self._check_init_statistics()
         self.assertEqual(XFRIN_OK, self.conn.do_xfrin(False, RRType.IXFR))
-        self._check_updated_statistics({'ixfrreq' + self._ipver: 1,
-                                        'xfrsuccess': 1,
-                                        'last_ixfr_duration':
-                                            self._const_sec})
+        self._check_updated_perzone_statistics({'ixfrreq' + self._ipver: 1,
+                                                'xfrsuccess': 1,
+                                                'last_ixfr_duration':
+                                                    self._const_sec})
 
     def test_ixfrreq_xfrsuccess_last_ixfr_duration2(self):
         '''tests that ixfrreqv4 or ixfrreqv6 and xfrsuccess counters
@@ -2265,10 +2324,10 @@ class TestStatisticsXfrinIXFRv4(TestStatisticsXfrinConn):
         self.conn._handle_xfrin_responses = exception_raiser
         self._check_init_statistics()
         self.assertEqual(self.conn.do_xfrin(False, RRType.IXFR), XFRIN_OK)
-        self._check_updated_statistics({'ixfrreq' + self._ipver: 1,
-                                        'xfrsuccess': 1,
-                                        'last_ixfr_duration':
-                                            self._const_sec})
+        self._check_updated_perzone_statistics({'ixfrreq' + self._ipver: 1,
+                                                'xfrsuccess': 1,
+                                                'last_ixfr_duration':
+                                                    self._const_sec})
 
     def test_ixfrreq_xfrfail(self):
         '''tests that ixfrreqv4 or ixfrreqv6 and xfrfail counters are
@@ -2284,8 +2343,36 @@ class TestStatisticsXfrinIXFRv4(TestStatisticsXfrinConn):
             self.conn._handle_xfrin_responses = exception_raiser
             self.assertEqual(self.conn.do_xfrin(False, RRType.IXFR), XFRIN_FAIL)
             count += 1
-            self._check_updated_statistics({'ixfrreq' + self._ipver: count,
-                                            'xfrfail': count})
+            self._check_updated_perzone_statistics({'ixfrreq' + self._ipver:
+                                                        count,
+                                                    'xfrfail': count})
+
+    def test_ixfr_running1(self):
+        '''tests that ixfr_running counter is incremented and decremented'''
+        def create_ixfr_response():
+            self.conn.reply_data = self.conn.create_response_data(
+                questions=[Question(TEST_ZONE_NAME, TEST_RRCLASS,
+                                    RRType.IXFR)],
+                answers=[soa_rrset, begin_soa_rrset, soa_rrset, soa_rrset])
+        self.conn.response_generator = create_ixfr_response
+        self._check_init_statistics()
+        self.assertEqual(XFRIN_OK, self.conn.do_xfrin(False, RRType.IXFR))
+        self._check_updated_statistics({'ixfr_running': 0})
+
+    def test_ixfr_running2(self):
+        '''tests that ixfr_running counter is incremented and decremented even
+        if some failure exceptions are expected to be raised inside do_xfrin():
+        XfrinZoneError, XfrinProtocolError, XfrinException, and Exception'''
+        self._check_init_statistics()
+        count = 0
+        for ex in [XfrinZoneError, XfrinProtocolError, XfrinException,
+                   Exception]:
+            def exception_raiser():
+                raise ex()
+            self.conn._handle_xfrin_responses = exception_raiser
+            self.assertEqual(self.conn.do_xfrin(False, RRType.IXFR), XFRIN_FAIL)
+            count += 1
+            self._check_updated_statistics({'ixfr_running': 0})
 
 class TestStatisticsXfrinAXFRv6(TestStatisticsXfrinAXFRv4):
     '''Same tests as TestStatisticsXfrinAXFRv4 for IPv6'''

+ 40 - 27
src/bin/xfrin/xfrin.py.in

@@ -877,37 +877,44 @@ class XfrinConnection(asyncore.dispatcher):
 
         '''
 
-        self._send_query(RRType.SOA)
-        # count soaoutv4 or soaoutv6 requests
-        self._counters.inc('zones', self._rrclass.to_text(),
-                           self._zone_name.to_text(), 'soaout' +
-                           self._get_ipver_str())
-        data_len = self._get_request_response(2)
-        msg_len = socket.htons(struct.unpack('H', data_len)[0])
-        soa_response = self._get_request_response(msg_len)
-        msg = Message(Message.PARSE)
-        msg.from_wire(soa_response, Message.PRESERVE_ORDER)
-
-        # Validate/parse the rest of the response, and extract the SOA
-        # from the answer section
-        soa = self.__parse_soa_response(msg, soa_response)
-
-        # Compare the two serials.  If ours is 'new', abort with ZoneUptodate.
-        primary_serial = get_soa_serial(soa.get_rdata()[0])
-        if self._request_serial is not None and \
-                self._request_serial >= primary_serial:
-            if self._request_serial != primary_serial:
-                logger.info(XFRIN_ZONE_SERIAL_AHEAD, primary_serial,
-                            self.zone_str(),
-                            format_addrinfo(self._master_addrinfo),
-                            self._request_serial)
-            raise XfrinZoneUptodate
-
-        return XFRIN_OK
+        # increment SOA query in progress
+        self._counters.inc('soa_in_progress')
+        try:
+            self._send_query(RRType.SOA)
+            # count soaoutv4 or soaoutv6 requests
+            self._counters.inc('zones', self._rrclass.to_text(),
+                               self._zone_name.to_text(), 'soaout' +
+                               self._get_ipver_str())
+            data_len = self._get_request_response(2)
+            msg_len = socket.htons(struct.unpack('H', data_len)[0])
+            soa_response = self._get_request_response(msg_len)
+            msg = Message(Message.PARSE)
+            msg.from_wire(soa_response, Message.PRESERVE_ORDER)
+
+            # Validate/parse the rest of the response, and extract the SOA
+            # from the answer section
+            soa = self.__parse_soa_response(msg, soa_response)
+
+            # Compare the two serials.  If ours is 'new', abort with ZoneUptodate.
+            primary_serial = get_soa_serial(soa.get_rdata()[0])
+            if self._request_serial is not None and \
+                    self._request_serial >= primary_serial:
+                if self._request_serial != primary_serial:
+                    logger.info(XFRIN_ZONE_SERIAL_AHEAD, primary_serial,
+                                self.zone_str(),
+                                format_addrinfo(self._master_addrinfo),
+                                self._request_serial)
+                raise XfrinZoneUptodate
+
+            return XFRIN_OK
+        finally:
+            # decrement SOA query in progress
+            self._counters.dec('soa_in_progress')
 
     def do_xfrin(self, check_soa, request_type=RRType.AXFR):
         '''Do an xfr session by sending xfr request and parsing responses.'''
 
+        xfer_started = False # Don't set True until xfer is started
         try:
             ret = XFRIN_OK
             self._request_type = request_type
@@ -919,6 +926,9 @@ class XfrinConnection(asyncore.dispatcher):
                 if not self.connect_to_master():
                     raise XfrinException('Unable to reconnect to master')
 
+            xfer_started = True
+            # increment xfer running
+            self._counters.inc(req_str.lower() + '_running')
             # start statistics timer
             # Note: If the timer for the zone is already started but
             # not yet stopped due to some error, the last start time
@@ -1009,6 +1019,9 @@ class XfrinConnection(asyncore.dispatcher):
                                           self._zone_name.to_text(),
                                           'last_' + req_str.lower() +
                                           '_duration')
+            # decrement xfer running only if started
+            if xfer_started:
+                self._counters.dec(req_str.lower() + '_running')
             # Make sure any remaining transaction in the diff is closed
             # (if not yet - possible in case of xfr-level exception) as soon
             # as possible

+ 24 - 0
src/bin/xfrin/xfrin.spec

@@ -250,6 +250,30 @@
             ]
           }
         }
+      },
+      {
+        "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": "soa_in_progress",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "SOA queries",
+        "item_description": "Number of SOA queries in progress"
       }
     ]
   }

+ 80 - 54
tests/lettuce/features/xfrin_notify_handling.feature

@@ -28,8 +28,8 @@ Feature: Xfrin incoming notify handling
     # Test1 for Xfrout statistics
     #
     check initial statistics not containing example.org for Xfrout with cmdctl port 47804 except for the following items
-      | item_name                | item_max | item_min |
-      | socket.unixdomain.open   |        1 |        0 |
+      | item_name                | min_value | max_value |
+      | socket.unixdomain.open   |         0 |         1 |
     # Note: .Xfrout.socket.unixdomain.open can be either expected to
     # be 0 or 1 here.  The reason is: if b10-xfrout has started up and is
     # ready for a request from b10-stats, then b10-stats does request
@@ -41,7 +41,13 @@ Feature: Xfrin incoming notify handling
     #
     # Test2 for Xfrin statistics
     #
-    check initial statistics not containing example.org for Xfrin
+    check initial statistics not containing example.org for Xfrin except for the following items
+      | item_name       | min_value | max_value |
+      | soa_in_progress |         0 |         1 |
+      | axfr_running    |         0 |         1 |
+    # Note: soa_in_progress and axfr_running cannot be always a fixed value. The
+    # reason is same as the case of .Xfrout.socket.unixdomain.open. as described
+    # above.
 
     When I send bind10 with cmdctl port 47804 the command Xfrout notify example.org IN
     Then wait for new master stderr message XFROUT_NOTIFY_COMMAND
@@ -99,17 +105,19 @@ Feature: Xfrin incoming notify handling
     wait for new bind10 stderr message XFRIN_RECEIVED_COMMAND
     last bindctl output should not contain "error"
 
-    When I query statistics zones of bind10 module Xfrin with cmdctl
-    The statistics counters are 0 in category .Xfrin.zones.IN except for the following items
-      | item_name                       | item_value | min_value |
-      | _SERVER_.soaoutv6               |          1 |           |
-      | _SERVER_.axfrreqv6              |          1 |           |
-      | _SERVER_.xfrsuccess             |          1 |           |
-      | _SERVER_.last_axfr_duration     |            |       0.0 |
-      | example.org..soaoutv6           |          1 |           |
-      | example.org..axfrreqv6          |          1 |           |
-      | example.org..xfrsuccess         |          1 |           |
-      | example.org..last_axfr_duration |            |       0.0 |
+    When I query statistics of bind10 module Xfrin with cmdctl
+    The statistics counters are 0 in category .Xfrin except for the following items
+      | item_name                                | item_value | min_value |
+      | zones.IN._SERVER_.soaoutv6               |          1 |           |
+      | zones.IN._SERVER_.axfrreqv6              |          1 |           |
+      | zones.IN._SERVER_.xfrsuccess             |          1 |           |
+      | zones.IN._SERVER_.last_axfr_duration     |            |       0.0 |
+      | zones.IN.example.org..soaoutv6           |          1 |           |
+      | zones.IN.example.org..axfrreqv6          |          1 |           |
+      | zones.IN.example.org..xfrsuccess         |          1 |           |
+      | zones.IN.example.org..last_axfr_duration |            |       0.0 |
+      | soa_in_progress                          |          0 |           |
+      | axfr_running                             |          0 |           |
 
     #
     # Test for handling incoming notify only in IPv4
@@ -136,14 +144,18 @@ Feature: Xfrin incoming notify handling
     # Test1 for Xfrout statistics
     #
     check initial statistics not containing example.org for Xfrout with cmdctl port 47804 except for the following items
-      | item_name                | item_max | item_min |
-      | socket.unixdomain.open   |        1 |        0 |
+      | item_name                | min_value | max_value |
+      | socket.unixdomain.open   |         0 |         1 |
     # Note: See above about .Xfrout.socket.unixdomain.open.
 
     #
     # Test2 for Xfrin statistics
     #
-    check initial statistics not containing example.org for Xfrin
+    check initial statistics not containing example.org for Xfrin except for the following items
+      | item_name       | min_value | max_value |
+      | soa_in_progress |         0 |         1 |
+      | axfr_running    |         0 |         1 |
+    # Note: See above about soa_in_progress and axfr_running of Xfrin
 
     When I send bind10 with cmdctl port 47804 the command Xfrout notify example.org IN
     Then wait for new master stderr message XFROUT_NOTIFY_COMMAND
@@ -201,17 +213,19 @@ Feature: Xfrin incoming notify handling
     wait for new bind10 stderr message XFRIN_RECEIVED_COMMAND
     last bindctl output should not contain "error"
 
-    When I query statistics zones of bind10 module Xfrin with cmdctl
-    The statistics counters are 0 in category .Xfrin.zones.IN except for the following items
-      | item_name                       | item_value | min_value |
-      | _SERVER_.soaoutv4               |          1 |           |
-      | _SERVER_.axfrreqv4              |          1 |           |
-      | _SERVER_.xfrsuccess             |          1 |           |
-      | _SERVER_.last_axfr_duration     |            |       0.0 |
-      | example.org..soaoutv4           |          1 |           |
-      | example.org..axfrreqv4          |          1 |           |
-      | example.org..xfrsuccess         |          1 |           |
-      | example.org..last_axfr_duration |            |       0.0 |
+    When I query statistics of bind10 module Xfrin with cmdctl
+    The statistics counters are 0 in category .Xfrin except for the following items
+      | item_name                                | item_value | min_value |
+      | zones.IN._SERVER_.soaoutv4               |          1 |           |
+      | zones.IN._SERVER_.axfrreqv4              |          1 |           |
+      | zones.IN._SERVER_.xfrsuccess             |          1 |           |
+      | zones.IN._SERVER_.last_axfr_duration     |            |       0.0 |
+      | zones.IN.example.org..soaoutv4           |          1 |           |
+      | zones.IN.example.org..axfrreqv4          |          1 |           |
+      | zones.IN.example.org..xfrsuccess         |          1 |           |
+      | zones.IN.example.org..last_axfr_duration |            |       0.0 |
+      | soa_in_progress                          |          0 |           |
+      | axfr_running                             |          0 |           |
 
     #
     # Test for Xfr request rejected
@@ -238,14 +252,18 @@ Feature: Xfrin incoming notify handling
     # Test1 for Xfrout statistics
     #
     check initial statistics not containing example.org for Xfrout with cmdctl port 47804 except for the following items
-      | item_name                | item_max | item_min |
-      | socket.unixdomain.open   |        1 |        0 |
+      | item_name                | min_value | max_value |
+      | socket.unixdomain.open   |         0 |         1 |
     # Note: See above about .Xfrout.socket.unixdomain.open.
 
     #
     # Test2 for Xfrin statistics
     #
-    check initial statistics not containing example.org for Xfrin
+    check initial statistics not containing example.org for Xfrin except for the following items
+      | item_name       | min_value | max_value |
+      | soa_in_progress |         0 |         1 |
+      | axfr_running    |         0 |         1 |
+    # Note: See above about soa_in_progress and axfr_running of Xfrin
 
     #
     # set transfer_acl rejection
@@ -309,15 +327,17 @@ Feature: Xfrin incoming notify handling
     wait for new bind10 stderr message XFRIN_RECEIVED_COMMAND
     last bindctl output should not contain "error"
 
-    When I query statistics zones of bind10 module Xfrin with cmdctl
-    The statistics counters are 0 in category .Xfrin.zones.IN except for the following items
-      | item_name              | item_value |
-      | _SERVER_.soaoutv6      |          1 |
-      | _SERVER_.axfrreqv6     |          1 |
-      | _SERVER_.xfrfail       |          1 |
-      | example.org..soaoutv6  |          1 |
-      | example.org..axfrreqv6 |          1 |
-      | example.org..xfrfail   |          1 |
+    When I query statistics of bind10 module Xfrin with cmdctl
+    The statistics counters are 0 in category .Xfrin except for the following items
+      | item_name                       | item_value | min_value |
+      | zones.IN._SERVER_.soaoutv6      |            |         1 |
+      | zones.IN._SERVER_.axfrreqv6     |            |         1 |
+      | zones.IN._SERVER_.xfrfail       |            |         1 |
+      | zones.IN.example.org..soaoutv6  |            |         1 |
+      | zones.IN.example.org..axfrreqv6 |            |         1 |
+      | zones.IN.example.org..xfrfail   |            |         1 |
+      | soa_in_progress                 |            |         0 |
+      | axfr_running                    |            |         0 |
 
     #
     # Test for Xfr request rejected in IPv4
@@ -344,14 +364,18 @@ Feature: Xfrin incoming notify handling
     # Test1 for Xfrout statistics
     #
     check initial statistics not containing example.org for Xfrout with cmdctl port 47804 except for the following items
-      | item_name                | item_max | item_min |
-      | socket.unixdomain.open   |        1 |        0 |
+      | item_name                | min_value | max_value |
+      | socket.unixdomain.open   |         0 |         1 |
     # Note: See above about .Xfrout.socket.unixdomain.open.
 
     #
     # Test2 for Xfrin statistics
     #
-    check initial statistics not containing example.org for Xfrin
+    check initial statistics not containing example.org for Xfrin except for the following items
+      | item_name       | min_value | max_value |
+      | soa_in_progress |         0 |         1 |
+      | axfr_running    |         0 |         1 |
+    # Note: See above about soa_in_progress and axfr_running of Xfrin
 
     #
     # set transfer_acl rejection
@@ -415,15 +439,17 @@ Feature: Xfrin incoming notify handling
     wait for new bind10 stderr message XFRIN_RECEIVED_COMMAND
     last bindctl output should not contain "error"
 
-    When I query statistics zones of bind10 module Xfrin with cmdctl
-    The statistics counters are 0 in category .Xfrin.zones.IN except for the following items
-      | item_name              | item_value |
-      | _SERVER_.soaoutv4      |          1 |
-      | _SERVER_.axfrreqv4     |          1 |
-      | _SERVER_.xfrfail       |          1 |
-      | example.org..soaoutv4  |          1 |
-      | example.org..axfrreqv4 |          1 |
-      | example.org..xfrfail   |          1 |
+    When I query statistics of bind10 module Xfrin with cmdctl
+    The statistics counters are 0 in category .Xfrin except for the following items
+      | item_name                       | item_value | min_value |
+      | zones.IN._SERVER_.soaoutv4      |            |         1 |
+      | zones.IN._SERVER_.axfrreqv4     |            |         1 |
+      | zones.IN._SERVER_.xfrfail       |            |         1 |
+      | zones.IN.example.org..soaoutv4  |            |         1 |
+      | zones.IN.example.org..axfrreqv4 |            |         1 |
+      | zones.IN.example.org..xfrfail   |            |         1 |
+      | soa_in_progress                 |            |         0 |
+      | axfr_running                    |            |         0 |
 
     #
     # Test for unreachable slave
@@ -456,8 +482,8 @@ Feature: Xfrin incoming notify handling
     When I query statistics zones of bind10 module Xfrout with cmdctl port 47804
     The statistics counters are 0 in category .Xfrout.zones.IN except for the following items
       | item_name                | min_value | max_value |
-      | _SERVER_.notifyoutv6     |         1 |	       5 |
-      | example.org..notifyoutv6 |         1 |	       5 |
+      | _SERVER_.notifyoutv6     |         1 |         5 |
+      | example.org..notifyoutv6 |         1 |         5 |
 
     When I query statistics socket of bind10 module Xfrout with cmdctl port 47804
     The statistics counters are 0 in category .Xfrout.socket.unixdomain except for the following items