Browse Source

[1376] updated the Diff class so that it can enable journaling when specified.

JINMEI Tatuya 13 years ago
parent
commit
dbf32272f3

+ 1 - 1
src/bin/xfrin/tests/xfrin_test.py

@@ -170,7 +170,7 @@ class MockDataSourceClient():
             return (ZoneFinder.SUCCESS, dup_soa_rrset)
             return (ZoneFinder.SUCCESS, dup_soa_rrset)
         raise ValueError('Unexpected input to mock finder: bug in test case?')
         raise ValueError('Unexpected input to mock finder: bug in test case?')
 
 
-    def get_updater(self, zone_name, replace):
+    def get_updater(self, zone_name, replace, journaling=False):
         return self
         return self
 
 
     def add_rrset(self, rrset):
     def add_rrset(self, rrset):

+ 15 - 3
src/lib/python/isc/xfrin/diff.py

@@ -59,7 +59,7 @@ class Diff:
     the changes to underlying data source right away, but keeps them for
     the changes to underlying data source right away, but keeps them for
     a while.
     a while.
     """
     """
-    def __init__(self, ds_client, zone, replace=False):
+    def __init__(self, ds_client, zone, replace=False, journaling=False):
         """
         """
         Initializes the diff to a ready state. It checks the zone exists
         Initializes the diff to a ready state. It checks the zone exists
         in the datasource and if not, NoSuchZone is raised. This also creates
         in the datasource and if not, NoSuchZone is raised. This also creates
@@ -67,13 +67,25 @@ class Diff:
 
 
         The ds_client is the datasource client containing the zone. Zone is
         The ds_client is the datasource client containing the zone. Zone is
         isc.dns.Name object representing the name of the zone (its apex).
         isc.dns.Name object representing the name of the zone (its apex).
-        If replace is true, the content of the whole zone is wiped out before
+        If replace is True, the content of the whole zone is wiped out before
         applying the diff.
         applying the diff.
 
 
+        If journaling is True, the history of subsequent updates will be
+        recorded as well as the updates themselves as long as the underlying
+        data source support the journaling.  If the data source allows
+        incoming updates but does not support journaling, the Diff object
+        will still continue applying the diffs with disabling journaling.
+
         You can also expect isc.datasrc.Error or isc.datasrc.NotImplemented
         You can also expect isc.datasrc.Error or isc.datasrc.NotImplemented
         exceptions.
         exceptions.
         """
         """
-        self.__updater = ds_client.get_updater(zone, replace)
+        try:
+            self.__updater = ds_client.get_updater(zone, replace, journaling)
+        except isc.datasrc.NotImplemented as ex:
+            if not journaling:
+                raise ex
+            self.__updater = ds_client.get_updater(zone, replace, False)
+            logger.info(LIBXFRIN_NO_JOURNAL, zone, ds_client)
         if self.__updater is None:
         if self.__updater is None:
             # The no such zone case
             # The no such zone case
             raise NoSuchZone("Zone " + str(zone) +
             raise NoSuchZone("Zone " + str(zone) +

+ 12 - 0
src/lib/python/isc/xfrin/libxfrin_messages.mes

@@ -19,3 +19,15 @@
 The xfrin module received an update containing multiple rdata changes for the
 The xfrin module received an update containing multiple rdata changes for the
 same RRset. But the TTLs of these don't match each other. As we combine them
 same RRset. But the TTLs of these don't match each other. As we combine them
 together, the later one get's overwritten to the earlier one in the sequence.
 together, the later one get's overwritten to the earlier one in the sequence.
+
+% LIBXFRIN_NO_JOURNAL disabled journaling for updates to %1 on %2
+A Diff object was attempted to be created with enabling journaing, but
+the underlying data source didn't support journaling (while still
+allowing updates).  So the resulting Diff object will continue handle
+updates by disabling journaing.  At a higher level this means that the
+updates will be applied to the zone but subsequent IXFR requests will
+result in a full zone transfer (i.e., an AXFR-style IXFR).  Unless the
+overhead of the full transfer is an issue this message can be ignored;
+otherwise you may want to check why the journaling wasn't allowed on
+the data source and either fix the issue or use a different type of
+data source.

+ 23 - 3
src/lib/python/isc/xfrin/tests/diff_tests.py

@@ -15,6 +15,7 @@
 
 
 import isc.log
 import isc.log
 import unittest
 import unittest
+import isc.datasrc
 from isc.dns import Name, RRset, RRClass, RRType, RRTTL, Rdata
 from isc.dns import Name, RRset, RRClass, RRType, RRTTL, Rdata
 from isc.xfrin.diff import Diff, NoSuchZone
 from isc.xfrin.diff import Diff, NoSuchZone
 
 
@@ -127,7 +128,7 @@ class DiffTest(unittest.TestCase):
         """
         """
         return self.__rrclass
         return self.__rrclass
 
 
-    def get_updater(self, zone_name, replace):
+    def get_updater(self, zone_name, replace, journaling=False):
         """
         """
         This one pretends this is the data source client and serves
         This one pretends this is the data source client and serves
         getting an updater.
         getting an updater.
@@ -138,11 +139,20 @@ class DiffTest(unittest.TestCase):
         # The diff should not delete the old data.
         # The diff should not delete the old data.
         self.assertEqual(self.__should_replace, replace)
         self.assertEqual(self.__should_replace, replace)
         self.__updater_requested = True
         self.__updater_requested = True
-        # Pretend this zone doesn't exist
         if zone_name == Name('none.example.org.'):
         if zone_name == Name('none.example.org.'):
+            # Pretend this zone doesn't exist
             return None
             return None
+
+        # If journaling is enabled, record the fact; for a special zone
+        # pretend that we don't support journaling.
+        if journaling:
+            if zone_name == Name('nodiff.example.org'):
+                raise isc.datasrc.NotImplemented('journaling not supported')
+            self.__journaling_enabled = True
         else:
         else:
-            return self
+            self.__journaling_enabled = False
+
+        return self
 
 
     def test_create(self):
     def test_create(self):
         """
         """
@@ -152,6 +162,8 @@ class DiffTest(unittest.TestCase):
         diff = Diff(self, Name('example.org.'))
         diff = Diff(self, Name('example.org.'))
         self.assertTrue(self.__updater_requested)
         self.assertTrue(self.__updater_requested)
         self.assertEqual([], diff.get_buffer())
         self.assertEqual([], diff.get_buffer())
+        # By default journaling is disabled
+        self.assertFalse(self.__journaling_enabled)
 
 
     def test_create_nonexist(self):
     def test_create_nonexist(self):
         """
         """
@@ -161,6 +173,14 @@ class DiffTest(unittest.TestCase):
         self.assertRaises(NoSuchZone, Diff, self, Name('none.example.org.'))
         self.assertRaises(NoSuchZone, Diff, self, Name('none.example.org.'))
         self.assertTrue(self.__updater_requested)
         self.assertTrue(self.__updater_requested)
 
 
+    def test_create_withjournal(self):
+        Diff(self, Name('example.org'), False, True)
+        self.assertTrue(self.__journaling_enabled)
+
+    def test_create_nojournal(self):
+        Diff(self, Name('nodiff.example.org'), False, True)
+        self.assertFalse(self.__journaling_enabled)
+
     def __data_common(self, diff, method, operation):
     def __data_common(self, diff, method, operation):
         """
         """
         Common part of test for test_add and test_delte.
         Common part of test for test_add and test_delte.