Rev 5119: (spiv) Add reload-and-retry logic to RepositoryPackCollection.pack when a in file:///home/pqm/archives/thelove/bzr/2.2/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Jan 20 00:52:48 UTC 2011
At file:///home/pqm/archives/thelove/bzr/2.2/
------------------------------------------------------------
revno: 5119 [merge]
revision-id: pqm at pqm.ubuntu.com-20110120005245-9i7zq3f8ujoy355g
parent: pqm at pqm.ubuntu.com-20110114230435-ww0f1p7y9rgdr7nn
parent: andrew.bennetts at canonical.com-20110119223447-2w8drxa2kq5mmymo
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: 2.2
timestamp: Thu 2011-01-20 00:52:45 +0000
message:
(spiv) Add reload-and-retry logic to RepositoryPackCollection.pack when a
concurrent pack happens. (#701940) (Andrew Bennetts)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/repofmt/pack_repo.py pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
bzrlib/tests/test_knit.py test_knit.py-20051212171302-95d4c00dd5f11f2b
=== modified file 'NEWS'
--- a/NEWS 2011-01-14 21:36:35 +0000
+++ b/NEWS 2011-01-19 22:34:47 +0000
@@ -28,6 +28,10 @@
* Avoid UnicodeDecodeError in ``bzr add`` with multiple files under a non-ascii
path on windows from symlink support addition. (Martin [gz], #686611)
+* Fix a crash during ``RepositoryPackCollection.pack`` caused by a
+ concurrent repository pack operation. This was particularly affecting
+ ``bzr-svn`` users. (Andrew Bennetts, #701940)
+
* Correctly resolve content (and path) conflicts for files in subdirs.
(Vincent Ladeuil, #660935)
=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py 2010-05-11 08:36:16 +0000
+++ b/bzrlib/repofmt/pack_repo.py 2011-01-19 22:26:56 +0000
@@ -1574,6 +1574,20 @@
mutter('Packing repository %s, which has %d pack files, '
'containing %d revisions with hint %r.', self, total_packs,
total_revisions, hint)
+ while True:
+ try:
+ self._try_pack_operations(hint)
+ except RetryPackOperations:
+ continue
+ break
+
+ if clean_obsolete_packs:
+ self._clear_obsolete_packs()
+
+ def _try_pack_operations(self, hint):
+ """Calculate the pack operations based on the hint (if any), and
+ execute them.
+ """
# determine which packs need changing
pack_operations = [[0, []]]
for pack in self.all_packs():
@@ -1582,10 +1596,8 @@
# or this pack was included in the hint.
pack_operations[-1][0] += pack.get_revision_count()
pack_operations[-1][1].append(pack)
- self._execute_pack_operations(pack_operations, OptimisingPacker)
-
- if clean_obsolete_packs:
- self._clear_obsolete_packs()
+ self._execute_pack_operations(pack_operations, OptimisingPacker,
+ reload_func=self._restart_pack_operations)
def plan_autopack_combinations(self, existing_packs, pack_distribution):
"""Plan a pack operation.
@@ -2042,6 +2054,14 @@
raise
raise errors.RetryAutopack(self.repo, False, sys.exc_info())
+ def _restart_pack_operations(self):
+ """Reload the pack names list, and restart the autopack code."""
+ if not self.reload_pack_names():
+ # Re-raise the original exception, because something went missing
+ # and a restart didn't find it
+ raise
+ raise RetryPackOperations(self.repo, False, sys.exc_info())
+
def _clear_obsolete_packs(self, preserve=None):
"""Delete everything from the obsolete-packs directory.
@@ -2933,3 +2953,17 @@
return ("Development repository format, currently the same as "
"1.6.1-subtree with B+Tree indices.\n")
+
+class RetryPackOperations(errors.RetryWithNewPacks):
+ """Raised when we are packing and we find a missing file.
+
+ Meant as a signaling exception, to tell the RepositoryPackCollection.pack
+ code it should try again.
+ """
+
+ internal_error = True
+
+ _fmt = ("Pack files have changed, reload and try pack again."
+ " context: %(context)s %(orig_error)s")
+
+
=== modified file 'bzrlib/tests/test_knit.py'
--- a/bzrlib/tests/test_knit.py 2010-06-20 11:18:38 +0000
+++ b/bzrlib/tests/test_knit.py 2011-01-19 22:06:31 +0000
@@ -338,6 +338,33 @@
writer.end()
return memos
+ def test_pack_collection_pack_retries(self):
+ """An explicit pack of a pack collection succeeds even when a
+ concurrent pack happens.
+ """
+ builder = self.make_branch_builder('.')
+ builder.start_series()
+ builder.build_snapshot('rev-1', None, [
+ ('add', ('', 'root-id', 'directory', None)),
+ ('add', ('file', 'file-id', 'file', 'content\nrev 1\n')),
+ ])
+ builder.build_snapshot('rev-2', ['rev-1'], [
+ ('modify', ('file-id', 'content\nrev 2\n')),
+ ])
+ builder.build_snapshot('rev-3', ['rev-2'], [
+ ('modify', ('file-id', 'content\nrev 3\n')),
+ ])
+ self.addCleanup(builder.finish_series)
+ b = builder.get_branch()
+ self.addCleanup(b.lock_write().unlock)
+ repo = b.repository
+ collection = repo._pack_collection
+ # Concurrently repack the repo.
+ reopened_repo = repo.bzrdir.open_repository()
+ reopened_repo.pack()
+ # Pack the new pack.
+ collection.pack()
+
def make_vf_for_retrying(self):
"""Create 3 packs and a reload function.
More information about the bazaar-commits
mailing list