Search in sources :

Example 31 with NarCloseable

use of org.apache.nifi.nar.NarCloseable in project nifi by apache.

the class ReportingTaskingInitializer method teardown.

@Override
public void teardown(ConfigurableComponent component) {
    ReportingTask reportingTask = (ReportingTask) component;
    try (NarCloseable narCloseable = NarCloseable.withComponentNarLoader(component.getClass(), component.getIdentifier())) {
        final MockConfigurationContext context = new MockConfigurationContext();
        ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnShutdown.class, reportingTask, new MockComponentLogger(), context);
    } finally {
        ExtensionManager.removeInstanceClassLoader(component.getIdentifier());
    }
}
Also used : NarCloseable(org.apache.nifi.nar.NarCloseable) MockConfigurationContext(org.apache.nifi.mock.MockConfigurationContext) MockComponentLogger(org.apache.nifi.mock.MockComponentLogger) ReportingTask(org.apache.nifi.reporting.ReportingTask)

Example 32 with NarCloseable

use of org.apache.nifi.nar.NarCloseable in project nifi by apache.

the class StandardProcessorNode method getUndefinedRelationships.

public Set<Relationship> getUndefinedRelationships() {
    final Set<Relationship> undefined = new HashSet<>();
    final Set<Relationship> relationships;
    final Processor processor = processorRef.get().getProcessor();
    try (final NarCloseable narCloseable = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
        relationships = processor.getRelationships();
    }
    if (relationships == null) {
        return undefined;
    }
    for (final Relationship relation : relationships) {
        final Set<Connection> connectionSet = this.connections.get(relation);
        if (connectionSet == null || connectionSet.isEmpty()) {
            undefined.add(relation);
        }
    }
    return undefined;
}
Also used : NarCloseable(org.apache.nifi.nar.NarCloseable) Processor(org.apache.nifi.processor.Processor) Relationship(org.apache.nifi.processor.Relationship) Connection(org.apache.nifi.connectable.Connection) HashSet(java.util.HashSet)

Example 33 with NarCloseable

use of org.apache.nifi.nar.NarCloseable in project nifi by apache.

the class StandardProcessorNode method initiateStart.

private void initiateStart(final ScheduledExecutorService taskScheduler, final long administrativeYieldMillis, final ProcessContext processContext, final SchedulingAgentCallback schedulingAgentCallback) {
    final Processor processor = getProcessor();
    final ComponentLog procLog = new SimpleProcessLogger(StandardProcessorNode.this.getIdentifier(), processor);
    final long completionTimestamp = System.currentTimeMillis() + onScheduleTimeoutMillis;
    // Create a task to invoke the @OnScheduled annotation of the processor
    final Callable<Void> startupTask = () -> {
        LOG.debug("Invoking @OnScheduled methods of {}", processor);
        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
            try {
                activateThread();
                try {
                    ReflectionUtils.invokeMethodsWithAnnotation(OnScheduled.class, processor, processContext);
                } finally {
                    deactivateThread();
                }
                if (scheduledState.compareAndSet(ScheduledState.STARTING, ScheduledState.RUNNING)) {
                    LOG.debug("Successfully completed the @OnScheduled methods of {}; will now start triggering processor to run", processor);
                    // callback provided by StandardProcessScheduler to essentially initiate component's onTrigger() cycle
                    schedulingAgentCallback.trigger();
                } else {
                    LOG.debug("Successfully invoked @OnScheduled methods of {} but scheduled state is no longer STARTING so will stop processor now", processor);
                    // can only happen if stopProcessor was called before service was transitioned to RUNNING state
                    activateThread();
                    try {
                        ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnUnscheduled.class, processor, processContext);
                        ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnStopped.class, processor, processContext);
                    } finally {
                        deactivateThread();
                    }
                    scheduledState.set(ScheduledState.STOPPED);
                }
            } finally {
                schedulingAgentCallback.onTaskComplete();
            }
        } catch (final Exception e) {
            procLog.error("Failed to properly initialize Processor. If still scheduled to run, NiFi will attempt to " + "initialize and run the Processor again after the 'Administrative Yield Duration' has elapsed. Failure is due to " + e, e);
            // If processor's task completed Exceptionally, then we want to retry initiating the start (if Processor is still scheduled to run).
            try (final NarCloseable nc = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
                activateThread();
                try {
                    ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnUnscheduled.class, processor, processContext);
                    ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnStopped.class, processor, processContext);
                } finally {
                    deactivateThread();
                }
            }
            // make sure we only continue retry loop if STOP action wasn't initiated
            if (scheduledState.get() != ScheduledState.STOPPING) {
                // re-initiate the entire process
                final Runnable initiateStartTask = () -> initiateStart(taskScheduler, administrativeYieldMillis, processContext, schedulingAgentCallback);
                taskScheduler.schedule(initiateStartTask, administrativeYieldMillis, TimeUnit.MILLISECONDS);
            } else {
                scheduledState.set(ScheduledState.STOPPED);
            }
        }
        return null;
    };
    // Trigger the task in a background thread.
    final Future<?> taskFuture = schedulingAgentCallback.scheduleTask(startupTask);
    // Trigger a task periodically to check if @OnScheduled task completed. Once it has,
    // this task will call SchedulingAgentCallback#onTaskComplete.
    // However, if the task times out, we need to be able to cancel the monitoring. So, in order
    // to do this, we use #scheduleWithFixedDelay and then make that Future available to the task
    // itself by placing it into an AtomicReference.
    final AtomicReference<Future<?>> futureRef = new AtomicReference<>();
    final Runnable monitoringTask = new Runnable() {

        @Override
        public void run() {
            Future<?> monitoringFuture = futureRef.get();
            if (monitoringFuture == null) {
                // Future is not yet available. Just return and wait for the next invocation.
                return;
            }
            monitorAsyncTask(taskFuture, monitoringFuture, completionTimestamp);
        }
    };
    final Future<?> future = taskScheduler.scheduleWithFixedDelay(monitoringTask, 1, 10, TimeUnit.MILLISECONDS);
    futureRef.set(future);
}
Also used : NarCloseable(org.apache.nifi.nar.NarCloseable) Processor(org.apache.nifi.processor.Processor) OnStopped(org.apache.nifi.annotation.lifecycle.OnStopped) AtomicReference(java.util.concurrent.atomic.AtomicReference) ComponentLog(org.apache.nifi.logging.ComponentLog) ProcessorInstantiationException(org.apache.nifi.controller.exception.ProcessorInstantiationException) OnScheduled(org.apache.nifi.annotation.lifecycle.OnScheduled) OnUnscheduled(org.apache.nifi.annotation.lifecycle.OnUnscheduled) Future(java.util.concurrent.Future) CompletableFuture(java.util.concurrent.CompletableFuture) SimpleProcessLogger(org.apache.nifi.processor.SimpleProcessLogger)

