Package co.cask.cdap.internal.app.runtime.schedule

Source Code of co.cask.cdap.internal.app.runtime.schedule.ScheduleTaskRunner

/*
* Copyright © 2014 Cask Data, Inc.
*
* 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 co.cask.cdap.internal.app.runtime.schedule;

import co.cask.cdap.app.program.Program;
import co.cask.cdap.app.runtime.Arguments;
import co.cask.cdap.app.runtime.ProgramController;
import co.cask.cdap.app.runtime.ProgramOptions;
import co.cask.cdap.app.runtime.ProgramRuntimeService;
import co.cask.cdap.app.store.Store;
import co.cask.cdap.internal.UserErrors;
import co.cask.cdap.internal.UserMessages;
import co.cask.cdap.internal.app.runtime.AbstractListener;
import co.cask.cdap.internal.app.runtime.BasicArguments;
import co.cask.cdap.internal.app.runtime.SimpleProgramOptions;
import co.cask.cdap.proto.Id;
import co.cask.cdap.proto.ProgramType;
import com.google.common.base.Preconditions;
import org.apache.twill.common.Threads;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
* Task runner that runs a schedule.
*/
public final class ScheduleTaskRunner {

  private static final Logger LOG = LoggerFactory.getLogger(ScheduleTaskRunner.class);

  private final ProgramRuntimeService runtimeService;
  private final Store store;

  public ScheduleTaskRunner(Store store, ProgramRuntimeService runtimeService) {
    this.runtimeService = runtimeService;
    this.store = store;
  }

  /**
   * Executes the giving program and block until its completion.
   *
   * @param programId Program Id
   * @param programType Program type.
   * @param arguments Arguments that would be supplied as system runtime arguments for the program.
   * @throws JobExecutionException If fails to execute the program.
   */
  public void run(Id.Program programId, ProgramType programType, Arguments arguments) throws JobExecutionException {
    ProgramRuntimeService.RuntimeInfo existingRuntimeInfo = findRuntimeInfo(programId, programType);
    if (existingRuntimeInfo != null) {
      throw new JobExecutionException(UserMessages.getMessage(UserErrors.ALREADY_RUNNING), false);
    }
    Map<String, String> userArgs;
    Program program;
    try {
      program =  store.loadProgram(programId, ProgramType.WORKFLOW);
      Preconditions.checkNotNull(program, "Program not found");

      userArgs = store.getRunArguments(programId);

    } catch (Throwable t) {
      throw new JobExecutionException(UserMessages.getMessage(UserErrors.PROGRAM_NOT_FOUND), t, false);
    }

    executeAndBlock(program, new SimpleProgramOptions(programId.getId(), arguments, new BasicArguments(userArgs)));
  }

  /**
   * Returns runtime information for the given program if it is running,
   * or {@code null} if no instance of it is running.
   */
  private ProgramRuntimeService.RuntimeInfo findRuntimeInfo(Id.Program programId, ProgramType programType) {
    Collection<ProgramRuntimeService.RuntimeInfo> runtimeInfos = runtimeService.list(programType).values();

    for (ProgramRuntimeService.RuntimeInfo info : runtimeInfos) {
      if (programId.equals(info.getProgramId())) {
        return info;
      }
    }
    return null;
  }

  /**
   * Executes a program and block until it is completed.
   */
  private void executeAndBlock(final Program program, ProgramOptions options) throws JobExecutionException {
    ProgramController controller = runtimeService.run(program, options).getController();
    store.setStart(program.getId(), controller.getRunId().getId(),
                   TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS));

    final Id.Program programId = program.getId();
    final String runId = controller.getRunId().getId();
    final CountDownLatch latch = new CountDownLatch(1);
    controller.addListener(new AbstractListener() {
      @Override
      public void stopped() {
        store.setStop(programId, runId,
                      TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS),
                      ProgramController.State.STOPPED.toString());
        LOG.debug("Program {} {} {} completed successfully.",
                  programId.getAccountId(), programId.getApplicationId(), programId.getId());
        latch.countDown();
      }

      @Override
      public void error(Throwable cause) {
        store.setStop(programId, runId,
                      TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS),
                      ProgramController.State.STOPPED.toString());
        LOG.debug("Program {} {} {} execution failed.",
                  programId.getAccountId(), programId.getApplicationId(), programId.getId(),
                  cause);

        latch.countDown();
      }
    }, Threads.SAME_THREAD_EXECUTOR);

    try {
      latch.await();
    } catch (InterruptedException e) {
      throw new JobExecutionException(e, false);
    }
  }
}
TOP

Related Classes of co.cask.cdap.internal.app.runtime.schedule.ScheduleTaskRunner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.