/** Creates new DeadlockGraph from plan and checks for cycles */ public boolean hasDeadlock(List<? extends PlanNode> sinks) { this.g = new DeadlockGraph(); for (PlanNode s : sinks) { s.accept(this); } if (g.hasCycle()) { return true; } else { return false; } }
public void resolveDeadlocks(List<? extends PlanNode> sinks) { for (PlanNode s : sinks) { s.accept(this); } if (g.hasCycle()) { // in the remaining plan is a cycle for (DeadlockVertex v : g.vertices) { // first strategy to fix -> swap build and probe side if (v.getOriginal().getDriverStrategy().equals(DriverStrategy.HYBRIDHASH_BUILD_FIRST)) { v.getOriginal().setDriverStrategy(DriverStrategy.HYBRIDHASH_BUILD_SECOND); if (hasDeadlock(sinks)) { // Didn't fix anything -> revert v.getOriginal().setDriverStrategy(DriverStrategy.HYBRIDHASH_BUILD_FIRST); } else { // deadlock resolved break; } } // other direction if (v.getOriginal().getDriverStrategy().equals(DriverStrategy.HYBRIDHASH_BUILD_SECOND)) { v.getOriginal().setDriverStrategy(DriverStrategy.HYBRIDHASH_BUILD_FIRST); if (hasDeadlock(sinks)) { // Didn't fix anything -> revert v.getOriginal().setDriverStrategy(DriverStrategy.HYBRIDHASH_BUILD_SECOND); } else { // deadlock resolved break; } } } // switching build and probe side did not help -> pipeline breaker for (DeadlockVertex v : g.vertices) { if (v.getOriginal() instanceof DualInputPlanNode) { DualInputPlanNode n = (DualInputPlanNode) v.getOriginal(); // what is the pipelined side? (other side should be a dam, otherwise operator could not // be source of deadlock) if (!(n.getDriverStrategy().firstDam().equals(DamBehavior.FULL_DAM) || n.getInput1().getLocalStrategy().dams() || n.getInput1().getTempMode().breaksPipeline()) && (n.getDriverStrategy().secondDam().equals(DamBehavior.FULL_DAM) || n.getInput2().getLocalStrategy().dams() || n.getInput2().getTempMode().breaksPipeline())) { n.getInput1().setTempMode(n.getInput1().getTempMode().makePipelineBreaker()); } else if (!(n.getDriverStrategy().secondDam().equals(DamBehavior.FULL_DAM) || n.getInput2().getLocalStrategy().dams() || n.getInput2().getTempMode().breaksPipeline()) && (n.getDriverStrategy().firstDam().equals(DamBehavior.FULL_DAM) || n.getInput1().getLocalStrategy().dams() || n.getInput1().getTempMode().breaksPipeline())) { n.getInput2().setTempMode(n.getInput2().getTempMode().makePipelineBreaker()); } // Deadlock resolved? if (!hasDeadlock(sinks)) { break; } } } } }