Example 34 with NarCloseable

use of org.apache.nifi.nar.NarCloseable in project nifi by apache.

the class StandardProcessorNode method getRelationship.

/**
 * @param relationshipName
 *            name
 * @return the relationship for this nodes processor for the given name or
 *         creates a new relationship for the given name
 */
@Override
public Relationship getRelationship(final String relationshipName) {
    final Relationship specRel = new Relationship.Builder().name(relationshipName).build();
    Relationship returnRel = specRel;
    final Set<Relationship> relationships;
    final Processor processor = processorRef.get().getProcessor();
    try (final NarCloseable narCloseable = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
        relationships = processor.getRelationships();
    }
    for (final Relationship rel : relationships) {
        if (rel.equals(specRel)) {
            returnRel = rel;
            break;
        }
    }
    return returnRel;
}
Also used : NarCloseable(org.apache.nifi.nar.NarCloseable) Processor(org.apache.nifi.processor.Processor) Relationship(org.apache.nifi.processor.Relationship) HashCodeBuilder(org.apache.commons.lang3.builder.HashCodeBuilder) EqualsBuilder(org.apache.commons.lang3.builder.EqualsBuilder)

Example 35 with NarCloseable

use of org.apache.nifi.nar.NarCloseable in project nifi by apache.

the class StandardProcessorNode method stop.

/**
 * Will idempotently stop the processor using the following sequence: <i>
 * <ul>
 * <li>Transition (atomically) Processor's scheduled state from RUNNING to
 * STOPPING. If the above state transition succeeds, then invoke any method
 * on the Processor with the {@link OnUnscheduled} annotation. Once those methods
 * have been called and returned (either normally or exceptionally), start checking
 * to see if all of the Processor's active threads have finished. If not, check again
 * every 100 milliseconds until they have.
 * Once all after threads have completed, the processor's @OnStopped operation will be invoked
 * and its scheduled state is set to STOPPED which completes processor stop
 * sequence.</li>
 * </ul>
 * </i>
 *
 * <p>
 * If for some reason processor's scheduled state can not be transitioned to
 * STOPPING (e.g., the processor didn't finish @OnScheduled operation when
 * stop was called), the attempt will be made to transition processor's
 * scheduled state from STARTING to STOPPING which will allow
 * {@link #start(ScheduledExecutorService, long, ProcessContext, Runnable)}
 * method to initiate processor's shutdown upon exiting @OnScheduled
 * operation, otherwise the processor's scheduled state will remain
 * unchanged ensuring that multiple calls to this method are idempotent.
 * </p>
 */
