Rev 4193: Allow optional inclusion of ghost data in server get_parent_map calls. in http://people.ubuntu.com/~robertc/baz2.0/pending/Remote.negative_parents_cache
Robert Collins
robertc at robertcollins.net
Tue Mar 24 06:07:43 GMT 2009
At http://people.ubuntu.com/~robertc/baz2.0/pending/Remote.negative_parents_cache
------------------------------------------------------------
revno: 4193
revision-id: robertc at robertcollins.net-20090324060735-nk6ti3wq06062lvz
parent: robertc at robertcollins.net-20090324053736-rgxw7s77h2948gf2
committer: Robert Collins <robertc at robertcollins.net>
branch nick: Remote.negative_parents_cache
timestamp: Tue 2009-03-24 17:07:35 +1100
message:
Allow optional inclusion of ghost data in server get_parent_map calls.
=== modified file 'NEWS'
--- a/NEWS 2009-03-24 05:37:36 +0000
+++ b/NEWS 2009-03-24 06:07:35 +0000
@@ -208,6 +208,11 @@
whether the repository can efficiently generate deltas between trees
regardless of tree size. (Robert Collins)
+* The smart server verb ``Repository.get_parent_map`` can now include
+ information about ghosts when the special revision ``include-missing:``
+ is in the requested parents map list. With this flag, ghosts are
+ included as ``missing:REVISION_ID``. (Robert Collins, Andrew Bennetts)
+
* ``_walk_to_common_revisions`` will now batch up at least 50
revisions before calling ``get_parent_map`` on the target,
regardless of ``InterRepository``.
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2009-03-24 05:11:56 +0000
+++ b/bzrlib/remote.py 2009-03-24 06:07:35 +0000
@@ -1230,11 +1230,19 @@
# TODO: Manage this incrementally to avoid covering the same path
# repeatedly. (The server will have to on each request, but the less
# work done the better).
+ #
+ # Negative caching notes:
+ # new server sends missing when a request including the revid
+ # 'include-missing:' is present in the request.
+ # missing keys are serialised as missing:X, and we then call
+ # provider.note_missing(X) for-all X
parents_map = self._unstacked_provider.get_cached_map()
if parents_map is None:
# Repository is not locked, so there's no cache.
parents_map = {}
+ # start_set is all the keys in the cache
start_set = set(parents_map)
+ # result set is all the references to keys in the cache
result_parents = set()
for parents in parents_map.itervalues():
result_parents.update(parents)
=== modified file 'bzrlib/smart/repository.py'
--- a/bzrlib/smart/repository.py 2009-03-17 06:18:16 +0000
+++ b/bzrlib/smart/repository.py 2009-03-24 06:07:35 +0000
@@ -134,6 +134,10 @@
from revision_ids is returned. The verb takes a body containing the
current search state, see do_body for details.
+ If 'include-missing' is in revision_ids, ghosts encountered in the
+ graph traversal for getting parent data are included in the result with
+ a prefix of 'missing:'.
+
:param repository: The repository to query in.
:param revision_ids: The utf8 encoded revision_id to answer for.
"""
@@ -158,6 +162,9 @@
def _do_repository_request(self, body_bytes):
repository = self._repository
revision_ids = set(self._revision_ids)
+ include_missing = 'include-missing:' in revision_ids
+ if include_missing:
+ revision_ids.remove('include-missing:')
body_lines = body_bytes.split('\n')
search_result, error = self.recreate_search_from_recipe(
repository, body_lines)
@@ -178,19 +185,29 @@
while next_revs:
queried_revs.update(next_revs)
parent_map = repo_graph.get_parent_map(next_revs)
+ current_revs = next_revs
next_revs = set()
- for revision_id, parents in parent_map.iteritems():
- # adjust for the wire
- if parents == (_mod_revision.NULL_REVISION,):
- parents = ()
- # prepare the next query
- next_revs.update(parents)
- if revision_id not in client_seen_revs:
+ for revision_id in current_revs:
+ missing_rev = False
+ parents = parent_map.get(revision_id)
+ if parents is not None:
+ # adjust for the wire
+ if parents == (_mod_revision.NULL_REVISION,):
+ parents = ()
+ # prepare the next query
+ next_revs.update(parents)
+ encoded_id = revision_id
+ else:
+ missing_rev = True
+ encoded_id = "missing:" + revision_id
+ parents = []
+ if (revision_id not in client_seen_revs and
+ (not missing_rev or include_missing)):
# Client does not have this revision, give it to it.
# add parents to the result
- result[revision_id] = parents
+ result[encoded_id] = parents
# Approximate the serialized cost of this revision_id.
- size_so_far += 2 + len(revision_id) + sum(map(len, parents))
+ size_so_far += 2 + len(encoded_id) + sum(map(len, parents))
# get all the directly asked for parents, and then flesh out to
# 64K (compressed) or so. We do one level of depth at a time to
# stay in sync with the client. The 250000 magic number is
=== modified file 'bzrlib/tests/test_smart.py'
--- a/bzrlib/tests/test_smart.py 2009-03-16 08:26:29 +0000
+++ b/bzrlib/tests/test_smart.py 2009-03-24 06:07:35 +0000
@@ -914,11 +914,23 @@
self.assertEqual(None,
request.execute('', 'missing-id'))
- # Note that it returns a body (of '' bzipped).
+ # Note that it returns a body that is bzipped.
self.assertEqual(
SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
request.do_body('\n\n0\n'))
+ def test_trivial_include_missing(self):
+ backing = self.get_transport()
+ request = smart.repository.SmartServerRepositoryGetParentMap(backing)
+ tree = self.make_branch_and_memory_tree('.')
+
+ self.assertEqual(None,
+ request.execute('', 'missing-id', 'include-missing:'))
+ self.assertEqual(
+ SuccessfulSmartServerResponse(('ok', ),
+ bz2.compress('missing:missing-id')),
+ request.do_body('\n\n0\n'))
+
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
More information about the bazaar-commits
mailing list