You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flume.apache.org by es...@apache.org on 2011/10/05 22:17:33 UTC
svn commit: r1179413 - in /incubator/flume/branches/flume-728:
flume-ng-core/src/main/java/org/apache/flume/source/ExecSource.java
flume-ng-node/src/main/java/org/apache/flume/node/Application.java
Author: esammer
Date: Wed Oct 5 20:17:32 2011
New Revision: 1179413
URL: http://svn.apache.org/viewvc?rev=1179413&view=rev
Log:
- Added a very basic event driven exec source for unix tools that stream data (e.g. tail -F).
Added:
incubator/flume/branches/flume-728/flume-ng-core/src/main/java/org/apache/flume/source/ExecSource.java
Modified:
incubator/flume/branches/flume-728/flume-ng-node/src/main/java/org/apache/flume/node/Application.java
Added: incubator/flume/branches/flume-728/flume-ng-core/src/main/java/org/apache/flume/source/ExecSource.java
URL: http://svn.apache.org/viewvc/incubator/flume/branches/flume-728/flume-ng-core/src/main/java/org/apache/flume/source/ExecSource.java?rev=1179413&view=auto
==============================================================================
--- incubator/flume/branches/flume-728/flume-ng-core/src/main/java/org/apache/flume/source/ExecSource.java (added)
+++ incubator/flume/branches/flume-728/flume-ng-core/src/main/java/org/apache/flume/source/ExecSource.java Wed Oct 5 20:17:32 2011
@@ -0,0 +1,135 @@
+package org.apache.flume.source;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.flume.Channel;
+import org.apache.flume.Context;
+import org.apache.flume.CounterGroup;
+import org.apache.flume.Event;
+import org.apache.flume.EventDrivenSource;
+import org.apache.flume.Transaction;
+import org.apache.flume.conf.Configurable;
+import org.apache.flume.event.EventBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class ExecSource extends AbstractSource implements EventDrivenSource,
+ Configurable {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(ExecSource.class);
+
+ private String command;
+
+ private CounterGroup counterGroup;
+ private ExecutorService executor;
+ private Future<?> runnerFuture;
+
+ @Override
+ public void start() {
+ logger.info("Exec source starting with command:{}", command);
+
+ executor = Executors.newSingleThreadExecutor();
+ counterGroup = new CounterGroup();
+
+ ExecRunnable runner = new ExecRunnable();
+
+ runner.command = command;
+ runner.channel = getChannel();
+ runner.counterGroup = counterGroup;
+
+ // FIXME: Use a callback-like executor / future to signal us upon failure.
+ runnerFuture = executor.submit(runner);
+
+ /*
+ * NB: This comes at the end rather than the beginning of the method because
+ * it sets our state to running. We want to make sure the executor is alive
+ * and well first.
+ */
+ super.start();
+
+ logger.debug("Exec source started");
+ }
+
+ @Override
+ public void stop() {
+ logger.info("Stopping exec source with command:{}", command);
+
+ if (runnerFuture != null) {
+ logger.debug("Stopping exec runner");
+ runnerFuture.cancel(true);
+ logger.debug("Exec runner stopped");
+ }
+
+ executor.shutdown();
+
+ while (!executor.isTerminated()) {
+ logger.debug("Waiting for exec executor service to stop");
+ try {
+ executor.awaitTermination(500, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ logger
+ .debug("Interrupted while waiting for exec executor service to stop. Just exiting.");
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ super.stop();
+
+ logger.debug("Exec source with command:{} stopped. Metrics:{}", command,
+ counterGroup);
+ }
+
+ @Override
+ public void configure(Context context) {
+ command = context.get("command", String.class);
+
+ Preconditions.checkState(command != null,
+ "The parameter command must be specified");
+ }
+
+ private static class ExecRunnable implements Runnable {
+
+ private String command;
+ private Channel channel;
+ private CounterGroup counterGroup;
+
+ @Override
+ public void run() {
+ try {
+ String[] commandArgs = command.split("\\s+");
+ Process process = new ProcessBuilder(commandArgs).start();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ process.getInputStream()));
+
+ String line = null;
+
+ while ((line = reader.readLine()) != null) {
+ counterGroup.incrementAndGet("exec.lines.read");
+
+ Transaction transaction = channel.getTransaction();
+
+ transaction.begin();
+ Event event = EventBuilder.withBody(line.getBytes());
+ channel.put(event);
+ transaction.commit();
+ }
+
+ reader.close();
+ } catch (IOException e) {
+ logger.error("Failed while running command:{} - Exception follows.",
+ command, e);
+ }
+ }
+
+ }
+
+}
Modified: incubator/flume/branches/flume-728/flume-ng-node/src/main/java/org/apache/flume/node/Application.java
URL: http://svn.apache.org/viewvc/incubator/flume/branches/flume-728/flume-ng-node/src/main/java/org/apache/flume/node/Application.java?rev=1179413&r1=1179412&r2=1179413&view=diff
==============================================================================
--- incubator/flume/branches/flume-728/flume-ng-node/src/main/java/org/apache/flume/node/Application.java (original)
+++ incubator/flume/branches/flume-728/flume-ng-node/src/main/java/org/apache/flume/node/Application.java Wed Oct 5 20:17:32 2011
@@ -24,6 +24,7 @@ import org.apache.flume.sink.NullSink;
import org.apache.flume.sink.RollingFileSink;
import org.apache.flume.sink.hdfs.HDFSEventSink;
import org.apache.flume.source.DefaultSourceFactory;
+import org.apache.flume.source.ExecSource;
import org.apache.flume.source.NetcatSource;
import org.apache.flume.source.SequenceGeneratorSource;
import org.slf4j.Logger;
@@ -71,6 +72,7 @@ public class Application {
sourceFactory.register("seq", SequenceGeneratorSource.class);
sourceFactory.register("netcat", NetcatSource.class);
+ sourceFactory.register("exec", ExecSource.class);
sinkFactory.register("null", NullSink.class);
sinkFactory.register("logger", LoggerSink.class);