Browse Source

[1789] keep list of 'sqlite3' type memory ds zones in xfrin

Jelte Jansen 13 years ago
parent
commit
7a0dc75cee
2 changed files with 115 additions and 6 deletions
  1. 70 0
      src/bin/xfrin/tests/xfrin_test.py
  2. 45 6
      src/bin/xfrin/xfrin.py.in

+ 70 - 0
src/bin/xfrin/tests/xfrin_test.py

@@ -2577,6 +2577,76 @@ class TestXfrin(unittest.TestCase):
         self.common_ixfr_setup('refresh', False)
         self.assertEqual(RRType.AXFR(), self.xfr.xfrin_started_request_type)
 
+    def test_memory_zones(self):
+        # Configuration snippet containing 2 memory datasources,
+        # one for IN and one for CH. Both contain a zone 'example.com'
+        # the IN ds also contains a zone example2.com, and a zone example3.com,
+        # which is of file type 'text' (and hence, should be ignored)
+        config = { 'datasources': [
+                     { 'type': 'memory',
+                       'class': 'IN',
+                       'zones': [
+                         { 'origin': 'example.com',
+                           'filetype': 'sqlite3' },
+                         { 'origin': 'example2.com',
+                           'filetype': 'sqlite3' },
+                         { 'origin': 'example3.com',
+                           'filetype': 'text' }
+                       ]
+                     },
+                     { 'type': 'memory',
+                       'class': 'CH',
+                       'zones': [
+                         { 'origin': 'example.com',
+                           'filetype': 'sqlite3' }
+                       ]
+                     }
+                 ] }
+
+        self.assertFalse(self.xfr._is_memory_zone("example.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example2.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example3.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example.com", "CH"))
+
+        # add them all
+        self.xfr._set_memory_zones(config, None)
+        self.assertTrue(self.xfr._is_memory_zone("example.com", "IN"))
+        self.assertTrue(self.xfr._is_memory_zone("example2.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example3.com", "IN"))
+        self.assertTrue(self.xfr._is_memory_zone("example.com", "CH"))
+
+        # Remove the CH data source from the config snippet, and update
+        del config['datasources'][1]
+        self.xfr._set_memory_zones(config, None)
+        self.assertTrue(self.xfr._is_memory_zone("example.com", "IN"))
+        self.assertTrue(self.xfr._is_memory_zone("example2.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example3.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example.com", "CH"))
+
+        # Remove example2.com from the datasource, and update
+        del config['datasources'][0]['zones'][1]
+        self.xfr._set_memory_zones(config, None)
+        self.assertTrue(self.xfr._is_memory_zone("example.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example2.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example3.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example.com", "CH"))
+
+        # If 'datasources' is not in the config update list (i.e. its config
+        # has not changed), no difference should be found
+        self.xfr._set_memory_zones({}, None)
+        self.assertTrue(self.xfr._is_memory_zone("example.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example2.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example3.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example.com", "CH"))
+
+        # If datasources list becomes empty, everything should be removed
+        config['datasources'][0]['zones'] = []
+        self.xfr._set_memory_zones(config, None)
+        self.assertFalse(self.xfr._is_memory_zone("example.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example2.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example3.com", "IN"))
+        self.assertFalse(self.xfr._is_memory_zone("example.com", "CH"))
+
 def raise_interrupt():
     raise KeyboardInterrupt()
 

+ 45 - 6
src/bin/xfrin/xfrin.py.in

@@ -1246,10 +1246,11 @@ class Xfrin:
     def __init__(self):
         self._max_transfers_in = 10
         self._zones = {}
-        # keep a separate list so we can more easily update either for now
-        # these are the zones that are served by the in-memory datasource,
-        # but transfers are handled by sqlite3
-        self._memory_zones = {}
+        # This is a set of (zone/class) tuples (both as strings),
+        # representing the in-memory zones maintaned by Xfrin. It
+        # is used to trigger Auth/in-memory so that it reloads
+        # zones when they have been transfered in
+        self._memory_zones = set()
         self._cc_setup()
         self.recorder = XfrinRecorder()
         self._shutdown_event = threading.Event()
@@ -1316,10 +1317,48 @@ class Xfrin:
 
         return create_answer(0)
 
-    def auth_config_handler(self, new_config, foo):
+    def auth_config_handler(self, new_config, config_data):
         # Config handler for changes in Auth configuration
-        print("[XX] Hi. XFRIN HERE. AUTH CONFIG UPDATE")
         self._set_db_file()
+        self._set_memory_zones(new_config, config_data)
+
+    def _clear_memory_zones(self):
+        """Clears the memory_zones set; called before processing the
+           changed list of memory datasource zones that have file type
+           sqlite3"""
+        self._memory_zones.clear()
+
+    def _is_memory_zone(self, zone_name_str, zone_class_str):
+        """Returns true if the given zone/class combination is configured
+           in the in-memory datasource of the Auth process with file type
+           'sqlite3'.
+        """
+        return (zone_name_str, zone_class_str) in self._memory_zones
+
+    def _add_memory_zone(self, zone_name_str, zone_class_str):
+        """Add the given zone and class to the internal list of zones
+           in memory datasources with file type 'sqlite3'"""
+        self._memory_zones.add((zone_name_str, zone_class_str))
+
+    def _set_memory_zones(self, new_config, config_data):
+        """Part of the auth_config_handler function, keeps an internal set
+           of zones in the datasources config subset that have 'sqlite3' as
+           their file type"""
+        if "datasources" in new_config:
+            self._clear_memory_zones()
+            for datasource in new_config["datasources"]:
+                if "class" in datasource:
+                    ds_class = datasource["class"]
+                else:
+                    # Get the default
+                    ds_class =\
+                        config_data.get_default_value("datasources/class")
+                if datasource["type"] == "memory":
+                    zones = []
+                    for zone in datasource["zones"]:
+                        if zone["filetype"] == "sqlite3":
+                            zone_name = zone["origin"]
+                            self._add_memory_zone(zone_name, ds_class)
 
     def shutdown(self):
         ''' shutdown the xfrin process. the thread which is doing xfrin should be