@Override
public CompletableFuture<Void> stop(final ProcessScheduler processScheduler, final ScheduledExecutorService executor, final ProcessContext processContext, final SchedulingAgent schedulingAgent, final LifecycleState scheduleState) {
    final Processor processor = processorRef.get().getProcessor();
    LOG.info("Stopping processor: " + processor.getClass());
    desiredState = ScheduledState.STOPPED;
    final CompletableFuture<Void> future = new CompletableFuture<>();
    if (this.scheduledState.compareAndSet(ScheduledState.RUNNING, ScheduledState.STOPPING)) {
        // will ensure that the Processor represented by this node can only be stopped once
        scheduleState.incrementActiveThreadCount(null);
        // will continue to monitor active threads, invoking OnStopped once there are no
        // active threads (with the exception of the thread performing shutdown operations)
        executor.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    if (scheduleState.isScheduled()) {
                        schedulingAgent.unschedule(StandardProcessorNode.this, scheduleState);
                        activateThread();
                        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
                            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnUnscheduled.class, processor, processContext);
                        } finally {
                            deactivateThread();
                        }
                    }
                    // all threads are complete if the active thread count is 1. This is because this thread that is
                    // performing the lifecycle actions counts as 1 thread.
                    final boolean allThreadsComplete = scheduleState.getActiveThreadCount() == 1;
                    if (allThreadsComplete) {
                        activateThread();
                        try (final NarCloseable nc = NarCloseable.withComponentNarLoader(processor.getClass(), processor.getIdentifier())) {
                            ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnStopped.class, processor, processContext);
                        } finally {
                            deactivateThread();
                        }
                        scheduleState.decrementActiveThreadCount(null);
                        scheduledState.set(ScheduledState.STOPPED);
                        future.complete(null);
                        // Processor if need be.
                        if (desiredState == ScheduledState.RUNNING) {
                            processScheduler.startProcessor(StandardProcessorNode.this, true);
                        }
                    } else {
                        // Not all of the active threads have finished. Try again in 100 milliseconds.
                        executor.schedule(this, 100, TimeUnit.MILLISECONDS);
                    }
                } catch (final Exception e) {
                    LOG.warn("Failed while shutting down processor " + processor, e);
                }
            }
        });
    } else {
        // We do compareAndSet() instead of set() to ensure that Processor
        // stoppage is handled consistently including a condition where
        // Processor never got a chance to transition to RUNNING state
        // before stop() was called. If that happens the stop processor
        // routine will be initiated in start() method, otherwise the IF
        // part will handle the stop processor routine.
        this.scheduledState.compareAndSet(ScheduledState.STARTING, ScheduledState.STOPPING);
        future.complete(null);
    }
    return future;
}
Also used : NarCloseable(org.apache.nifi.nar.NarCloseable) CompletableFuture(java.util.concurrent.CompletableFuture) Processor(org.apache.nifi.processor.Processor) OnUnscheduled(org.apache.nifi.annotation.lifecycle.OnUnscheduled) OnStopped(org.apache.nifi.annotation.lifecycle.OnStopped) ProcessorInstantiationException(org.apache.nifi.controller.exception.ProcessorInstantiationException)

Aggregations

NarCloseable (org.apache.nifi.nar.NarCloseable)48 ComponentLog (org.apache.nifi.logging.ComponentLog)13 PropertyDescriptor (org.apache.nifi.components.PropertyDescriptor)12 Processor (org.apache.nifi.processor.Processor)12 HashMap (java.util.HashMap)9 ControllerServiceNode (org.apache.nifi.controller.service.ControllerServiceNode)9 SimpleProcessLogger (org.apache.nifi.processor.SimpleProcessLogger)9 URL (java.net.URL)8 LinkedHashMap (java.util.LinkedHashMap)8 ProcessorInstantiationException (org.apache.nifi.controller.exception.ProcessorInstantiationException)8 ReportingTask (org.apache.nifi.reporting.ReportingTask)8 Map (java.util.Map)7 ControllerService (org.apache.nifi.controller.ControllerService)6 IOException (java.io.IOException)5 InvocationTargetException (java.lang.reflect.InvocationTargetException)5 ArrayList (java.util.ArrayList)5 ComponentLifeCycleException (org.apache.nifi.controller.exception.ComponentLifeCycleException)5 ControllerServiceInstantiationException (org.apache.nifi.controller.exception.ControllerServiceInstantiationException)5 Relationship (org.apache.nifi.processor.Relationship)5 ComponentVariableRegistry (org.apache.nifi.registry.ComponentVariableRegistry)5