Rev 3804: Make _DirectPackAccess.reload_or_raise maintain the logic. in http://bzr.arbash-meinel.com/branches/bzr/1.9-dev/pack_retry_153786

John Arbash Meinel john at arbash-meinel.com
Fri Oct 24 23:07:54 BST 2008


At http://bzr.arbash-meinel.com/branches/bzr/1.9-dev/pack_retry_153786

------------------------------------------------------------
revno: 3804
revision-id: john at arbash-meinel.com-20081024220749-on46bi1n2ee170uh
parent: john at arbash-meinel.com-20081024215259-xh1qcfeu9bdy6350
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: pack_retry_153786
timestamp: Fri 2008-10-24 17:07:49 -0500
message:
  Make _DirectPackAccess.reload_or_raise maintain the logic.
  
  This way the exception that is raised by _DirectPackAccess is also properly
  handled by DPA. So we can keep the logic in sync.
-------------- next part --------------
=== modified file 'bzrlib/knit.py'
--- a/bzrlib/knit.py	2008-10-24 21:52:59 +0000
+++ b/bzrlib/knit.py	2008-10-24 22:07:49 +0000
@@ -2511,6 +2511,19 @@
 
         :param retry_exc: A RetryWithNewPacks exception.
         """
+        is_error = False
+        if self._reload_func is None:
+            is_error = True
+        elif not self._reload_func():
+            # The reload claimed that nothing changed
+            if not retry_exc.reload_occurred:
+                # If there wasn't an earlier reload, then we really were
+                # expecting to find changes. We didn't find them, so this is a
+                # hard error
+                is_error = True
+        if is_error:
+            exc_class, exc_value, exc_traceback = retry_exc.exc_info
+            raise exc_class, exc_value, exc_traceback
 
 
 # Deprecated, use PatienceSequenceMatcher instead

=== modified file 'bzrlib/tests/test_knit.py'
--- a/bzrlib/tests/test_knit.py	2008-10-24 21:52:59 +0000
+++ b/bzrlib/tests/test_knit.py	2008-10-24 22:07:49 +0000
@@ -322,7 +322,11 @@
         mapper = ConstantMapper("foo")
         access = _KnitKeyAccess(self.get_transport(), mapper)
         return access
-    
+
+
+class _TestException(Exception):
+    """Just an exception for local tests to use."""
+
 
 class TestPackKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin):
     """Tests for the pack based access."""
@@ -349,13 +353,23 @@
         writer.end()
         return memos
 
-    def make_reload_func(self):
+    def make_reload_func(self, return_val=True):
         reload_called = [0]
         def reload():
             reload_called[0] += 1
-            return True
+            return return_val
         return reload_called, reload
 
+    def make_retry_exception(self):
+        # We raise a real exception so that sys.exc_info() is properly
+        # populated
+        try:
+            raise _TestException('foobar')
+        except _TestException, e:
+            retry_exc = errors.RetryWithNewPacks(reload_occurred=False,
+                                                 exc_info=sys.exc_info())
+        return retry_exc
+
     def test_read_from_several_packs(self):
         access, writer = self._get_access()
         memos = []
@@ -483,6 +497,36 @@
         e = self.assertListRaises(errors.NoSuchFile,
                                   access.get_raw_records, memos)
 
+    def test_reload_or_raise_no_reload(self):
+        access = _DirectPackAccess({}, reload_func=None)
+        retry_exc = self.make_retry_exception()
+        # Without a reload_func, we will just re-raise the original exception
+        self.assertRaises(_TestException, access.reload_or_raise, retry_exc)
+
+    def test_reload_or_raise_reload_changed(self):
+        reload_called, reload_func = self.make_reload_func(return_val=True)
+        access = _DirectPackAccess({}, reload_func=reload_func)
+        retry_exc = self.make_retry_exception()
+        access.reload_or_raise(retry_exc)
+        self.assertEqual([1], reload_called)
+        retry_exc.reload_occurred=True
+        access.reload_or_raise(retry_exc)
+        self.assertEqual([2], reload_called)
+
+    def test_reload_or_raise_reload_no_change(self):
+        reload_called, reload_func = self.make_reload_func(return_val=False)
+        access = _DirectPackAccess({}, reload_func=reload_func)
+        retry_exc = self.make_retry_exception()
+        # If reload_occurred is False, then we consider it an error to have
+        # reload_func() return False (no changes).
+        self.assertRaises(_TestException, access.reload_or_raise, retry_exc)
+        self.assertEqual([1], reload_called)
+        retry_exc.reload_occurred=True
+        # If reload_occurred is True, then we assume nothing changed because
+        # it had changed earlier, but didn't change again
+        access.reload_or_raise(retry_exc)
+        self.assertEqual([2], reload_called)
+
 
 class LowLevelKnitDataTests(TestCase):
 



More information about the bazaar-commits mailing list