use of io.cdap.cdap.internal.app.runtime.AbstractListener 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.internal.app.runtime.AbstractListener 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.internal.app.runtime.AbstractListener in project cdap by caskdata.
the class WorkerProgramRunnerTest method stopProgram.
private void stopProgram(ProgramController controller) throws Throwable {
final AtomicReference<Throwable> errorCause = new AtomicReference<>();
final CountDownLatch complete = new CountDownLatch(1);
controller.addListener(new AbstractListener() {
@Override
public void error(Throwable cause) {
complete.countDown();
errorCause.set(cause);
}
@Override
public void completed() {
complete.countDown();
}
@Override
public void killed() {
complete.countDown();
}
}, Threads.SAME_THREAD_EXECUTOR);
controller.stop();
complete.await(30, TimeUnit.SECONDS);
runningPrograms.remove(controller);
Throwable t = errorCause.get();
if (t != null) {
throw t;
}
}
use of io.cdap.cdap.internal.app.runtime.AbstractListener in project cdap by caskdata.
the class ProgramControllerTest method testInitState.
@Test
public void testInitState() throws ExecutionException, InterruptedException {
// To test against race-condition, we start/stop service multiple times.
// If there is race, there is a chance that this test will fail in some env.
// Otherwise it should always pass
ExecutorService executor = Executors.newCachedThreadPool();
int serviceCount = 1000;
final CountDownLatch latch = new CountDownLatch(serviceCount);
ProgramId programId = new ApplicationId(NamespaceId.DEFAULT.getNamespace(), "test").service("test");
for (int i = 0; i < serviceCount; i++) {
// Creates a controller for a guava service do nothing in start/stop.
// The short time in start creates a chance to have out-of-order init() and alive() call if there is a race.
Service service = new TestService(0, 0);
ProgramController controller = new ProgramControllerServiceAdapter(service, programId.run(RunIds.generate()));
ListenableFuture<Service.State> startCompletion = service.start();
controller.addListener(new AbstractListener() {
private volatile boolean initCalled;
@Override
public void init(ProgramController.State currentState, @Nullable Throwable cause) {
initCalled = true;
if (currentState == ProgramController.State.ALIVE) {
latch.countDown();
}
}
@Override
public void alive() {
if (initCalled) {
latch.countDown();
} else {
LOG.error("init() not called before alive()");
}
}
}, executor);
startCompletion.get();
service.stopAndWait();
}
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
}
use of io.cdap.cdap.internal.app.runtime.AbstractListener in project cdap by caskdata.
the class MapReduceRunnerTestBase method waitForCompletion.
private boolean waitForCompletion(ProgramController controller) throws InterruptedException {
final AtomicBoolean success = new AtomicBoolean(false);
final CountDownLatch completion = new CountDownLatch(1);
controller.addListener(new AbstractListener() {
@Override
public void completed() {
success.set(true);
completion.countDown();
}
@Override
public void error(Throwable cause) {
completion.countDown();
}
}, Threads.SAME_THREAD_EXECUTOR);
// MR tests can run for long time.
completion.await(10, TimeUnit.MINUTES);
return success.get();
}
Aggregations