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