/** * Licensed to Cloudera, Inc. under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. Cloudera, Inc. licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cloudera.flume.core; import java.io.IOException; import java.util.Map; import com.cloudera.flume.conf.SourceFactory.SourceBuilder; import com.cloudera.flume.reporter.ReportEvent; import com.cloudera.flume.reporter.Reportable; import com.google.common.base.Preconditions; /** * This provides a synchronous interface to getting events. An state/event-based * architecture will likely be more efficient than a thread based one because * there are many sources of information and only one output. */ public interface EventSource extends Reportable { /** * This is a blocking call that gets the next message from the source. * * @return event or null if source is done/empty * @throws IOException */ Event next() throws IOException; public void open() throws IOException; public void close() throws IOException; /** * Generates one or more reports in some sort of readable format using the * supplied naming prefix. */ public void getReports(String namePrefix, Map<String, ReportEvent> reports); /** * The stub source is a place holder that can get instantiated but never * should never have any calls made upon it. (opened/closed/next) . If that * ever happens it throws an exception. */ public static class StubSource implements EventSource { @Override public void close() throws IOException { throw new IOException("Attempting to close a Stub Source!"); } @Override public Event next() throws IOException { throw new IOException("Attempting to next a Stub Source!"); } @Override public void open() throws IOException { throw new IOException("Attempting to open a Stub Source!"); } @Override public String getName() { return this.getClass().getSimpleName(); } @Override public ReportEvent getReport() { return new ReportEvent(getName()); } public static SourceBuilder builder() { return new SourceBuilder() { @Override public EventSource build(String... argv) { return new StubSource(); } }; } /** * Bounded ranges on stubs sources. */ public static SourceBuilder builder(final int minArgs, final int maxArgs) { return new SourceBuilder() { @Override public EventSource build(String... argv) { Preconditions.checkArgument(argv.length >= minArgs, "Too few arguments: expected at least " + minArgs + " but only had " + argv.length); Preconditions.checkArgument(argv.length <= maxArgs, "Too many arguments : exepected at most " + maxArgs + " but had " + argv.length); return new StubSource(); } }; } @Override public void getReports(String namePrefix, Map<String, ReportEvent> reports) { reports.put(namePrefix + getName(), getReport()); } } public static class Base implements EventSource { /** type attribute is common to all sinks */ protected static final String R_TYPE = "type"; /** byte count attribute is common to all sinks */ protected static final String R_NUM_BYTES = "number of bytes"; /** event count attribute is common to all sinks */ protected static final String R_NUM_EVENTS = "number of events"; /** total number of events appended to this sink */ private long numEvents = 0; /** total number bytes appended to this sink */ private long numBytes = 0; @Override public void close() throws IOException { } @Override public Event next() throws IOException { return null; } /** * This method should be called from sources which wish to track event * statistics. */ synchronized protected void updateEventProcessingStats(Event e) { if (e == null) return; numBytes += e.getBody().length; numEvents++; } @Override public void open() throws IOException { } @Override public String getName() { return this.getClass().getSimpleName(); } @Override synchronized public ReportEvent getReport() { ReportEvent rpt = new ReportEvent(getName()); rpt.setStringMetric(R_TYPE, getName()); rpt.setLongMetric(R_NUM_BYTES, numBytes); rpt.setLongMetric(R_NUM_EVENTS, numEvents); return rpt; } @Override public void getReports(String namePrefix, Map<String, ReportEvent> reports) { reports.put(namePrefix + getName(), getReport()); } } }