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