示例#1
0
  private void schedule() {
    try (SetThreadName ignored = new SetThreadName("Query-%s", queryStateMachine.getQueryId())) {
      Set<StageId> completedStages = new HashSet<>();
      ExecutionSchedule executionSchedule =
          executionPolicy.createExecutionSchedule(stages.values());
      while (!executionSchedule.isFinished()) {
        List<CompletableFuture<?>> blockedStages = new ArrayList<>();
        for (SqlStageExecution stage : executionSchedule.getStagesToSchedule()) {
          stage.beginScheduling();

          // perform some scheduling work
          ScheduleResult result = stageSchedulers.get(stage.getStageId()).schedule();

          // modify parent and children based on the results of the scheduling
          if (result.isFinished()) {
            stage.schedulingComplete();
          } else if (!result.getBlocked().isDone()) {
            blockedStages.add(result.getBlocked());
          }
          stageLinkages
              .get(stage.getStageId())
              .processScheduleResults(stage.getState(), result.getNewTasks());
        }

        // make sure to update stage linkage at least once per loop to catch async state changes
        // (e.g., partial cancel)
        for (SqlStageExecution stage : stages.values()) {
          if (!completedStages.contains(stage.getStageId()) && stage.getState().isDone()) {
            stageLinkages
                .get(stage.getStageId())
                .processScheduleResults(stage.getState(), ImmutableSet.of());
            completedStages.add(stage.getStageId());
          }
        }

        // wait for a state change and then schedule again
        if (!blockedStages.isEmpty()) {
          tryGetFutureValue(firstCompletedFuture(blockedStages), 100, MILLISECONDS);
          for (CompletableFuture<?> blockedStage : blockedStages) {
            blockedStage.cancel(true);
          }
        }
      }

      for (SqlStageExecution stage : stages.values()) {
        StageState state = stage.getState();
        if (state != SCHEDULED && state != RUNNING && !state.isDone()) {
          throw new PrestoException(
              INTERNAL_ERROR,
              format(
                  "Scheduling is complete, but stage %s is in state %s",
                  stage.getStageId(), state));
        }
      }
    } catch (Throwable t) {
      queryStateMachine.transitionToFailed(t);
      throw Throwables.propagate(t);
    } finally {
      RuntimeException closeError = new RuntimeException();
      for (StageScheduler scheduler : stageSchedulers.values()) {
        try {
          scheduler.close();
        } catch (Throwable t) {
          queryStateMachine.transitionToFailed(t);
          closeError.addSuppressed(t);
        }
      }
      if (closeError.getSuppressed().length > 0) {
        throw closeError;
      }
    }
  }