BIND 10 trac2989, updated. 311b72638fc8b1a8f5503b1b70af0fe2a79a84c0 [2989] Don't pre-fill list of zones.

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Jul 25 08:39:45 UTC 2013


The branch, trac2989 has been updated
       via  311b72638fc8b1a8f5503b1b70af0fe2a79a84c0 (commit)
      from  a97c67c75cae58f677c56c6344d040046b7dba25 (commit)

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 311b72638fc8b1a8f5503b1b70af0fe2a79a84c0
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Thu Jul 25 10:22:35 2013 +0200

    [2989] Don't pre-fill list of zones.
    
    Load the zone infos on demand, when the zone is first notified.
    
    They need to be cleared when not needed, but this is for another future
    ticket.

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

Summary of changes:
 src/lib/python/isc/notify/notify_out.py            |   61 +++++++++++--------
 src/lib/python/isc/notify/notify_out_messages.mes  |    7 +--
 src/lib/python/isc/notify/tests/notify_out_test.py |   64 ++++++++++++++++----
 3 files changed, 90 insertions(+), 42 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/python/isc/notify/notify_out.py b/src/lib/python/isc/notify/notify_out.py
index fb4cdd3..17267bd 100644
--- a/src/lib/python/isc/notify/notify_out.py
+++ b/src/lib/python/isc/notify/notify_out.py
@@ -132,6 +132,7 @@ class NotifyOut:
     in another thread. '''
     def __init__(self, initial_config, verbose=True):
         self._notify_infos = {} # key is (zone_name, zone_class)
+        self._additional_slaves = []
         self._waiting_zones = []
         self._notifying_zones = []
         self._serving = False
@@ -150,30 +151,39 @@ class NotifyOut:
         self._datasources = {}
         self._reconfigure_datasrc(initial_config)
 
-    def _init_notify_out(self, datasrc_file):
-        '''Get all the zones name and its notify target's address.
+    def _ensure_zone(self, zone_name, zone_class):
+        """
+        Ensure the given zone is available in the _notify_infos.
 
-        TODO, currently the zones are got by going through the zone
-        table in database. There should be a better way to get them
-        and also the setting 'also_notify', and there should be one
-        mechanism to cover the changed datasrc.
+        If it is not there yet, try to add it based on information
+        from the currently configured data sources.
 
-        TODO: Remove, replace, etc.
+        Return true if the zone is there at the end of the function,
+        false if not (in case it was not there and was not found in
+        any data source.
+        """
+        zone_id = (zone_name, zone_class)
+        if zone_id in self._notify_infos:
+            return True # Already there.
 
-        '''
-        for zone_name, zone_class in sqlite3_ds.get_zones_info(datasrc_file):
-            zone_id = (zone_name, zone_class)
-            self._notify_infos[zone_id] = ZoneNotifyInfo(zone_name, zone_class)
-            slaves = self._get_notify_slaves_from_ns(Name(zone_name),
-                                                     RRClass(zone_class))
-            for item in slaves:
-                self._notify_infos[zone_id].notify_slaves.append((item, 53))
+        slaves, found = self._get_notify_slaves_from_ns(Name(zone_name),
+                                                        RRClass(zone_class))
+        if not found:
+            return False
+
+        self._notify_infos[zone_id] = ZoneNotifyInfo(zone_name, zone_class)
+        for item in slaves:
+            self._notify_infos[zone_id].notify_slaves.append((item, 53))
+        for item in self._additional_slaves:
+            self._notify_infos[zone_id].notify_slaves.append(item)
+
+        return True # Just added
 
     def add_slave(self, address, port):
-        for zone_name, zone_class in sqlite3_ds.get_zones_info(self._db_file):
-            zone_id = (zone_name, zone_class)
-            if zone_id in self._notify_infos:
-                self._notify_infos[zone_id].notify_slaves.append((address, port))
+        slave = (address, port)
+        self._additional_slaves.append(slave)
+        for info in self._notify_infos:
+            info.notify_slaves.append(slave)
 
     def send_notify(self, zone_name, zone_class='IN'):
         '''Send notify to one zone's slaves, this function is
@@ -186,12 +196,13 @@ class NotifyOut:
         if zone_name[len(zone_name) - 1] != '.':
             zone_name += '.'
 
+        self._ensure_zone(zone_name, zone_class)
         zone_id = (zone_name, zone_class)
         if zone_id not in self._notify_infos:
             return False
 
         # Has no slave servers, skip it.
-        if (len(self._notify_infos[zone_id].notify_slaves) <= 0):
+        if not self._notify_infos[zone_id].notify_slaves:
             return True
 
         with self._lock:
