use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class FlowProgramRunner method run.
@Override
public ProgramController run(Program program, ProgramOptions options) {
// Extract and verify parameters
ApplicationSpecification appSpec = program.getApplicationSpecification();
Preconditions.checkNotNull(appSpec, "Missing application specification.");
ProgramType processorType = program.getType();
Preconditions.checkNotNull(processorType, "Missing processor type.");
Preconditions.checkArgument(processorType == ProgramType.FLOW, "Only FLOW process type is supported.");
FlowSpecification flowSpec = appSpec.getFlows().get(program.getName());
Preconditions.checkNotNull(flowSpec, "Missing FlowSpecification for %s", program.getName());
try {
// Launch flowlet program runners
RunId runId = ProgramRunners.getRunId(options);
Multimap<String, QueueName> consumerQueues = FlowUtils.configureQueue(program, flowSpec, streamAdmin, queueAdmin, txExecutorFactory);
final Table<String, Integer, ProgramController> flowlets = createFlowlets(program, options, flowSpec);
return new FlowProgramController(flowlets, program, options, flowSpec, consumerQueues);
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class FlowProgramRunner method createFlowlets.
/**
* Starts all flowlets in the flow program.
* @param program Program to run
* @param flowSpec The {@link FlowSpecification}.
* @return A {@link Table} with row as flowlet id, column as instance id, cell as the {@link ProgramController}
* for the flowlet.
*/
private Table<String, Integer, ProgramController> createFlowlets(Program program, ProgramOptions options, FlowSpecification flowSpec) {
Table<String, Integer, ProgramController> flowlets = HashBasedTable.create();
try {
for (Map.Entry<String, FlowletDefinition> entry : flowSpec.getFlowlets().entrySet()) {
ProgramOptions flowletOptions = resolveFlowletOptions(options, entry.getKey());
int instanceCount = entry.getValue().getInstances();
for (int instanceId = 0; instanceId < instanceCount; instanceId++) {
flowlets.put(entry.getKey(), instanceId, startFlowlet(program, createFlowletOptions(entry.getKey(), instanceId, instanceCount, flowletOptions)));
}
}
} catch (Throwable t) {
try {
// Need to stop all started flowlets
Futures.successfulAsList(Iterables.transform(flowlets.values(), new Function<ProgramController, ListenableFuture<?>>() {
@Override
public ListenableFuture<?> apply(ProgramController controller) {
return controller.stop();
}
})).get();
} catch (Exception e) {
LOG.error("Fail to stop all flowlets on failure.");
}
throw Throwables.propagate(t);
}
return flowlets;
}
use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class ProgramLifecycleService method stop.
/**
* Stops the specified run of the specified program.
*
* @param programId the {@link ProgramId program} to stop
* @param runId the runId of the program run to stop. If null, all runs of the program as returned by
* {@link ProgramRuntimeService} are stopped.
* @throws NotFoundException if the app, program or run was not found
* @throws BadRequestException if an attempt is made to stop a program that is either not running or
* was started by a workflow
* @throws InterruptedException if there was a problem while waiting for the stop call to complete
* @throws ExecutionException if there was a problem while waiting for the stop call to complete
*/
public void stop(ProgramId programId, @Nullable String runId) throws Exception {
List<ListenableFuture<ProgramController>> futures = issueStop(programId, runId);
// Block until all stop requests completed. This call never throw ExecutionException
Futures.successfulAsList(futures).get();
Throwable failureCause = null;
for (ListenableFuture<ProgramController> f : futures) {
try {
f.get();
} catch (ExecutionException e) {
// an IllegalStateException will be throw, which we can safely ignore
if (!(e.getCause() instanceof IllegalStateException)) {
if (failureCause == null) {
failureCause = e.getCause();
} else {
failureCause.addSuppressed(e.getCause());
}
}
}
}
if (failureCause != null) {
throw new ExecutionException(String.format("%d out of %d runs of the program %s failed to stop", failureCause.getSuppressed().length + 1, futures.size(), programId), failureCause);
}
}
use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class ProgramLifecycleServiceTest method testInvalidFlowRunRecord.
@Test
public void testInvalidFlowRunRecord() throws Exception {
// Create App with Flow and the deploy
HttpResponse response = deploy(WordCountApp.class, Constants.Gateway.API_VERSION_3_TOKEN, TEST_NAMESPACE1);
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
final Id.Program wordcountFlow1 = Id.Program.from(TEST_NAMESPACE1, "WordCountApp", ProgramType.FLOW, "WordCountFlow");
// flow is stopped initially
Assert.assertEquals("STOPPED", getProgramStatus(wordcountFlow1));
// start a flow and check the status
startProgram(wordcountFlow1);
waitState(wordcountFlow1, ProgramRunStatus.RUNNING.toString());
// Wait until we have a run record
Tasks.waitFor(1, new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return getProgramRuns(wordcountFlow1, ProgramRunStatus.RUNNING.toString()).size();
}
}, 5, TimeUnit.SECONDS);
// Get the RunRecord
List<RunRecord> runRecords = getProgramRuns(wordcountFlow1, ProgramRunStatus.RUNNING.toString());
Assert.assertEquals(1, runRecords.size());
final RunRecord rr = runRecords.get(0);
// Check the RunRecords status
Assert.assertEquals(ProgramRunStatus.RUNNING, rr.getStatus());
// Lets set the runtime info to off
RuntimeInfo runtimeInfo = runtimeService.lookup(wordcountFlow1.toEntityId(), RunIds.fromString(rr.getPid()));
ProgramController programController = runtimeInfo.getController();
programController.stop();
// Verify that the status of that run is KILLED
Tasks.waitFor(ProgramRunStatus.KILLED, new Callable<ProgramRunStatus>() {
@Override
public ProgramRunStatus call() throws Exception {
RunRecordMeta runRecord = store.getRun(wordcountFlow1.toEntityId(), rr.getPid());
return runRecord == null ? null : runRecord.getStatus();
}
}, 5, TimeUnit.SECONDS, 100, TimeUnit.MILLISECONDS);
// Use the store manipulate state to be RUNNING
long now = System.currentTimeMillis();
long nowSecs = TimeUnit.MILLISECONDS.toSeconds(now);
store.setStart(wordcountFlow1.toEntityId(), rr.getPid(), nowSecs);
// Now check again via Store to assume data store is wrong.
RunRecord runRecordMeta = store.getRun(wordcountFlow1.toEntityId(), rr.getPid());
Assert.assertNotNull(runRecordMeta);
Assert.assertEquals(ProgramRunStatus.RUNNING, runRecordMeta.getStatus());
// Verify there is NO FAILED run record for the application
runRecords = getProgramRuns(wordcountFlow1, ProgramRunStatus.FAILED.toString());
Assert.assertEquals(0, runRecords.size());
// Lets fix it
Set<String> processedInvalidRunRecordIds = Sets.newHashSet();
programLifecycleService.validateAndCorrectRunningRunRecords(ProgramType.FLOW, processedInvalidRunRecordIds);
// Verify there is one FAILED run record for the application
runRecords = getProgramRuns(wordcountFlow1, ProgramRunStatus.FAILED.toString());
Assert.assertEquals(1, runRecords.size());
Assert.assertEquals(ProgramRunStatus.FAILED, runRecords.get(0).getStatus());
}
use of co.cask.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class SparkProgramRunner method run.
@Override
public ProgramController run(Program program, ProgramOptions options) {
// Get the RunId first. It is used for the creation of the ClassLoader closing thread.
Arguments arguments = options.getArguments();
RunId runId = ProgramRunners.getRunId(options);
Deque<Closeable> closeables = new LinkedList<>();
try {
// Extract and verify parameters
ApplicationSpecification appSpec = program.getApplicationSpecification();
Preconditions.checkNotNull(appSpec, "Missing application specification.");
ProgramType processorType = program.getType();
Preconditions.checkNotNull(processorType, "Missing processor type.");
Preconditions.checkArgument(processorType == ProgramType.SPARK, "Only Spark process type is supported.");
SparkSpecification spec = appSpec.getSpark().get(program.getName());
Preconditions.checkNotNull(spec, "Missing SparkSpecification for %s", program.getName());
String host = options.getArguments().getOption(ProgramOptionConstants.HOST);
Preconditions.checkArgument(host != null, "No hostname is provided");
// Get the WorkflowProgramInfo if it is started by Workflow
WorkflowProgramInfo workflowInfo = WorkflowProgramInfo.create(arguments);
DatasetFramework programDatasetFramework = workflowInfo == null ? datasetFramework : NameMappedDatasetFramework.createFromWorkflowProgramInfo(datasetFramework, workflowInfo, appSpec);
// Setup dataset framework context, if required
if (programDatasetFramework instanceof ProgramContextAware) {
ProgramId programId = program.getId();
((ProgramContextAware) programDatasetFramework).setContext(new BasicProgramContext(programId.run(runId)));
}
PluginInstantiator pluginInstantiator = createPluginInstantiator(options, program.getClassLoader());
if (pluginInstantiator != null) {
closeables.addFirst(pluginInstantiator);
}
SparkRuntimeContext runtimeContext = new SparkRuntimeContext(new Configuration(hConf), program, options, cConf, host, txClient, programDatasetFramework, discoveryServiceClient, metricsCollectionService, streamAdmin, workflowInfo, pluginInstantiator, secureStore, secureStoreManager, authorizationEnforcer, authenticationContext, messagingService, serviceAnnouncer, pluginFinder, locationFactory);
closeables.addFirst(runtimeContext);
Spark spark;
try {
spark = new InstantiatorFactory(false).get(TypeToken.of(program.<Spark>getMainClass())).create();
} catch (Exception e) {
LOG.error("Failed to instantiate Spark class for {}", spec.getClassName(), e);
throw Throwables.propagate(e);
}
SparkSubmitter submitter = SparkRuntimeContextConfig.isLocal(hConf) ? new LocalSparkSubmitter() : new DistributedSparkSubmitter(hConf, locationFactory, host, runtimeContext, options.getArguments().getOption(Constants.AppFabric.APP_SCHEDULER_QUEUE));
Service sparkRuntimeService = new SparkRuntimeService(cConf, spark, getPluginArchive(options), runtimeContext, submitter, locationFactory);
sparkRuntimeService.addListener(createRuntimeServiceListener(closeables), Threads.SAME_THREAD_EXECUTOR);
ProgramController controller = new SparkProgramController(sparkRuntimeService, runtimeContext);
LOG.debug("Starting Spark Job. Context: {}", runtimeContext);
if (SparkRuntimeContextConfig.isLocal(hConf) || UserGroupInformation.isSecurityEnabled()) {
sparkRuntimeService.start();
} else {
ProgramRunners.startAsUser(cConf.get(Constants.CFG_HDFS_USER), sparkRuntimeService);
}
return controller;
} catch (Throwable t) {
closeAllQuietly(closeables);
throw Throwables.propagate(t);
}
}
Aggregations