Rev 3405: Try using _find_any_seen_ancestors, in http://bzr.arbash-meinel.com/branches/bzr/1.4-dev/find_unique_ancestors
John Arbash Meinel
john at arbash-meinel.com
Fri Apr 25 03:00:26 BST 2008
At http://bzr.arbash-meinel.com/branches/bzr/1.4-dev/find_unique_ancestors
------------------------------------------------------------
revno: 3405
revision-id: john at arbash-meinel.com-20080425015422-k2xb2p6k6sgxwt5s
parent: john at arbash-meinel.com-20080425004033-y7p8ol60qntr1pyn
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: find_unique_ancestors
timestamp: Thu 2008-04-24 20:54:22 -0500
message:
Try using _find_any_seen_ancestors,
which pulls out the loop around find_seen_ancestors.
This may not be a net win yet.
modified:
bzrlib/graph.py graph_walker.py-20070525030359-y852guab65d4wtn0-1
-------------- next part --------------
=== modified file 'bzrlib/graph.py'
--- a/bzrlib/graph.py 2008-04-25 00:40:33 +0000
+++ b/bzrlib/graph.py 2008-04-25 01:54:22 +0000
@@ -159,6 +159,52 @@
def __repr__(self):
return 'Graph(%r)' % self._parents_provider
+ def _find_any_seen_ancestors(self, revisions, searchers):
+ """Find any revisions that are seen by any of the searchers."""
+ # This will actually return more nodes than just aggregating
+ # find_seen_ancestors() across the searchers, because it can bridge
+ # 1-node gaps inline.
+
+ # seen contains what nodes have been returned, not what nodes
+ # have been queried. We don't want to probe for nodes that haven't
+ # been searched yet.
+ all_seen = set()
+ not_searched_yet = set()
+ for searcher in searchers:
+ all_seen.update(searcher.seen)
+
+ not_searched = set(searcher._next_query)
+ # Have these nodes been searched in any other searcher?
+ for other_searcher in searchers:
+ if other_searcher is searcher:
+ continue
+ # This other searcher claims to have seen these nodes
+ maybe_searched = not_searched.intersection(other_searcher.seen)
+ searched = maybe_searched.difference(other_searcher._next_query)
+ not_searched.difference_update(searched)
+
+ # Now we know the real ones that haven't been searched
+ not_searched_yet.update(not_searched)
+
+ pending = set(revisions).intersection(all_seen)
+ seen_ancestors = set(pending)
+
+ pending.difference_update(not_searched_yet)
+ get_parent_map = self._parents_provider.get_parent_map
+ while pending:
+ parent_map = get_parent_map(pending)
+ all_parents = []
+ # We don't care if it is a ghost, since it can't be seen if it is
+ # a ghost
+ for parent_ids in parent_map.itervalues():
+ all_parents.extend(parent_ids)
+ next_pending = all_seen.intersection(all_parents).difference(seen_ancestors)
+ seen_ancestors.update(next_pending)
+ next_pending.difference_update(not_searched_yet)
+ pending = next_pending
+
+ return seen_ancestors
+
def find_lca(self, *revisions):
"""Determine the lowest common ancestors of the provided revisions
@@ -253,9 +299,8 @@
unique_are_common_nodes.update(
next_common_nodes.intersection(unique_searcher.seen))
if unique_are_common_nodes:
- ancestors = unique_searcher.find_seen_ancestors(
- unique_are_common_nodes)
- ancestors.update(common_searcher.find_seen_ancestors(ancestors))
+ ancestors = self._find_any_seen_ancestors(unique_are_common_nodes,
+ [unique_searcher, common_searcher])
unique_searcher.stop_searching_any(ancestors)
common_searcher.start_searching(ancestors)
@@ -265,7 +310,6 @@
unique_tips = self._remove_simple_descendants(unique_nodes,
self.get_parent_map(unique_nodes))
- # TODO: setup the unique searchers, and keep searching until done
unique_searchers = []
for tip in unique_tips:
revs_to_search = unique_searcher.find_seen_ancestors([tip])
@@ -284,7 +328,7 @@
# Stop any search tips that are already known as ancestors of the
# unique nodes
- stopped = common_searcher.stop_searching_any(
+ common_searcher.stop_searching_any(
common_searcher.find_seen_ancestors(ancestor_all_unique))
# While we still have common nodes to search
@@ -306,13 +350,10 @@
ancestor_all_unique.intersection(newly_seen_common))
if unique_are_common_nodes:
# We have new common-to-all-unique-searchers nodes
- for searcher in unique_searchers:
- unique_are_common_nodes.update(
- searcher.find_seen_ancestors(unique_are_common_nodes))
- # Since these are common, we can grab another set of ancestors
- # that we have seen
+ # Which also means we can check in the common_searcher
unique_are_common_nodes.update(
- common_searcher.find_seen_ancestors(unique_are_common_nodes))
+ self._find_any_seen_ancestors(unique_are_common_nodes,
+ [common_searcher] + unique_searchers))
# We can tell all of the unique searchers to start at these
# nodes, and tell all of the common searchers to *stop*
More information about the bazaar-commits
mailing list