public void constructList() throws Exception { // // Create a counter for each node based on the # of children that it has // If any node has no children, put it in the execute list // List<AbstractPlanNode> execute_list = Collections.synchronizedList(new ArrayList<AbstractPlanNode>()); Map<AbstractPlanNode, Integer> child_cnts = new HashMap<AbstractPlanNode, Integer>(); for (AbstractPlanNode node : m_planNodes) { int num_of_children = node.getChildCount(); if (num_of_children == 0) { execute_list.add(node); } else { child_cnts.put(node, num_of_children); } } // // Now run through a simulation // Doing it this way maintains the nuances of the parent-child relationships // m_list.clear(); while (!execute_list.isEmpty()) { AbstractPlanNode node = execute_list.remove(0); // // Add the node to our execution list // m_list.add(node); // // Then update all of this node's parents and reduce their wait counter by 1 // If the counter is at zero, then we'll add it to end of our list // for (int i = 0; i < node.getParentCount(); i++) { AbstractPlanNode parent = node.getParent(i); int remaining = child_cnts.get(parent) - 1; child_cnts.put(parent, remaining); if (remaining == 0) { execute_list.add(parent); } } } // // Important! Make sure that our list has the same number of entries in our tree // if (m_list.size() != m_planNodes.size()) { throw new Exception( "ERROR: The execution list has '" + m_list.size() + "' PlanNodes but our original tree has '" + m_planNodes.size() + "' PlanNode entries"); } return; }