/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.tajo.engine.planner.global; import java.util.ArrayList; import java.util.Stack; /** * A distributed execution plan (DEP) is a direct acyclic graph (DAG) of ExecutionBlocks. * This class is a pointer to an ExecutionBlock that the query engine should execute. * For each call of nextBlock(), it retrieves a next ExecutionBlock in a postfix order. */ public class ExecutionBlockCursor { private MasterPlan masterPlan; private ArrayList<ExecutionBlock> orderedBlocks = new ArrayList<ExecutionBlock>(); private int cursor = 0; public ExecutionBlockCursor(MasterPlan plan) { this.masterPlan = plan; buildOrder(plan.getRoot()); } public int size() { return orderedBlocks.size(); } // Add all execution blocks in a depth first and postfix order private void buildOrder(ExecutionBlock current) { Stack<ExecutionBlock> stack = new Stack<ExecutionBlock>(); if (!masterPlan.isLeaf(current.getId())) { for (ExecutionBlock execBlock : masterPlan.getChilds(current)) { if (!masterPlan.isLeaf(execBlock)) { buildOrder(execBlock); } else { stack.push(execBlock); } } for (ExecutionBlock execBlock : stack) { buildOrder(execBlock); } } orderedBlocks.add(current); } public boolean hasNext() { return cursor < orderedBlocks.size(); } public ExecutionBlock nextBlock() { return orderedBlocks.get(cursor++); } public ExecutionBlock peek() { return orderedBlocks.get(cursor); } public ExecutionBlock peek(int skip) { return orderedBlocks.get(cursor + skip); } public void reset() { cursor = 0; } public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < orderedBlocks.size(); i++) { if (i == (cursor == 0 ? 0 : cursor - 1)) { sb.append("(").append(orderedBlocks.get(i).getId().getId()).append(")"); } else { sb.append(orderedBlocks.get(i).getId().getId()); } if (i < orderedBlocks.size() - 1) { sb.append(","); } } return sb.toString(); } }