use of io.cdap.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class DistributedProgramRuntimeService method createRuntimeInfo.
@Override
protected RuntimeInfo createRuntimeInfo(final ProgramController controller, final ProgramId programId, final Runnable cleanUpTask) {
SimpleRuntimeInfo runtimeInfo = new SimpleRuntimeInfo(controller, programId, cleanUpTask);
// Add a listener that publishes KILLED status notification when the YARN application is killed in case that
// the KILLED status notification is not published from the YARN application container, so we don't need to wait
// for the run record corrector to mark the status as KILLED.
// Also, the local staging files can be deleted when the twill program is alive.
controller.addListener(new AbstractListener() {
ProgramController actualController = controller;
@Override
public void init(ProgramController.State currentState, @Nullable Throwable cause) {
while (actualController instanceof Delegator) {
// noinspection unchecked
actualController = ((Delegator<ProgramController>) actualController).getDelegate();
}
if (actualController instanceof AbstractTwillProgramController) {
runtimeInfo.setTwillRunId(((AbstractTwillProgramController) actualController).getTwillRunId());
}
if (currentState == ProgramController.State.ALIVE) {
alive();
} else if (currentState == ProgramController.State.KILLED) {
killed();
}
}
@Override
public void alive() {
cleanUpTask.run();
}
@Override
public void killed() {
programStateWriter.killed(programId.run(controller.getRunId()));
}
}, Threads.SAME_THREAD_EXECUTOR);
return runtimeInfo;
}
use of io.cdap.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class AbstractInMemoryProgramRunner method startAll.
/**
* Starts all instances of a Program component.
* @param program The program to run
* @param options options for the program
* @param numInstances number of component instances to start
*/
protected final ProgramController startAll(Program program, ProgramOptions options, int numInstances) {
RunId runId = ProgramRunners.getRunId(options);
Table<String, Integer, ProgramController> components = HashBasedTable.create();
try {
for (int instanceId = 0; instanceId < numInstances; instanceId++) {
ProgramOptions componentOptions = createComponentOptions(instanceId, numInstances, runId, options);
ProgramController controller = createProgramRunner().run(program, componentOptions);
components.put(program.getName(), instanceId, controller);
}
return new InMemoryProgramController(components, program, options);
} catch (Throwable t) {
LOG.error("Failed to start all program instances", t);
try {
// Need to stop all started components
Futures.successfulAsList(Iterables.transform(components.values(), new Function<ProgramController, ListenableFuture<?>>() {
@Override
public ListenableFuture<?> apply(ProgramController controller) {
return controller.stop();
}
})).get();
throw Throwables.propagate(t);
} catch (Exception e) {
LOG.error("Failed to stop all program instances upon startup failure.", e);
throw Throwables.propagate(e);
}
}
}
use of io.cdap.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class DefaultProgramWorkflowRunner method blockForCompletion.
/**
* Adds a listener to the {@link ProgramController} and blocks for completion.
*
* @param closeable a {@link Closeable} to call when the program execution completed
* @param controller the {@link ProgramController} for the program
* @throws Exception if the execution failed
*/
private void blockForCompletion(final Closeable closeable, final ProgramController controller) throws Exception {
// Execute the program.
final SettableFuture<Void> completion = SettableFuture.create();
controller.addListener(new AbstractListener() {
@Override
public void init(ProgramController.State currentState, @Nullable Throwable cause) {
switch(currentState) {
case COMPLETED:
completed();
break;
case KILLED:
killed();
break;
case ERROR:
error(cause);
break;
}
}
@Override
public void completed() {
Closeables.closeQuietly(closeable);
Set<Operation> fieldLineageOperations = new HashSet<>();
if (controller instanceof WorkflowDataProvider) {
fieldLineageOperations.addAll(((WorkflowDataProvider) controller).getFieldLineageOperations());
}
nodeStates.put(nodeId, new WorkflowNodeState(nodeId, NodeStatus.COMPLETED, fieldLineageOperations, controller.getRunId().getId(), null));
completion.set(null);
}
@Override
public void killed() {
Closeables.closeQuietly(closeable);
nodeStates.put(nodeId, new WorkflowNodeState(nodeId, NodeStatus.KILLED, controller.getRunId().getId(), null));
completion.set(null);
}
@Override
public void error(Throwable cause) {
Closeables.closeQuietly(closeable);
nodeStates.put(nodeId, new WorkflowNodeState(nodeId, NodeStatus.FAILED, controller.getRunId().getId(), cause));
completion.setException(cause);
}
}, Threads.SAME_THREAD_EXECUTOR);
// Block for completion.
try {
completion.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof Exception) {
throw (Exception) cause;
}
throw Throwables.propagate(cause);
} catch (InterruptedException e) {
try {
Futures.getUnchecked(controller.stop());
} catch (Throwable t) {
// no-op
}
// reset the interrupt
Thread.currentThread().interrupt();
}
}
use of io.cdap.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class ServiceProgramRunner method run.
@Override
public ProgramController run(Program program, ProgramOptions options) {
int instanceId = Integer.parseInt(options.getArguments().getOption(ProgramOptionConstants.INSTANCE_ID, "-1"));
Preconditions.checkArgument(instanceId >= 0, "Missing instance Id");
int instanceCount = Integer.parseInt(options.getArguments().getOption(ProgramOptionConstants.INSTANCES, "0"));
Preconditions.checkArgument(instanceCount > 0, "Invalid or missing instance count");
RunId runId = ProgramRunners.getRunId(options);
ApplicationSpecification appSpec = program.getApplicationSpecification();
Preconditions.checkNotNull(appSpec, "Missing application specification.");
ProgramType programType = program.getType();
Preconditions.checkNotNull(programType, "Missing processor type.");
Preconditions.checkArgument(programType == ProgramType.SERVICE, "Only Service process type is supported.");
ServiceSpecification spec = appSpec.getServices().get(program.getName());
String host = options.getArguments().getOption(ProgramOptionConstants.HOST);
Preconditions.checkArgument(host != null, "No hostname is provided");
// Setup dataset framework context, if required
if (datasetFramework instanceof ProgramContextAware) {
ProgramId programId = program.getId();
((ProgramContextAware) datasetFramework).setContext(new BasicProgramContext(programId.run(runId)));
}
final PluginInstantiator pluginInstantiator = createPluginInstantiator(options, program.getClassLoader());
try {
RetryStrategy retryStrategy = SystemArguments.getRetryStrategy(options.getUserArguments().asMap(), program.getType(), cConf);
ArtifactManager artifactManager = artifactManagerFactory.create(program.getId().getNamespaceId(), retryStrategy);
ServiceHttpServer component = new ServiceHttpServer(host, program, options, cConf, spec, instanceId, instanceCount, serviceAnnouncer, metricsCollectionService, datasetFramework, txClient, discoveryServiceClient, pluginInstantiator, secureStore, secureStoreManager, messagingService, artifactManager, metadataReader, metadataPublisher, namespaceQueryAdmin, pluginFinder, fieldLineageWriter, transactionRunner, preferencesFetcher, remoteClientFactory, contextAccessEnforcer);
// Add a service listener to make sure the plugin instantiator is closed when the http server is finished.
component.addListener(createRuntimeServiceListener(Collections.singleton(pluginInstantiator)), Threads.SAME_THREAD_EXECUTOR);
ProgramController controller = new ServiceProgramControllerAdapter(component, program.getId().run(runId));
component.start();
return controller;
} catch (Throwable t) {
Closeables.closeQuietly(pluginInstantiator);
throw t;
}
}
use of io.cdap.cdap.app.runtime.ProgramController in project cdap by caskdata.
the class WorkerProgramRunnerTest method testWorkerWithMisbehavedDataset.
@Test
public void testWorkerWithMisbehavedDataset() throws Throwable {
final ApplicationWithPrograms app = AppFabricTestHelper.deployApplicationWithManager(AppWithMisbehavedDataset.class, TEMP_FOLDER_SUPPLIER);
final ProgramController controller = startProgram(app, AppWithMisbehavedDataset.TableWriter.class);
Tasks.waitFor(ProgramController.State.COMPLETED, new Callable<ProgramController.State>() {
@Override
public ProgramController.State call() throws Exception {
return controller.getState();
}
}, 30, TimeUnit.SECONDS);
// validate worker was able to execute its second transaction
final TransactionExecutor executor = txExecutorFactory.createExecutor(datasetCache);
executor.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Table table = datasetCache.getDataset(AppWithMisbehavedDataset.TABLE);
Row result = table.get(new Get(AppWithMisbehavedDataset.ROW, AppWithMisbehavedDataset.COLUMN));
Assert.assertEquals(AppWithMisbehavedDataset.VALUE, result.getString(AppWithMisbehavedDataset.COLUMN));
}
});
}
Aggregations