@@ -313,25 +324,25 @@ class NotifyOut:
         else:
             logger.error(NOTIFY_OUT_DATASRC_CLASS_NOT_FOUND,
                          zone_class)
-            return []
+            return [], False
 
         client, finder, _ = client_list.find(zone_name, True)
         if finder is None:
             logger.error(NOTIFY_OUT_DATASRC_ZONE_NOT_FOUND,
                          format_zone_str(zone_name, zone_class))
-            return []
+            return [], False
 
         result, ns_rrset, _ = finder.find(zone_name, RRType.NS)
         if result is not finder.SUCCESS or ns_rrset is None:
             logger.warn(NOTIFY_OUT_ZONE_NO_NS,
                         format_zone_str(zone_name, zone_class))
-            return []
+            return [], True
         result, soa_rrset, _ = finder.find(zone_name, RRType.SOA)
         if result is not finder.SUCCESS or soa_rrset is None or \
                 soa_rrset.get_rdata_count() != 1:
             logger.warn(NOTIFY_OUT_ZONE_BAD_SOA,
                         format_zone_str(zone_name, zone_class))
-            return []           # broken zone anyway, stop here.
+            return [], True           # broken zone anyway, stop here.
         soa_mname = Name(soa_rrset.get_rdata()[0].to_text().split(' ')[0])
 
         addrs = []
@@ -350,7 +361,7 @@ class NotifyOut:
                     addrs.extend([aaaa.to_text()
                                     for aaaa in rrset.get_rdata()])
 
