Rev 5201: (andrew) Allow repo.refresh_data() to be called in a write group for in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue May 4 12:16:20 BST 2010


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 5201 [merge]
revision-id: pqm at pqm.ubuntu.com-20100504111615-fcjkr4i0oi12oubc
parent: pqm at pqm.ubuntu.com-20100503090750-ojeefmuph3yj8m5z
parent: andrew.bennetts at canonical.com-20100504084752-lhksueg0uy5i25oa
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2010-05-04 12:16:15 +0100
message:
  (andrew) Allow repo.refresh_data() to be called in a write group for
  	pack format repositories. (#574236)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
  bzrlib/repofmt/knitrepo.py     knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/per_repository/test_refresh_data.py test_refresh_data.py-20090316045630-5sw0ipqwk7rvpn3h-1
=== modified file 'NEWS'
--- a/NEWS	2010-05-03 04:08:50 +0000
+++ b/NEWS	2010-05-04 02:41:17 +0000
@@ -96,6 +96,14 @@
   implementations.
   (Martin Pool)
 
+* ``Repository.refresh_data`` may now be called in a write group on
+  pack-based repositories.  Older repositories will still raise an error
+  in this case.  Subclasses of ``Repository`` can still override
+  ``Repository._refresh_data``, but are now responsible for raising
+  ``bzrlib.repository.IsInWriteGroupError`` if they do not support
+  ``refresh_data`` during a write group.
+  (Andrew Bennetts, #574236)
+
 Internals
 *********
 

=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py	2010-05-03 04:08:50 +0000
+++ b/bzrlib/remote.py	2010-05-04 08:47:52 +0000
@@ -1306,16 +1306,16 @@
         return self._real_repository.make_working_trees()
 
     def refresh_data(self):
-        """Re-read any data needed to to synchronise with disk.
+        """Re-read any data needed to synchronise with disk.
 
         This method is intended to be called after another repository instance
         (such as one used by a smart server) has inserted data into the
-        repository. It may not be called during a write group, but may be
-        called at any other time.
+        repository. On all repositories this will work outside of write groups.
+        Some repository formats (pack and newer for bzrlib native formats)
+        support refresh_data inside write groups. If called inside a write
+        group on a repository that does not support refreshing in a write group
+        IsInWriteGroupError will be raised.
         """
-        if self.is_in_write_group():
-            raise errors.InternalBzrError(
-                "May not refresh_data while in a write group.")
         if self._real_repository is not None:
             self._real_repository.refresh_data()
 

=== modified file 'bzrlib/repofmt/knitrepo.py'
--- a/bzrlib/repofmt/knitrepo.py	2010-04-26 13:51:08 +0000
+++ b/bzrlib/repofmt/knitrepo.py	2010-05-04 02:41:17 +0000
@@ -38,6 +38,7 @@
 from bzrlib.decorators import needs_read_lock, needs_write_lock
 from bzrlib.repository import (
     CommitBuilder,
+    IsInWriteGroupError,
     MetaDirRepository,
     MetaDirRepositoryFormat,
     RepositoryFormat,
@@ -210,6 +211,8 @@
     def _refresh_data(self):
         if not self.is_locked():
             return
+        if self.is_in_write_group():
+            raise IsInWriteGroupError(self)
         # Create a new transaction to force all knits to see the scope change.
         # This is safe because we're outside a write group.
         self.control_files._finish_transaction()

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2010-04-28 07:03:38 +0000
+++ b/bzrlib/repository.py	2010-05-04 08:47:52 +0000
@@ -26,7 +26,6 @@
     chk_map,
     config,
     debug,
-    errors,
     fetch as _mod_fetch,
     fifo_cache,
     generate_ids,
@@ -62,7 +61,10 @@
     entry_factory,
     )
 from bzrlib.lock import _RelockDebugMixin
-from bzrlib import registry
+from bzrlib import (
+    errors,
+    registry,
+    )
 from bzrlib.trace import (
     log_exception_quietly, note, mutter, mutter_callsite, warning)
 
@@ -71,6 +73,14 @@
 _deprecation_warning_done = False
 
 
+class IsInWriteGroupError(errors.InternalBzrError):
+
+    _fmt = "May not refresh_data of repo %(repo)s while in a write group."
+
+    def __init__(self, repo):
+        errors.InternalBzrError.__init__(self, repo=repo)
+
+
 class CommitBuilder(object):
     """Provides an interface to build up a commit.
 
@@ -1634,16 +1644,16 @@
         return missing_keys
 
     def refresh_data(self):
-        """Re-read any data needed to to synchronise with disk.
+        """Re-read any data needed to synchronise with disk.
 
         This method is intended to be called after another repository instance
         (such as one used by a smart server) has inserted data into the
-        repository. It may not be called during a write group, but may be
-        called at any other time.
+        repository. On all repositories this will work outside of write groups.
+        Some repository formats (pack and newer for bzrlib native formats)
+        support refresh_data inside write groups. If called inside a write
+        group on a repository that does not support refreshing in a write group
+        IsInWriteGroupError will be raised.
         """
-        if self.is_in_write_group():
-            raise errors.InternalBzrError(
-                "May not refresh_data while in a write group.")
         self._refresh_data()
 
     def resume_write_group(self, tokens):

=== modified file 'bzrlib/tests/per_repository/test_refresh_data.py'
--- a/bzrlib/tests/per_repository/test_refresh_data.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/per_repository/test_refresh_data.py	2010-05-04 08:45:21 +0000
@@ -18,7 +18,7 @@
 
 from bzrlib import (
     errors,
-    remote,
+    repository,
     )
 from bzrlib.tests import TestSkipped
 from bzrlib.tests.per_repository import TestCaseWithRepository
@@ -45,22 +45,34 @@
         self.addCleanup(repo.unlock)
         repo.refresh_data()
 
-    def test_refresh_data_in_write_group_errors(self):
+    def test_refresh_data_in_write_group(self):
+        # refresh_data may either succeed or raise IsInWriteGroupError during a
+        # write group.
         repo = self.make_repository('.')
         repo.lock_write()
         self.addCleanup(repo.unlock)
         repo.start_write_group()
         self.addCleanup(repo.abort_write_group)
-        # No flow control anticipated, BzrError is enough
-        self.assertRaises(errors.BzrError, repo.refresh_data)
+        try:
+            repo.refresh_data()
+        except repository.IsInWriteGroupError:
+            # This is ok.
+            pass
+        else:
+            # This is ok too.
+            pass
 
-    def test_refresh_data_after_fetch_new_data_visible(self):
-        source = self.make_branch_and_tree('source')
-        revid = source.commit('foo')
-        repo = self.make_repository('target')
-        token = repo.lock_write()
-        self.addCleanup(repo.unlock)
+    def fetch_new_revision_into_concurrent_instance(self, repo, token):
+        """Create a new revision (revid 'new-rev') and fetch it into a
+        concurrent instance of repo.
+        """
+        source = self.make_branch_and_memory_tree('source')
+        source.lock_write()
+        self.addCleanup(source.unlock)
+        source.add([''], ['root-id'])
+        revid = source.commit('foo', rev_id='new-rev')
         # Force data reading on weaves/knits
+        repo.all_revision_ids()
         repo.revisions.keys()
         repo.inventories.keys()
         # server repo is the instance a smart server might hold for this
@@ -75,5 +87,34 @@
             server_repo.fetch(source.branch.repository, revid)
         finally:
             server_repo.unlock()
+
+    def test_refresh_data_after_fetch_new_data_visible(self):
+        repo = self.make_repository('target')
+        token = repo.lock_write()
+        self.addCleanup(repo.unlock)
+        self.fetch_new_revision_into_concurrent_instance(repo, token)
         repo.refresh_data()
-        self.assertNotEqual({}, repo.get_graph().get_parent_map([revid]))
+        self.assertNotEqual({}, repo.get_graph().get_parent_map(['new-rev']))
+
+    def test_refresh_data_after_fetch_new_data_visible_in_write_group(self):
+        tree = self.make_branch_and_memory_tree('target')
+        tree.lock_write()
+        self.addCleanup(tree.unlock)
+        tree.add([''], ['root-id'])
+        tree.commit('foo', rev_id='commit-in-target')
+        repo = tree.branch.repository
+        token = repo.lock_write()
+        self.addCleanup(repo.unlock)
+        repo.start_write_group()
+        self.addCleanup(repo.abort_write_group)
+        self.fetch_new_revision_into_concurrent_instance(repo, token)
+        # Call refresh_data.  It either fails with IsInWriteGroupError, or it
+        # succeeds and the new revisions are visible.
+        try:
+            repo.refresh_data()
+        except repository.IsInWriteGroupError:
+            pass
+        else:
+            self.assertEqual(
+                ['commit-in-target', 'new-rev'],
+                sorted(repo.all_revision_ids()))




More information about the bazaar-commits mailing list