@Override public final void registerInputOutput() throws Exception { LOG.debug("registerInputOutput for {}", getName()); boolean initializationCompleted = false; try { AccumulatorRegistry accumulatorRegistry = getEnvironment().getAccumulatorRegistry(); userClassLoader = getUserCodeClassLoader(); configuration = new StreamConfig(getTaskConfiguration()); accumulatorMap = accumulatorRegistry.getUserMap(); stateBackend = createStateBackend(); stateBackend.initializeForJob(getEnvironment().getJobID()); headOperator = configuration.getStreamOperator(userClassLoader); operatorChain = new OperatorChain<>(this, headOperator, accumulatorRegistry.getReadWriteReporter()); if (headOperator != null) { headOperator.setup(this, configuration, operatorChain.getChainEntryPoint()); } timerService = Executors.newSingleThreadScheduledExecutor( new DispatcherThreadFactory(TRIGGER_THREAD_GROUP, "Time Trigger for " + getName())); // task specific initialization init(); initializationCompleted = true; } finally { if (!initializationCompleted) { if (timerService != null) { timerService.shutdownNow(); } if (operatorChain != null) { operatorChain.releaseOutputs(); } } } }
@Override public final void invoke() throws Exception { LOG.debug("Invoking {}", getName()); boolean disposed = false; try { // first order of business is to ive operators back their state restoreStateLazy(); // we need to make sure that any triggers scheduled in open() cannot be // executed before all operators are opened synchronized (lock) { openAllOperators(); } // let the task do its work isRunning = true; run(); isRunning = false; if (LOG.isDebugEnabled()) { LOG.debug("Finished task {}", getName()); } // make sure no further checkpoint and notification actions happen. // we make sure that no other thread is currently in the locked scope before // we close the operators by trying to acquire the checkpoint scope lock // we also need to make sure that no triggers fire concurrently with the close logic synchronized (lock) { // this is part of the main logic, so if this fails, the task is considered failed closeAllOperators(); } // make sure all buffered data is flushed operatorChain.flushOutputs(); // make an attempt to dispose the operators such that failures in the dispose call // still let the computation fail tryDisposeAllOperators(); disposed = true; } finally { isRunning = false; timerService.shutdownNow(); // release the output resources. this method should never fail. if (operatorChain != null) { operatorChain.releaseOutputs(); } // we must! perform this cleanup try { cleanup(); } catch (Throwable t) { // catch and log the exception to not replace the original exception LOG.error("Error during cleanup of stream task."); } // if the operators were not disposed before, do a hard dispose if (!disposed) { disposeAllOperators(); } try { if (stateBackend != null) { stateBackend.close(); } } catch (Throwable t) { LOG.error("Error while closing the state backend", t); } } }