use of org.apache.nifi.processor.util.put.sender.ChannelSender in project nifi by apache.
the class PutTCP method onTrigger.
/**
* event handler method to handle the FlowFile being forwarded to the Processor by the framework. The FlowFile contents is sent out over a TCP connection using an acquired ChannelSender object. If
* the FlowFile contents was sent out successfully then the FlowFile is forwarded to the success relationship. If an error occurred then the FlowFile is forwarded to the failure relationship.
*
* @param context
* - the current process context.
*
* @param sessionFactory
* - a factory object to obtain a process session.
*/
@Override
public void onTrigger(final ProcessContext context, final ProcessSessionFactory sessionFactory) throws ProcessException {
final ProcessSession session = sessionFactory.createSession();
final FlowFile flowFile = session.get();
if (flowFile == null) {
final PruneResult result = pruneIdleSenders(context.getProperty(IDLE_EXPIRATION).asTimePeriod(TimeUnit.MILLISECONDS).longValue());
// yield if we closed an idle connection, or if there were no connections in the first place
if (result.getNumClosed() > 0 || (result.getNumClosed() == 0 && result.getNumConsidered() == 0)) {
context.yield();
}
return;
}
ChannelSender sender = acquireSender(context, session, flowFile);
if (sender == null) {
return;
}
// can cast to a SocketChannelSender later in order to obtain the OutputStream
if (!(sender instanceof SocketChannelSender)) {
getLogger().error("Processor can only be used with a SocketChannelSender, but obtained: " + sender.getClass().getCanonicalName());
context.yield();
return;
}
boolean closeSender = isConnectionPerFlowFile(context);
try {
// We might keep the connection open across invocations of the processor so don't auto-close this
final OutputStream out = ((SocketChannelSender) sender).getOutputStream();
final String delimiter = getOutgoingMessageDelimiter(context, flowFile);
final StopWatch stopWatch = new StopWatch(true);
try (final InputStream rawIn = session.read(flowFile);
final BufferedInputStream in = new BufferedInputStream(rawIn)) {
IOUtils.copy(in, out);
if (delimiter != null) {
final Charset charSet = Charset.forName(context.getProperty(CHARSET).getValue());
out.write(delimiter.getBytes(charSet), 0, delimiter.length());
}
out.flush();
} catch (final Exception e) {
closeSender = true;
throw e;
}
session.getProvenanceReporter().send(flowFile, transitUri, stopWatch.getElapsed(TimeUnit.MILLISECONDS));
session.transfer(flowFile, REL_SUCCESS);
session.commit();
} catch (Exception e) {
onFailure(context, session, flowFile);
getLogger().error("Exception while handling a process session, transferring {} to failure.", new Object[] { flowFile }, e);
} finally {
if (closeSender) {
getLogger().debug("Closing sender");
sender.close();
} else {
getLogger().debug("Relinquishing sender");
relinquishSender(sender);
}
}
}
use of org.apache.nifi.processor.util.put.sender.ChannelSender in project nifi by apache.
the class PutSplunk method onTrigger.
@Override
public void onTrigger(ProcessContext context, ProcessSessionFactory sessionFactory) throws ProcessException {
// first complete any batches from previous executions
FlowFileMessageBatch batch;
while ((batch = completeBatches.poll()) != null) {
batch.completeSession();
}
// create a session and try to get a FlowFile, if none available then close any idle senders
final ProcessSession session = sessionFactory.createSession();
final FlowFile flowFile = session.get();
if (flowFile == null) {
final PruneResult result = pruneIdleSenders(context.getProperty(IDLE_EXPIRATION).asTimePeriod(TimeUnit.MILLISECONDS).longValue());
// yield if we closed an idle connection, or if there were no connections in the first place
if (result.getNumClosed() > 0 || (result.getNumClosed() == 0 && result.getNumConsidered() == 0)) {
context.yield();
}
return;
}
// get a sender from the pool, or create a new one if the pool is empty
// if we can't create a new connection then route flow files to failure and yield
// acquireSender will handle the routing to failure and yielding
ChannelSender sender = acquireSender(context, session, flowFile);
if (sender == null) {
return;
}
try {
String delimiter = context.getProperty(MESSAGE_DELIMITER).evaluateAttributeExpressions(flowFile).getValue();
if (delimiter != null) {
delimiter = delimiter.replace("\\n", "\n").replace("\\r", "\r").replace("\\t", "\t");
}
// if no delimiter then treat the whole FlowFile as a single message
if (delimiter == null) {
processSingleMessage(context, session, flowFile, sender);
} else {
processDelimitedMessages(context, session, flowFile, sender, delimiter);
}
} finally {
relinquishSender(sender);
}
}
use of org.apache.nifi.processor.util.put.sender.ChannelSender in project nifi by apache.
the class AbstractPutEventProcessor method createSender.
/**
* Helper for sub-classes to create a sender.
*
* @param protocol the protocol for the sender
* @param host the host to send to
* @param port the port to send to
* @param timeout the timeout for connecting and communicating over the channel
* @param maxSendBufferSize the maximum size of the socket send buffer
* @param sslContext an SSLContext, or null if not using SSL
*
* @return a ChannelSender based on the given properties
*
* @throws IOException if an error occurs creating the sender
*/
protected ChannelSender createSender(final String protocol, final String host, final int port, final int timeout, final int maxSendBufferSize, final SSLContext sslContext) throws IOException {
ChannelSender sender;
if (protocol.equals(UDP_VALUE.getValue())) {
sender = new DatagramChannelSender(host, port, maxSendBufferSize, getLogger());
} else {
// if an SSLContextService is provided then we make a secure sender
if (sslContext != null) {
sender = new SSLSocketChannelSender(host, port, maxSendBufferSize, sslContext, getLogger());
} else {
sender = new SocketChannelSender(host, port, maxSendBufferSize, getLogger());
}
}
sender.setTimeout(timeout);
sender.open();
return sender;
}
use of org.apache.nifi.processor.util.put.sender.ChannelSender in project nifi by apache.
the class PutSyslog method onTrigger.
@Override
public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException {
final String protocol = context.getProperty(PROTOCOL).getValue();
final int batchSize = context.getProperty(BATCH_SIZE).evaluateAttributeExpressions().asInteger();
final List<FlowFile> flowFiles = session.get(batchSize);
if (flowFiles == null || flowFiles.isEmpty()) {
final PruneResult result = pruneIdleSenders(context.getProperty(IDLE_EXPIRATION).evaluateAttributeExpressions().asTimePeriod(TimeUnit.MILLISECONDS).longValue());
// yield if we closed an idle connection, or if there were no connections in the first place
if (result.getNumClosed() > 0 || (result.getNumClosed() == 0 && result.getNumConsidered() == 0)) {
context.yield();
}
return;
}
// get a sender from the pool, or create a new one if the pool is empty
// if we can't create a new connection then route flow files to failure and yield
ChannelSender sender = senderPool.poll();
if (sender == null) {
try {
getLogger().debug("No available connections, creating a new one...");
sender = createSender(context);
} catch (IOException e) {
for (final FlowFile flowFile : flowFiles) {
getLogger().error("No available connections, and unable to create a new one, transferring {} to failure", new Object[] { flowFile }, e);
session.transfer(flowFile, REL_FAILURE);
}
context.yield();
return;
}
}
final String port = context.getProperty(PORT).evaluateAttributeExpressions().getValue();
final String host = context.getProperty(HOSTNAME).evaluateAttributeExpressions().getValue();
final String transitUri = new StringBuilder().append(protocol).append("://").append(host).append(":").append(port).toString();
final AtomicReference<IOException> exceptionHolder = new AtomicReference<>(null);
final Charset charSet = Charset.forName(context.getProperty(CHARSET).evaluateAttributeExpressions().getValue());
try {
for (FlowFile flowFile : flowFiles) {
final StopWatch timer = new StopWatch(true);
final String priority = context.getProperty(MSG_PRIORITY).evaluateAttributeExpressions(flowFile).getValue();
final String version = context.getProperty(MSG_VERSION).evaluateAttributeExpressions(flowFile).getValue();
final String timestamp = context.getProperty(MSG_TIMESTAMP).evaluateAttributeExpressions(flowFile).getValue();
final String hostname = context.getProperty(MSG_HOSTNAME).evaluateAttributeExpressions(flowFile).getValue();
final String body = context.getProperty(MSG_BODY).evaluateAttributeExpressions(flowFile).getValue();
final StringBuilder messageBuilder = new StringBuilder();
messageBuilder.append("<").append(priority).append(">");
if (version != null) {
messageBuilder.append(version).append(" ");
}
messageBuilder.append(timestamp).append(" ").append(hostname).append(" ").append(body);
final String fullMessage = messageBuilder.toString();
getLogger().debug(fullMessage);
if (isValid(fullMessage)) {
try {
// now that we validated, add a new line if doing TCP
if (protocol.equals(TCP_VALUE.getValue())) {
messageBuilder.append('\n');
}
sender.send(messageBuilder.toString(), charSet);
timer.stop();
final long duration = timer.getDuration(TimeUnit.MILLISECONDS);
session.getProvenanceReporter().send(flowFile, transitUri, duration, true);
getLogger().info("Transferring {} to success", new Object[] { flowFile });
session.transfer(flowFile, REL_SUCCESS);
} catch (IOException e) {
getLogger().error("Transferring {} to failure", new Object[] { flowFile }, e);
session.transfer(flowFile, REL_FAILURE);
exceptionHolder.set(e);
}
} else {
getLogger().info("Transferring {} to invalid", new Object[] { flowFile });
session.transfer(flowFile, REL_INVALID);
}
}
} finally {
// if the connection is still open and no IO errors happened then try to return, if pool is full then close
if (sender.isConnected() && exceptionHolder.get() == null) {
boolean returned = senderPool.offer(sender);
if (!returned) {
sender.close();
}
} else {
// probably already closed here, but quietly close anyway to be safe
sender.close();
}
}
}
use of org.apache.nifi.processor.util.put.sender.ChannelSender in project nifi by apache.
the class PutSyslog method onStopped.
@OnStopped
public void onStopped() {
if (senderPool != null) {
ChannelSender sender = senderPool.poll();
while (sender != null) {
sender.close();
sender = senderPool.poll();
}
}
}
Aggregations