public List<ExecEdge> computeCriticalPath(ExecVertex start, ExecVertex stop) { this.start = start; this.stop = stop; visitedEdges = new HashSet<ExecEdge>(); Stack<ExecVertex> splits = new Stack<ExecVertex>(); Stack<ExecEdge> path = new Stack<ExecEdge>(); HashSet<ExecVertex> visitedSplits = new HashSet<ExecVertex>(); ExecVertex curr = start; while (curr != null) { // FIXME: check time bounds to stop traversing non-convergent path if (curr == stop) { log.debug("stop verted reached, break"); break; } log.debug("processing " + curr); ExecEdge selfEdge = null; ExecVertex next = null; Set<ExecEdge> out = graph.getGraph().outgoingEdgesOf(curr); for (ExecEdge e : out) { ExecVertex target = graph.getGraph().getEdgeTarget(e); if (target.getOwner() != curr.getOwner()) { if (!visitedSplits.contains(curr)) { log.debug("push split vertex " + curr); splits.push(curr); visitedSplits.add(curr); } } else { log.debug("push self edge " + e); selfEdge = e; } } if (selfEdge != null) { path.push(selfEdge); } // detect blocking if (path.peek().getType() == EdgeType.BLOCKED && splits.isEmpty()) { log.debug("blocking ahead, splits empty, search for new head"); ExecVertex mergeVertex = graph.getGraph().getEdgeTarget(path.peek()); Set<ExecEdge> incomingEdges = graph.getGraph().incomingEdgesOf(mergeVertex); ExecEdge mergeEdge = null; for (ExecEdge edge : incomingEdges) { ExecVertex source = graph.getGraph().getEdgeSource(edge); ExecVertex target = graph.getGraph().getEdgeTarget(edge); if (source.getOwner() != target.getOwner()) { mergeEdge = edge; break; } } if (mergeEdge == null) { log.debug("no merge edge found, break"); break; } log.debug("clear path"); path.clear(); // roll-back // FIXME: make sure we traverse connected edges ExecVertex source = graph.getGraph().getEdgeSource(mergeEdge); List<ExecVertex> list = graph.getVertexMap().get(source.getOwner()); int index = BinarySearch.floor(list, start); next = list.get(index); log.debug("changing curr to " + next); } else if (path.peek().getType() == EdgeType.BLOCKED || selfEdge == null) { if (path.peek().getType() == EdgeType.BLOCKED) log.debug("blocking ahead"); if (selfEdge == null) log.debug("dead-end ahead"); if (splits.isEmpty()) { log.debug("splits empty, break"); break; } else { ExecVertex top = splits.pop(); // rewind path to top split vertex log.debug("rewind path until " + top); while (!path.isEmpty() && graph.getGraph().getEdgeTarget(path.peek()) != top) { ExecEdge edge = path.pop(); log.debug("pop " + edge); } if (!path.isEmpty()) log.debug("path.peek() " + path.peek()); // switch actor out = graph.getGraph().outgoingEdgesOf(top); for (ExecEdge e : out) { ExecVertex target = graph.getGraph().getEdgeTarget(e); if (target.getOwner() != top.getOwner()) { path.push(e); next = target; break; } } } } else { next = graph.getGraph().getEdgeTarget(selfEdge); log.debug("self next " + next); } if (curr.getOwner() != next.getOwner()) { log.debug("switch actor from " + curr.getOwner() + " to " + next.getOwner()); } if (curr == next) { log.debug("the algorithm do not progress, break"); break; } curr = next; log.debug("stack splits:"); for (ExecVertex split : splits) { log.debug(" " + split); } log.debug("stack path:"); for (ExecEdge edge : path) { log.debug(" " + edge); } } propagateParentOwner(graph, path); return path; }