-        return addrs
+        return addrs, True
 
     def _prepare_select_info(self):
         '''
diff --git a/src/lib/python/isc/notify/notify_out_messages.mes b/src/lib/python/isc/notify/notify_out_messages.mes
index da4afdd..0f71a42 100644
--- a/src/lib/python/isc/notify/notify_out_messages.mes
+++ b/src/lib/python/isc/notify/notify_out_messages.mes
@@ -21,10 +21,9 @@ zone class is not found in the configuration.
 
 % NOTIFY_OUT_DATASRC_ZONE_NOT_FOUND zone %1 is not found
 notify_out attempted to get slave information of a zone but the zone
-isn't found in the expected data source.  This shouldn't happen,
-because notify_out first identifies a list of available zones before
-this process.  So this means some critical inconsistency in the data
-source or software bug.
+isn't found in the expected data source. It can happen when manually
+asked to notify a zone that does not exist. If it happens in other
+circumstances, it's likely a software bug.
 
 % NOTIFY_OUT_INVALID_ADDRESS invalid address %1: %2
 The notify_out library tried to send a notify message to the given
diff --git a/src/lib/python/isc/notify/tests/notify_out_test.py b/src/lib/python/isc/notify/tests/notify_out_test.py
index ce092f2..2d024bb 100644
--- a/src/lib/python/isc/notify/tests/notify_out_test.py
+++ b/src/lib/python/isc/notify/tests/notify_out_test.py
@@ -130,6 +130,7 @@ class TestNotifyOut(unittest.TestCase):
         self._db_file = TESTDATA_SRCDIR + '/test.sqlite3'
         self._config = self.get_dsrc_config(self._db_file)
         self._notify = notify_out.NotifyOut(self._config)
+        self.assertEqual({}, self._notify._notify_infos)
         self._notify._notify_infos[('example.com.', 'IN')] = MockZoneNotifyInfo('example.com.', 'IN')
         self._notify._notify_infos[('example.com.', 'CH')] = MockZoneNotifyInfo('example.com.', 'CH')
         self._notify._notify_infos[('example.net.', 'IN')] = MockZoneNotifyInfo('example.net.', 'IN')
@@ -171,6 +172,21 @@ class TestNotifyOut(unittest.TestCase):
         self._notify._datasource_config = config
         self._notify._check_datasrc()
 
+    def test_ensure_zone(self):
+        # Drop the mocked-up zones
+        self._notify._notify_infos = {}
+        # Add a zone info
+        self.assertTrue(self._notify._ensure_zone('example.net', 'IN'))
+        self.assertTrue(('example.net', 'IN') in self._notify._notify_infos)
+        info = self._notify._notify_infos[('example.net', 'IN')]
+        # Adding again has no effect
+        self.assertTrue(self._notify._ensure_zone('example.net', 'IN'))
+        self.assertEqual(info,
+                         self._notify._notify_infos[('example.net', 'IN')])
+        # Zone not found
+        self.assertFalse(self._notify._ensure_zone('example.org', 'IN'))
+        self.assertFalse(('example.org', 'IN') in self._notify._notify_infos)
+
     def test_send_notify(self):
         notify_out._MAX_NOTIFY_NUM = 2
 
@@ -220,6 +236,18 @@ class TestNotifyOut(unittest.TestCase):
         self.assertEqual(self._notify.notify_num, 2)
         self.assertEqual(2, len(self._notify._waiting_zones))
 
+    def test_send_notify_clean(self):
+        """
+        Sending notifications, but without pre-filled zones.
+        """
+        self._notify._notify_infos = {}
+
+        self._notify._nonblock_event.clear()
+        self.assertTrue(self._notify.send_notify('example.net'))
+        self.assertTrue(self._notify._nonblock_event.isSet())
+        self.assertEqual(self._notify.notify_num, 1)
+        self.assertEqual(self._notify._notifying_zones[0], ('example.net.', 'IN'))
+
     def test_wait_for_notify_reply(self):
         self._notify.send_notify('example.net.')
         self._notify.send_notify('example.com.')
@@ -467,8 +495,10 @@ class TestNotifyOut(unittest.TestCase):
         self.assertEqual(('192.0.2.1', 5353), example_net_info._notify_current)
 
     def test_get_notify_slaves_from_ns(self):
-        records = self._notify._get_notify_slaves_from_ns(Name('example.net.'),
-                                                          RRClass.IN)
+        records, found = \
+            self._notify._get_notify_slaves_from_ns(Name('example.net.'),
+                                                    RRClass.IN)
+        self.assertTrue(found)
         self.assertEqual(6, len(records))
         self.assertEqual('8:8::8:8', records[5])
         self.assertEqual('7.7.7.7', records[4])
@@ -477,24 +507,37 @@ class TestNotifyOut(unittest.TestCase):
         self.assertEqual('4:4::4:4', records[1])
         self.assertEqual('3.3.3.3', records[0])
 
-        records = self._notify._get_notify_slaves_from_ns(Name('example.com.'),
-                                                          RRClass.IN)
+        records, found = \
+            self._notify._get_notify_slaves_from_ns(Name('example.com.'),
+                                                    RRClass.IN)
         self.assertEqual(3, len(records))
         self.assertEqual('5:5::5:5', records[2])
         self.assertEqual('4:4::4:4', records[1])
         self.assertEqual('3.3.3.3', records[0])
 
+        records, found = \
+            self._notify._get_notify_slaves_from_ns(Name('notexist.com.'),
+                                                    RRClass.IN)
+        self.assertFalse(found)
+        self.assertEqual([], records)
+
+        records, found = \
+            self._notify._get_notify_slaves_from_ns(Name('example.com.'),
+                                                    RRClass.CH)
+        self.assertFalse(found)
+        self.assertEqual([], records)
+
     def test_get_notify_slaves_from_ns_unusual(self):
         self.configure_dsrc(self.get_dsrc_config(TESTDATA_SRCDIR +
                                                  '/brokentest.sqlite3'))
-        self.assertEqual([], self._notify._get_notify_slaves_from_ns(
+        self.assertEqual(([], True), self._notify._get_notify_slaves_from_ns(
                 Name('nons.example'), RRClass.IN))
-        self.assertEqual([], self._notify._get_notify_slaves_from_ns(
+        self.assertEqual(([], True), self._notify._get_notify_slaves_from_ns(
                 Name('nosoa.example'), RRClass.IN))
-        self.assertEqual([], self._notify._get_notify_slaves_from_ns(
+        self.assertEqual(([], True), self._notify._get_notify_slaves_from_ns(
                 Name('multisoa.example'), RRClass.IN))
 
-        self.assertEqual([], self._notify._get_notify_slaves_from_ns(
+        self.assertEqual(([], False), self._notify._get_notify_slaves_from_ns(
                 Name('nosuchzone.example'), RRClass.IN))
 
         return # TODO: The rest does not work now.
@@ -504,11 +547,6 @@ class TestNotifyOut(unittest.TestCase):
         self.assertEqual([], self._notify._get_notify_slaves_from_ns(
                 Name('example.com'), RRClass.IN))
 
-    def test_init_notify_out(self):
-        self._notify._init_notify_out(self._db_file)
-        self.assertListEqual([('3.3.3.3', 53), ('4:4::4:4', 53), ('5:5::5:5', 53)],
-                             self._notify._notify_infos[('example.com.', 'IN')].notify_slaves)
-
     def test_prepare_select_info(self):
         timeout, valid_fds, notifying_zones = self._notify._prepare_select_info()
         self.assertEqual(None, timeout)



More information about the bind10-changes mailing list