/**
   * Helper method for parallelizing a given fragment. Dependent fragments are parallelized first
   * before parallelizing the given fragment.
   */
  private void parallelizeFragment(
      Wrapper fragmentWrapper,
      PlanningSet planningSet,
      Collection<DrillbitEndpoint> activeEndpoints)
      throws PhysicalOperatorSetupException {
    // If the fragment is already parallelized, return.
    if (fragmentWrapper.isEndpointsAssignmentDone()) {
      return;
    }

    // First parallelize fragments on which this fragment depends on.
    final List<Wrapper> fragmentDependencies = fragmentWrapper.getFragmentDependencies();
    if (fragmentDependencies != null && fragmentDependencies.size() > 0) {
      for (Wrapper dependency : fragmentDependencies) {
        parallelizeFragment(dependency, planningSet, activeEndpoints);
      }
    }

    // Find stats. Stats include various factors including cost of physical operators,
    // parallelizability of
    // work in physical operator and affinity of physical operator to certain nodes.
    fragmentWrapper.getNode().getRoot().accept(new StatsCollector(planningSet), fragmentWrapper);

    fragmentWrapper
        .getStats()
        .getDistributionAffinity()
        .getFragmentParallelizer()
        .parallelizeFragment(fragmentWrapper, this, activeEndpoints);
  }
  /**
   * Helper method to reuse the code for QueryWorkUnit(s) generation
   *
   * @param activeEndpoints
   * @param rootFragment
   * @return
   * @throws ExecutionSetupException
   */
  protected PlanningSet getFragmentsHelper(
      Collection<DrillbitEndpoint> activeEndpoints, Fragment rootFragment)
      throws ExecutionSetupException {

    PlanningSet planningSet = new PlanningSet();

    initFragmentWrappers(rootFragment, planningSet);

    final Set<Wrapper> leafFragments = constructFragmentDependencyGraph(planningSet);

    // Start parallelizing from leaf fragments
    for (Wrapper wrapper : leafFragments) {
      parallelizeFragment(wrapper, planningSet, activeEndpoints);
    }

    return planningSet;
  }