131
132
raise errors.UnexpectedSmartServerResponse(response)
134
def _get_tree_branch(self):
135
"""See BzrDir._get_tree_branch()."""
136
return None, self.open_branch()
133
138
def open_branch(self, _unsupported=False):
134
139
assert _unsupported == False, 'unsupported flag support not implemented yet.'
135
140
reference_url = self.get_branch_reference()
268
273
self._leave_lock = False
269
274
# A cache of looked up revision parent data; reset at unlock time.
270
275
self._parents_map = None
276
if 'hpss' in debug.debug_flags:
277
self._requested_parents = None
272
279
# These depend on the actual remote format, so force them off for
273
280
# maximum compatibility. XXX: In future these should depend on the
777
790
len(set(ancestry).intersection(parent_map)),
779
792
ancestry.update(parent_map)
780
return dict((k, ancestry[k]) for k in keys if k in ancestry)
793
present_keys = [k for k in keys if k in ancestry]
794
if 'hpss' in debug.debug_flags:
795
self._requested_parents.update(present_keys)
796
mutter('Current RemoteRepository graph hit rate: %d%%',
797
100.0 * len(self._requested_parents) / len(ancestry))
798
return dict((k, ancestry[k]) for k in present_keys)
782
800
def _response_is_unknown_method(self, response, verb):
783
801
"""Return True if response is an unknonwn method response to verb.
814
832
return found_parents
816
834
found_parents = {}
835
# TODO(Needs analysis): We could assume that the keys being requested
836
# from get_parent_map are in a breadth first search, so typically they
837
# will all be depth N from some common parent, and we don't have to
838
# have the server iterate from the root parent, but rather from the
839
# keys we're searching; and just tell the server the keyspace we
840
# already have; but this may be more traffic again.
842
# Transform self._parents_map into a search request recipe.
843
# TODO: Manage this incrementally to avoid covering the same path
844
# repeatedly. (The server will have to on each request, but the less
845
# work done the better).
846
parents_map = self._parents_map
847
if parents_map is None:
848
# Repository is not locked, so there's no cache.
850
start_set = set(parents_map)
851
result_parents = set()
852
for parents in parents_map.itervalues():
853
result_parents.update(parents)
854
stop_keys = result_parents.difference(start_set)
855
included_keys = start_set.intersection(result_parents)
856
start_set.difference_update(included_keys)
857
recipe = (start_set, stop_keys, len(parents_map))
858
body = self._serialise_search_recipe(recipe)
817
859
path = self.bzrdir._path_for_remote_call(self._client)
819
861
assert type(key) is str
820
862
verb = 'Repository.get_parent_map'
821
response = self._client.call_expecting_body(
863
args = (path,) + tuple(keys)
864
response = self._client.call_with_body_bytes_expecting_body(
865
verb, args, self._serialise_search_recipe(recipe))
823
866
if self._response_is_unknown_method(response, verb):
824
867
# Server does not support this method, so get the whole graph.
825
868
# Worse, we have to force a disconnection, because the server now
837
880
reponse[1].cancel_read_body()
838
881
raise errors.UnexpectedSmartServerResponse(response[0])
839
882
if response[0][0] == 'ok':
840
coded = response[1].read_body_bytes()
883
coded = bz2.decompress(response[1].read_body_bytes())
842
885
# no revisions found
994
1037
return self._real_repository.get_data_stream_for_search(search)
995
1038
REQUEST_NAME = 'Repository.stream_revisions_chunked'
996
1039
path = self.bzrdir._path_for_remote_call(self._client)
997
recipe = search.get_recipe()
998
start_keys = ' '.join(recipe[0])
999
stop_keys = ' '.join(recipe[1])
1000
count = str(recipe[2])
1001
body = '\n'.join((start_keys, stop_keys, count))
1040
body = self._serialise_search_recipe(search.get_recipe())
1002
1041
response, protocol = self._client.call_with_body_bytes_expecting_body(
1003
1042
REQUEST_NAME, (path,), body)
1067
1106
def _make_parents_provider(self):
1109
def _serialise_search_recipe(self, recipe):
1110
"""Serialise a graph search recipe.
1112
:param recipe: A search recipe (start, stop, count).
1113
:return: Serialised bytes.
1115
start_keys = ' '.join(recipe[0])
1116
stop_keys = ' '.join(recipe[1])
1117
count = str(recipe[2])
1118
return '\n'.join((start_keys, stop_keys, count))
1071
1121
class RemoteBranchLockableFiles(LockableFiles):
1072
1122
"""A 'LockableFiles' implementation that talks to a smart server.