Search in sources :

Example 36 with Processor

use of org.apache.nifi.processor.Processor 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 37 with Processor

use of org.apache.nifi.processor.Processor 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 38 with Processor

use of org.apache.nifi.processor.Processor 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 39 with Processor

use of org.apache.nifi.processor.Processor 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)

Example 40 with Processor

use of org.apache.nifi.processor.Processor in project nifi by apache.

the class FlowController method reload.

@Override
public void reload(final ProcessorNode existingNode, final String newType, final BundleCoordinate bundleCoordinate, final Set<URL> additionalUrls) throws ProcessorInstantiationException {
    if (existingNode == null) {
        throw new IllegalStateException("Existing ProcessorNode cannot be null");
    }
    final String id = existingNode.getProcessor().getIdentifier();
    // ghost components will have a null logger
    if (existingNode.getLogger() != null) {
        existingNode.getLogger().debug("Reloading component {} to type {} from bundle {}", new Object[] { id, newType, bundleCoordinate });
    }
    // createProcessor will create a new instance class loader for the same id so
    // save the instance class loader to use it for calling OnRemoved on the existing processor
    final ClassLoader existingInstanceClassLoader = ExtensionManager.getInstanceClassLoader(id);
    // create a new node with firstTimeAdded as true so lifecycle methods get fired
    // attempt the creation to make sure it works before firing the OnRemoved methods below
    final ProcessorNode newNode = createProcessor(newType, id, bundleCoordinate, additionalUrls, true, false);
    // call OnRemoved for the existing processor using the previous instance class loader
    try (final NarCloseable x = NarCloseable.withComponentNarLoader(existingInstanceClassLoader)) {
        final StateManager stateManager = getStateManagerProvider().getStateManager(id);
        final StandardProcessContext processContext = new StandardProcessContext(existingNode, controllerServiceProvider, encryptor, stateManager, () -> false);
        ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnRemoved.class, existingNode.getProcessor(), processContext);
    } finally {
        ExtensionManager.closeURLClassLoader(id, existingInstanceClassLoader);
    }
    // set the new processor in the existing node
    final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getProcessor());
    final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger);
    LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger);
    final LoggableComponent<Processor> newProcessor = new LoggableComponent<>(newNode.getProcessor(), newNode.getBundleCoordinate(), terminationAwareLogger);
    existingNode.setProcessor(newProcessor);
    existingNode.setExtensionMissing(newNode.isExtensionMissing());
    // need to refresh the properties in case we are changing from ghost component to real component
    existingNode.refreshProperties();
}
Also used : NarCloseable(org.apache.nifi.nar.NarCloseable) GhostProcessor(org.apache.nifi.processor.GhostProcessor) Processor(org.apache.nifi.processor.Processor) ComponentLog(org.apache.nifi.logging.ComponentLog) StateManager(org.apache.nifi.components.state.StateManager) NarThreadContextClassLoader(org.apache.nifi.nar.NarThreadContextClassLoader) StandardProcessContext(org.apache.nifi.processor.StandardProcessContext) SimpleProcessLogger(org.apache.nifi.processor.SimpleProcessLogger)

Aggregations

Processor (org.apache.nifi.processor.Processor)50 Test (org.junit.Test)19 AbstractProcessor (org.apache.nifi.processor.AbstractProcessor)13 ComponentLog (org.apache.nifi.logging.ComponentLog)12 NarCloseable (org.apache.nifi.nar.NarCloseable)12 AtomicLong (java.util.concurrent.atomic.AtomicLong)11 Relationship (org.apache.nifi.processor.Relationship)11 ProcessorNode (org.apache.nifi.controller.ProcessorNode)9 HashSet (java.util.HashSet)8 StandardComponentVariableRegistry (org.apache.nifi.registry.variable.StandardComponentVariableRegistry)8 StandardProcessorInitializationContext (org.apache.nifi.processor.StandardProcessorInitializationContext)7 StandardProcessorNode (org.apache.nifi.controller.StandardProcessorNode)6 AbstractSessionFactoryProcessor (org.apache.nifi.processor.AbstractSessionFactoryProcessor)6 ProcessorInitializationContext (org.apache.nifi.processor.ProcessorInitializationContext)6 ArrayList (java.util.ArrayList)5 HashMap (java.util.HashMap)5 Map (java.util.Map)5 StandardValidationContextFactory (org.apache.nifi.processor.StandardValidationContextFactory)5 Collection (java.util.Collection)4 PropertyDescriptor (org.apache.nifi.components.PropertyDescriptor)4