use of org.locationtech.geogig.storage.GraphDatabase.GraphNode in project GeoGig by boundlessgeo.
the class CheckSparsePath method isSparsePath.
/**
* Recursive brute force function to exhaustively search for all paths between the start and end
* node. This should be optimized to avoid unnecessary work in the future.
*/
private boolean isSparsePath(GraphNode node, ObjectId end, boolean sparse) {
if (node.getIdentifier().equals(end)) {
return sparse;
}
Iterator<GraphEdge> outgoing = node.getEdges(Direction.OUT);
if (outgoing.hasNext()) {
boolean node_sparse = node.isSparse();
boolean combined_sparse = false;
while (outgoing.hasNext()) {
GraphEdge parent = outgoing.next();
GraphNode parentNode = parent.getToNode();
combined_sparse = combined_sparse || isSparsePath(parentNode, end, sparse || node_sparse);
}
return combined_sparse;
}
return false;
}
use of org.locationtech.geogig.storage.GraphDatabase.GraphNode in project GeoGig by boundlessgeo.
the class FindCommonAncestor method processCommit.
/**
* Process a commit to see if it has already been seen. If it has, prevent unnecessary work from
* continuing on the other traversal queue. If it hasn't, add it's parents to the traversal
* queue.
*
* @param commit commit to process
* @param myQueue my traversal queue
* @param mySet my visited nodes
* @param theirQueue other traversal queue
* @param theirSet other traversal's visited nodes
* @return
*/
private boolean processCommit(GraphNode commit, Queue<GraphNode> myQueue, Set<GraphNode> mySet, Queue<GraphNode> theirQueue, Set<GraphNode> theirSet) {
if (mySet.add(commit)) {
if (theirSet.contains(commit)) {
stopAncestryPath(commit, theirQueue, theirSet);
return true;
}
Iterator<GraphEdge> edges = commit.getEdges(Direction.OUT);
while (edges.hasNext()) {
GraphEdge parentEdge = edges.next();
GraphNode parent = parentEdge.getToNode();
myQueue.add(parent);
}
}
return false;
}
use of org.locationtech.geogig.storage.GraphDatabase.GraphNode in project GeoGig by boundlessgeo.
the class FindCommonAncestor method verifyAncestors.
/**
* This function is called at the end of the traversal to make sure none of our results have a
* more recent ancestor in the result list.
*
* @param potentialCommonAncestors the result list
* @param leftSet the visited nodes of the left traversal
* @param rightSet the visited nodes of the right traversal
*/
private void verifyAncestors(List<GraphNode> potentialCommonAncestors, Set<GraphNode> leftSet, Set<GraphNode> rightSet) {
Queue<GraphNode> ancestorQueue = new LinkedList<GraphNode>();
List<GraphNode> falseAncestors = new LinkedList<GraphNode>();
List<GraphNode> processed = new LinkedList<GraphNode>();
for (GraphNode v : potentialCommonAncestors) {
if (falseAncestors.contains(v)) {
continue;
}
ancestorQueue.add(v);
while (!ancestorQueue.isEmpty()) {
GraphNode ancestor = ancestorQueue.poll();
Iterator<GraphEdge> edges = ancestor.getEdges(Direction.OUT);
while (edges.hasNext()) {
GraphEdge parent = edges.next();
GraphNode parentNode = parent.getToNode();
if (parentNode.getIdentifier() != ancestor.getIdentifier()) {
if (leftSet.contains(parentNode) || rightSet.contains(parentNode)) {
if (!processed.contains(parentNode)) {
ancestorQueue.add(parentNode);
processed.add(parentNode);
}
if (potentialCommonAncestors.contains(parentNode)) {
falseAncestors.add(parentNode);
}
}
}
}
}
}
potentialCommonAncestors.removeAll(falseAncestors);
}
use of org.locationtech.geogig.storage.GraphDatabase.GraphNode in project GeoGig by boundlessgeo.
the class FindCommonAncestor method stopAncestryPath.
/**
* This function is called when a common ancestor is found and the other traversal queue should
* stop traversing down the history of that particular commit. Any ancestors caught after this
* one will be an older ancestor. This function follows the ancestry of the common ancestor
* until it has been removed from the opposite traversal queue.
*
* @param commit the common ancestor
* @param theirQueue the opposite traversal queue
* @param theirSet the opposite visited nodes
*/
private void stopAncestryPath(GraphNode commit, Queue<GraphNode> theirQueue, Set<GraphNode> theirSet) {
Queue<GraphNode> ancestorQueue = new LinkedList<GraphNode>();
ancestorQueue.add(commit);
Set<GraphNode> processed = new HashSet<GraphNode>();
while (!ancestorQueue.isEmpty()) {
GraphNode ancestor = ancestorQueue.poll();
Iterator<GraphEdge> edges = ancestor.getEdges(Direction.OUT);
while (edges.hasNext()) {
GraphEdge relationship = edges.next();
GraphNode parentNode = relationship.getToNode();
if (theirSet.contains(parentNode)) {
if (!processed.contains(parentNode)) {
ancestorQueue.add(parentNode);
processed.add(parentNode);
}
} else {
theirQueue.remove(parentNode);
}
}
}
}
use of org.locationtech.geogig.storage.GraphDatabase.GraphNode in project GeoGig by boundlessgeo.
the class FindCommonAncestor method findLowestCommonAncestor.
/**
* Finds the lowest common ancestor of two commits.
*
* @param leftId the commit id of the left commit
* @param rightId the commit id of the right commit
* @return An {@link Optional} of the lowest common ancestor of the two commits, or
* {@link Optional#absent()} if a common ancestor could not be found.
*/
public Optional<ObjectId> findLowestCommonAncestor(ObjectId leftId, ObjectId rightId) {
Set<GraphNode> leftSet = new HashSet<GraphNode>();
Set<GraphNode> rightSet = new HashSet<GraphNode>();
Queue<GraphNode> leftQueue = new LinkedList<GraphNode>();
Queue<GraphNode> rightQueue = new LinkedList<GraphNode>();
GraphDatabase graphDb = graphDatabase();
GraphNode leftNode = graphDb.getNode(leftId);
leftQueue.add(leftNode);
GraphNode rightNode = graphDb.getNode(rightId);
rightQueue.add(rightNode);
List<GraphNode> potentialCommonAncestors = new LinkedList<GraphNode>();
while (!leftQueue.isEmpty() || !rightQueue.isEmpty()) {
if (!leftQueue.isEmpty()) {
GraphNode commit = leftQueue.poll();
if (processCommit(commit, leftQueue, leftSet, rightQueue, rightSet)) {
potentialCommonAncestors.add(commit);
}
}
if (!rightQueue.isEmpty()) {
GraphNode commit = rightQueue.poll();
if (processCommit(commit, rightQueue, rightSet, leftQueue, leftSet)) {
potentialCommonAncestors.add(commit);
}
}
}
verifyAncestors(potentialCommonAncestors, leftSet, rightSet);
Optional<ObjectId> ancestor = Optional.absent();
if (potentialCommonAncestors.size() > 0) {
ancestor = Optional.of(potentialCommonAncestors.get(0).getIdentifier());
}
return ancestor;
}
Aggregations