Rev 3793: CombinedGraphIndex.iter_entries() is now able to reload on request. in http://bzr.arbash-meinel.com/branches/bzr/1.9-dev/pack_retry_153786

John Arbash Meinel john at arbash-meinel.com
Thu Oct 23 21:29:11 BST 2008


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

------------------------------------------------------------
revno: 3793
revision-id: john at arbash-meinel.com-20081023202849-2k0p95mvwrhcjze9
parent: john at arbash-meinel.com-20081023200801-72xbksw2uyj8cdmq
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: pack_retry_153786
timestamp: Thu 2008-10-23 15:28:49 -0500
message:
  CombinedGraphIndex.iter_entries() is now able to reload on request.
-------------- next part --------------
=== modified file 'bzrlib/index.py'
--- a/bzrlib/index.py	2008-10-23 20:08:01 +0000
+++ b/bzrlib/index.py	2008-10-23 20:28:49 +0000
@@ -1192,12 +1192,17 @@
             efficient order for the index.
         """
         keys = set(keys)
-        for index in self._indices:
-            if not keys:
+        while True:
+            try:
+                for index in self._indices:
+                    if not keys:
+                        return
+                    for node in index.iter_entries(keys):
+                        keys.remove(node[1])
+                        yield node
                 return
-            for node in index.iter_entries(keys):
-                keys.remove(node[1])
-                yield node
+            except errors.NoSuchFile:
+                self._reload_or_raise()
 
     def iter_entries_prefix(self, keys):
         """Iterate over keys within the index using prefix matching.
@@ -1238,16 +1243,24 @@
         have a maximum error of the number of child indices * largest number of
         keys in any index.
         """
-        do_retry = True
-        while do_retry:
+        while True:
             try:
                 return sum((index.key_count() for index in self._indices), 0)
             except errors.NoSuchFile:
-                if self._reload_func is None:
-                    raise
-                exc_type, exc_value, exc_traceback = sys.exc_info()
-                if not self._reload_func():
-                    raise exc_type, exc_value, exc_traceback
+                self._reload_or_raise()
+
+    def _reload_or_raise(self):
+        """We just got a NoSuchFile exception.
+
+        Try to reload the indices, if it fails, just raise the current
+        exception.
+        """
+        if self._reload_func is None:
+            raise
+        exc_type, exc_value, exc_traceback = sys.exc_info()
+        if not self._reload_func():
+            # We tried to reload, but nothing changed, so we fail anyway
+            raise exc_type, exc_value, exc_traceback
 
     def validate(self):
         """Validate that everything in the index can be accessed."""

=== modified file 'bzrlib/tests/test_index.py'
--- a/bzrlib/tests/test_index.py	2008-10-23 20:08:01 +0000
+++ b/bzrlib/tests/test_index.py	2008-10-23 20:28:49 +0000
@@ -927,13 +927,14 @@
         size = trans.put_file(name, stream)
         return GraphIndex(trans, name, size)
 
-    def make_index_with_missing_children(self):
+    def make_combined_index_with_missing(self, missing=['1', '2']):
         """Create a CombinedGraphIndex which will have missing indexes.
 
         This creates a CGI which thinks it has 2 indexes, however they have
         been deleted. If CGI._reload_func() is called, then it will repopulate
         with a new index.
 
+        :param missing: The underlying indexes to delete
         :return: (CombinedGraphIndex, reload_counter)
         """
         index1 = self.make_index('1', nodes=[(('1',), '', ())])
@@ -955,8 +956,8 @@
             return True
         index = CombinedGraphIndex([index1, index2], reload_func=reload)
         trans = self.get_transport()
-        trans.delete('1')
-        trans.delete('2')
+        for fname in missing:
+            trans.delete(fname)
         return index, reload_counter
 
     def test_open_missing_index_no_error(self):
@@ -1103,19 +1104,58 @@
         index.validate()
 
     def test_key_count_reloads(self):
-        index, reload_counter = self.make_index_with_missing_children()
+        index, reload_counter = self.make_combined_index_with_missing()
         self.assertEqual(2, index.key_count())
         self.assertEqual([1, 1, 0], reload_counter)
 
+    def test_key_count_no_reload(self):
+        index, reload_counter = self.make_combined_index_with_missing()
+        index._reload_func = None
+        # Without a _reload_func we just raise the exception
+        self.assertRaises(errors.NoSuchFile, index.key_count)
+
     def test_key_count_reloads_and_fails(self):
-        index, reload_counter = self.make_index_with_missing_children()
-        # We have deleted the underlying index, so we will try to reload, but
+        # We have deleted all underlying indexes, so we will try to reload, but
         # still fail. This is mostly to test we don't get stuck in an infinite
         # loop trying to reload
-        self.get_transport().delete('3')
+        index, reload_counter = self.make_combined_index_with_missing(
+                                    ['1', '2', '3'])
         self.assertRaises(errors.NoSuchFile, index.key_count)
         self.assertEqual([2, 1, 1], reload_counter)
 
+    def test_iter_entries_reloads(self):
+        index, reload_counter = self.make_combined_index_with_missing()
+        result = list(index.iter_entries([('1',), ('2',), ('3',)]))
+        index3 = index._indices[0]
+        self.assertEqual([(index3, ('1',), ''), (index3, ('2',), '')],
+                         result)
+        self.assertEqual([1, 1, 0], reload_counter)
+
+    def test_iter_entries_reloads_midway(self):
+        # The first index still looks present, so we get interrupted mid-way
+        # through
+        index, reload_counter = self.make_combined_index_with_missing(['2'])
+        index1, index2 = index._indices
+        result = list(index.iter_entries([('1',), ('2',), ('3',)]))
+        index3 = index._indices[0]
+        # We had already yielded '1', so we just go on to the next
+        self.assertEqual([(index1, ('1',), ''), (index3, ('2',), '')],
+                         result)
+        self.assertEqual([1, 1, 0], reload_counter)
+
+    def test_iter_entries_no_reload(self):
+        index, reload_counter = self.make_combined_index_with_missing()
+        index._reload_func = None
+        # Without a _reload_func we just raise the exception
+        self.assertListRaises(errors.NoSuchFile, index.iter_entries, [('3',)])
+
+    def test_iter_entries_reloads_and_fails(self):
+        index, reload_counter = self.make_combined_index_with_missing(
+                                    ['1', '2', '3'])
+        self.assertListRaises(errors.NoSuchFile, index.iter_entries, [('3',)])
+        self.assertEqual([2, 1, 1], reload_counter)
+
+
 
 class TestInMemoryGraphIndex(TestCaseWithMemoryTransport):
 



More information about the bazaar-commits mailing list