Rev 4660: Merge 638451-malformed into more-tests in file:///home/vila/src/bzr/experimental/conflict-manager/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Fri Nov 12 09:35:48 GMT 2010
At file:///home/vila/src/bzr/experimental/conflict-manager/
------------------------------------------------------------
revno: 4660 [merge]
revision-id: v.ladeuil+lp at free.fr-20101112093548-00wds4q71zc6mtxy
parent: v.ladeuil+lp at free.fr-20101112093418-ges0dyaprq1lddwv
parent: v.ladeuil+lp at free.fr-20101112093546-nvbasoql1jlpxr43
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: more-tests
timestamp: Fri 2010-11-12 10:35:48 +0100
message:
Merge 638451-malformed into more-tests
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
bzrlib/tests/per_branch/test_tags.py test_tags.py-20070212110545-w2s799hm2jlbsmg5-1
doc/en/release-notes/bzr-2.3.txt NEWS-20050323055033-4e00b5db738777ff
-------------- next part --------------
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2010-10-12 09:46:37 +0000
+++ b/bzrlib/branch.py 2010-11-11 03:53:12 +0000
@@ -92,6 +92,7 @@
self._revision_id_to_revno_cache = None
self._partial_revision_id_to_revno_cache = {}
self._partial_revision_history_cache = []
+ self._tags_bytes = None
self._last_revision_info_cache = None
self._merge_sorted_revisions_cache = None
self._open_hook()
@@ -227,6 +228,7 @@
possible_transports=[self.bzrdir.root_transport])
return a_branch.repository
+ @needs_read_lock
def _get_tags_bytes(self):
"""Get the bytes of a serialised tags dict.
@@ -239,7 +241,9 @@
:return: The bytes of the tags file.
:seealso: Branch._set_tags_bytes.
"""
- return self._transport.get_bytes('tags')
+ if self._tags_bytes is None:
+ self._tags_bytes = self._transport.get_bytes('tags')
+ return self._tags_bytes
def _get_nick(self, local=False, possible_transports=None):
config = self.get_config()
@@ -876,8 +880,12 @@
:seealso: Branch._get_tags_bytes.
"""
- return _run_with_write_locked_target(self, self._transport.put_bytes,
- 'tags', bytes)
+ return _run_with_write_locked_target(self, self._set_tags_bytes_locked,
+ bytes)
+
+ def _set_tags_bytes_locked(self, bytes):
+ self._tags_bytes = bytes
+ return self._transport.put_bytes('tags', bytes)
def _cache_revision_history(self, rev_history):
"""Set the cached revision history to rev_history.
@@ -913,6 +921,7 @@
self._merge_sorted_revisions_cache = None
self._partial_revision_history_cache = []
self._partial_revision_id_to_revno_cache = {}
+ self._tags_bytes = None
def _gen_revision_history(self):
"""Return sequence of revision hashes on to this branch.
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2010-09-26 02:27:37 +0000
+++ b/bzrlib/remote.py 2010-11-11 03:53:12 +0000
@@ -2369,7 +2369,13 @@
self._ensure_real()
return self._real_branch._get_tags_bytes()
+ @needs_read_lock
def _get_tags_bytes(self):
+ if self._tags_bytes is None:
+ self._tags_bytes = self._get_tags_bytes_via_hpss()
+ return self._tags_bytes
+
+ def _get_tags_bytes_via_hpss(self):
medium = self._client._medium
if medium._is_remote_before((1, 13)):
return self._vfs_get_tags_bytes()
@@ -2385,6 +2391,8 @@
return self._real_branch._set_tags_bytes(bytes)
def _set_tags_bytes(self, bytes):
+ if self.is_locked():
+ self._tags_bytes = bytes
medium = self._client._medium
if medium._is_remote_before((1, 18)):
self._vfs_set_tags_bytes(bytes)
=== modified file 'bzrlib/tests/blackbox/test_branch.py'
--- a/bzrlib/tests/blackbox/test_branch.py 2010-07-21 20:09:34 +0000
+++ b/bzrlib/tests/blackbox/test_branch.py 2010-11-10 05:43:15 +0000
@@ -414,7 +414,7 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(38, self.hpss_calls)
+ self.assertLength(37, self.hpss_calls)
def test_branch_from_trivial_branch_streaming_acceptance(self):
self.setup_smart_server_with_call_log()
@@ -429,7 +429,7 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(10, self.hpss_calls)
+ self.assertLength(9, self.hpss_calls)
def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
self.setup_smart_server_with_call_log()
@@ -449,7 +449,7 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(15, self.hpss_calls)
+ self.assertLength(14, self.hpss_calls)
class TestRemoteBranch(TestCaseWithSFTPServer):
=== modified file 'bzrlib/tests/per_branch/test_tags.py'
--- a/bzrlib/tests/per_branch/test_tags.py 2010-03-12 02:14:56 +0000
+++ b/bzrlib/tests/per_branch/test_tags.py 2010-11-11 03:53:12 +0000
@@ -108,7 +108,6 @@
# and it keeps the same value
self.assertEquals(b2.tags.lookup_tag('conflicts'), 'revid-2')
-
def test_unicode_tag(self):
b1 = self.make_branch('b')
tag_name = u'\u3070'
@@ -143,6 +142,90 @@
b2 = self.make_branch('b2')
b1.tags.merge_to(b2.tags)
+ def test_read_lock_caches_tags(self):
+ """Tags are read from a branch only once during a read-lock."""
+ # Open the same branch twice. Read-lock one, and then mutate the tags
+ # in the second. The read-locked branch never re-reads the tags, so it
+ # never observes the changed/new tags.
+ b1 = self.make_branch('b')
+ b1.tags.set_tag('one', 'rev-1')
+ b2 = b1.bzrdir.open_branch()
+ b1.lock_read()
+ self.assertEqual({'one': 'rev-1'}, b1.tags.get_tag_dict())
+ # Add a tag and modify a tag in b2. b1 is read-locked and has already
+ # read the tags, so it is unaffected.
+ b2.tags.set_tag('one', 'rev-1-changed')
+ b2.tags.set_tag('two', 'rev-2')
+ self.assertEqual({'one': 'rev-1'}, b1.tags.get_tag_dict())
+ b1.unlock()
+ # Once unlocked the cached value is forgotten, so now the latest tags
+ # will be retrieved.
+ self.assertEqual(
+ {'one': 'rev-1-changed', 'two': 'rev-2'}, b1.tags.get_tag_dict())
+
+ def test_unlocked_does_not_cache_tags(self):
+ """Unlocked branches do not cache tags."""
+ # Open the same branch twice.
+ b1 = self.make_branch('b')
+ b1.tags.set_tag('one', 'rev-1')
+ b2 = b1.bzrdir.open_branch()
+ self.assertEqual({'one': 'rev-1'}, b1.tags.get_tag_dict())
+ # Add a tag and modify a tag in b2. b1 isn't locked, so it will
+ # immediately return the new tags too.
+ b2.tags.set_tag('one', 'rev-1-changed')
+ b2.tags.set_tag('two', 'rev-2')
+ self.assertEqual(
+ {'one': 'rev-1-changed', 'two': 'rev-2'}, b1.tags.get_tag_dict())
+
+ def test_cached_tag_dict_not_accidentally_mutable(self):
+ """When there's a cached version of the tags, b.tags.get_tag_dict
+ returns a copy of the cached data so that callers cannot accidentally
+ corrupt the cache.
+ """
+ b = self.make_branch('b')
+ b.tags.set_tag('one', 'rev-1')
+ self.addCleanup(b.lock_read().unlock)
+ # The first time the data returned will not be in the cache
+ tags_dict = b.tags.get_tag_dict()
+ tags_dict['two'] = 'rev-2'
+ # The second time the data comes from the cache
+ tags_dict = b.tags.get_tag_dict()
+ tags_dict['three'] = 'rev-3'
+ # The get_tag_dict() result should still be unchanged, even though we
+ # mutated its earlier return values.
+ self.assertEqual({'one': 'rev-1'}, b.tags.get_tag_dict())
+
+ def make_write_locked_branch_with_one_tag(self):
+ b = self.make_branch('b')
+ b.tags.set_tag('one', 'rev-1')
+ self.addCleanup(b.lock_write().unlock)
+ # Populate the cache
+ b.tags.get_tag_dict()
+ return b
+
+ def test_set_tag_invalides_cache(self):
+ b = self.make_write_locked_branch_with_one_tag()
+ b.tags.set_tag('one', 'rev-1-changed')
+ self.assertEqual({'one': 'rev-1-changed'}, b.tags.get_tag_dict())
+
+ def test_delete_tag_invalides_cache(self):
+ b = self.make_write_locked_branch_with_one_tag()
+ b.tags.delete_tag('one')
+ self.assertEqual({}, b.tags.get_tag_dict())
+
+ def test_merge_to_invalides_cache(self):
+ b1 = self.make_write_locked_branch_with_one_tag()
+ b2 = self.make_branch('b2')
+ b2.tags.set_tag('two', 'rev-2')
+ b2.tags.merge_to(b1.tags)
+ self.assertEqual(
+ {'one': 'rev-1', 'two': 'rev-2'}, b1.tags.get_tag_dict())
+
+ def test_rename_revisions_invalides_cache(self):
+ b = self.make_write_locked_branch_with_one_tag()
+ b.tags.rename_revisions({'rev-1': 'rev-1-changed'})
+ self.assertEqual({'one': 'rev-1-changed'}, b.tags.get_tag_dict())
+
class TestUnsupportedTags(per_branch.TestCaseWithBranch):
"""Formats that don't support tags should give reasonable errors."""
=== modified file 'doc/en/release-notes/bzr-2.3.txt'
--- a/doc/en/release-notes/bzr-2.3.txt 2010-11-10 16:24:31 +0000
+++ b/doc/en/release-notes/bzr-2.3.txt 2010-11-12 09:35:46 +0000
@@ -26,6 +26,10 @@
.. Improvements to existing commands, especially improved performance
or memory usage, or better results.
+* Bazaar now caches a branch's tags while that branch is read-locked.
+ This removes 1 network roundtrip from most interactions with a remote
+ branch. (Andrew Bennetts)
+
* ``bzr config <option>`` will now display only the value itself so scripts
can use it to query the currently active configuration. Displaying several
options matching a given regular expression is now controlled via the
More information about the bazaar-commits
mailing list