Package com.cloudera.flume.core.connector

Source Code of com.cloudera.flume.core.connector.DirectDriver

/**
* 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.connector;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cloudera.flume.core.Driver;
import com.cloudera.flume.core.DriverListener;
import com.cloudera.flume.core.Event;
import com.cloudera.flume.core.EventSink;
import com.cloudera.flume.core.EventSource;
import com.cloudera.flume.master.StatusManager.NodeState;
import com.google.common.base.Preconditions;

/**
* This connector hooks a source to a sink and allow this connection to be
* stopped and started.
*
* This assumes that sources and sinks are opened before the start() method is
* called
*/
public class DirectDriver extends Driver {

  static final Logger LOG = LoggerFactory.getLogger(DirectDriver.class);

  EventSink sink;
  EventSource source;
  PumperThread thd;
  Exception error = null;
  NodeState state = NodeState.HELLO;
  final List<DriverListener> listeners = new ArrayList<DriverListener>();

  public DirectDriver(EventSource src, EventSink snk) {
    this("pumper", src, snk);
  }

  public DirectDriver(String threadName, EventSource src, EventSink snk) {

    Preconditions.checkNotNull(src, "Driver Source was invalid");
    Preconditions.checkNotNull(snk, "Driver Sink was invalid");
    thd = new PumperThread(threadName);
    this.source = src;
    this.sink = snk;
  }

  class PumperThread extends Thread {
    volatile boolean stopped = true;

    public PumperThread(String name) {
      super();
      setName(name + "-" + getId());
    }

    public void run() {
      EventSink sink = null;
      EventSource source = null;
      synchronized (DirectDriver.this) {
        sink = DirectDriver.this.sink;
        source = DirectDriver.this.source;
      }
      try {
        stopped = false;
        error = null;
        state = NodeState.ACTIVE;
        LOG.debug("Starting driver " + DirectDriver.this);
        fireStart();

        while (!stopped) {
          Event e = source.next();
          if (e == null)
            break;

          sink.append(e);
        }
      } catch (Exception e1) {
        // Catches all exceptions or throwables. This is a separate thread
        error = e1;
        stopped = true;

        LOG.error("Driving src/sink failed! " + DirectDriver.this + " because "
            + e1.getMessage(), e1);
        fireError(e1);
        state = NodeState.ERROR;
        return;
      }

      LOG.debug("Driver completed: " + DirectDriver.this);
      fireStop();
      state = NodeState.IDLE;
    }
  }

  @Override
  synchronized public void setSink(EventSink snk) {
    this.sink = snk;
  }

  synchronized public EventSink getSink() {
    return sink;
  }

  @Override
  synchronized public void setSource(EventSource src) {
    this.source = src;
  }

  synchronized public EventSource getSource() {
    return source;
  }

  @Override
  public synchronized void start() throws IOException {
    // don't allow thread to be "started twice"
    if (thd.stopped) {
      thd.start();
    }
  }

  public synchronized boolean isStopped() {
    return thd.stopped;
  }

  @Override
  public synchronized void stop() throws IOException {
    thd.stopped = true;
  }

  /**
   * Start the mean shutdown.
   */
  public void cancel() {
    thd.interrupt();
  }

  @Override
  public void join() throws InterruptedException {
    join(0);
  }

  @Override
  public boolean join(long ms) throws InterruptedException {
    final PumperThread t = thd;
    t.join(ms);
    return !t.isAlive();
  }

  public Exception getError() {
    return error;
  }

  @Override
  public NodeState getState() {
    return state;
  }

  /**
   * Callbacks cannot add or remove ConnectorListeners -- they can cause
   * deadlocks on the listeners lock if that happens.
   *
   * Here we only lock on the 'listeners' object lock. Previously this locked on
   * the directconnector which could cause deadlocks with the callback.
   */
  @Override
  public void registerListener(DriverListener listener) {
    synchronized (listeners) {
      listeners.add(listener);
    }
  }

  @Override
  public void deregisterListener(DriverListener listener) {
    synchronized (listeners) {
      listeners.remove(listener);
    }
  }

  void fireStart() {
    synchronized (listeners) {
      for (DriverListener l : listeners) {
        l.fireStarted(this);
      }
    }
  }

  void fireStop() {
    synchronized (listeners) {
      for (DriverListener l : listeners) {
        l.fireStopped(this);
      }
    }
  }

  void fireError(Exception e) {
    synchronized (listeners) {
      for (DriverListener l : listeners) {
        l.fireError(this, e);
      }
    }
  }

  @Override
  public String toString() {
    return source.getClass().getSimpleName() + " | " + sink.getName();
  }
}
TOP

Related Classes of com.cloudera.flume.core.connector.DirectDriver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.