Package org.commoncrawl.async

Source Code of org.commoncrawl.async.EventLoop

/**
* Copyright 2008 - CommonCrawl Foundation
*
* CommonCrawl 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 org.commoncrawl.async;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.util.StringUtils;
import org.commoncrawl.async.Callbacks.Callback;
import org.commoncrawl.async.Callbacks.CallbackWithResult;
import org.commoncrawl.io.internal.NIODNSLocalResolver;
import org.commoncrawl.io.internal.NIOSocketSelector;
import org.junit.Test;

public class EventLoop  implements Runnable  {

  /** logging **/
  private static final Log          LOG                = LogFactory
                                                           .getLog(EventLoop.class);

  ExecutorService                   _resolverThreadPool = null;
  boolean                           _ownsResolverThreadPool = false;
  NIODNSLocalResolver               _resolver;
  NIOSocketSelector                 _selector;
  Thread                            _eventThread;
  TimerRegistry                     _timerRegistry     = new TimerRegistry(this);
  boolean                           _shutdown          = false;
  long                              _loopCount         = 0;

  NIOSocketSelector.TimeUsageDetail _selectorTimeUsage = new NIOSocketSelector.TimeUsageDetail();
 

  public EventLoop()throws IOException {
    init(null);
    // stop the async client manager thread (we are managing sockets ourselves)
    //super.stop();
  }

  public EventLoop(ExecutorService resolverThreadPool) throws IOException {
    init(resolverThreadPool);
    // stop the async client manager thread (we are managing sockets ourselves)
    //super.stop();
  }

  private void init(ExecutorService resolverThreadPool) {
    try {
      _selector = new NIOSocketSelector(this);
      _resolverThreadPool = resolverThreadPool;

    } catch (IOException e) {
      LOG.fatal("Unable to initialize NIO Selector");
      throw new RuntimeException("Unable to initialize NIO Selector");
    }

  }

  public NIOSocketSelector getSelector() {
    return _selector;
  }

  public NIODNSLocalResolver getResolver() {
    if (_resolver == null) {
      if (_resolverThreadPool == null) {
        _resolverThreadPool = Executors.newFixedThreadPool(1);
        _ownsResolverThreadPool = true;
      }
      _resolver = new NIODNSLocalResolver(this, _resolverThreadPool, true);
    }
    return _resolver;
  }

  public void start() {
    if (_eventThread != null) {
      LOG.fatal("Invalid Call State");
      throw new RuntimeException("Invalid Call State");
    }

    _shutdown = false;
    _eventThread = new Thread(this);
    _eventThread.start();
  }

  //@Override
  public void stop() {
    if (_eventThread == null) {
      throw new RuntimeException("Invalid Call State");
    }
    // set shutdown flag ...
    _shutdown = true;

    // and wakeup the socket selector ...
    try {
      _selector.wakeup();
    } catch (IOException e) {
      LOG.fatal("IOException encountered in Selector.wakeup!");
      throw new RuntimeException(e);
    }

    // if NOT called from event thread itself, wait for event thread to die ...
    if (Thread.currentThread() != _eventThread) {
      try {
        LOG.info("Waiting for Event Thread to DIE TID:"
            + Thread.currentThread().getId());
        _eventThread.join();
        _eventThread = null;
        LOG.info("Event Thread DEAD. Exiting EventLoop TID:"
            + Thread.currentThread().getId());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    if (_ownsResolverThreadPool) {
      _resolverThreadPool.shutdown();
      _resolverThreadPool = null;
    }
    _resolver = null;
  }

  //@Override
  public boolean isRunning() {
    return (_eventThread != null && _eventThread.isAlive())
  }

  /*
  @SuppressWarnings("unchecked")
  @Override
  public void call(TAsyncMethodCall method) throws org.apache.thrift.TException {
    if (!isRunning()) {
      throw new TException("SelectThread is not running");
    }
    _selector.call(method);
  }
  */
 
  public void wakeup() {

    if (_selector != null) {
      try {
        _selector.wakeup();
      } catch (IOException e) {
        LOG.fatal("IOException encountered in Selector.wakeup!");
        throw new RuntimeException(e);
      }
    }
  }

  public Thread getEventThread() {
    return _eventThread;
  }

  public boolean waitForIO(long waitTime) throws IOException {

    long timeStart = System.currentTimeMillis();
    long timeEnd = timeStart + waitTime;

    while (!_shutdown) {

      long nextFireTime = _timerRegistry.fireTimers();

      waitTime = timeEnd - System.currentTimeMillis();

      if (waitTime > 0) {
        if (nextFireTime != 0) {
          waitTime = Math.max(1, Math.min(nextFireTime
              - System.currentTimeMillis(), waitTime));
        }

        if (_selector.poll(waitTime, _selectorTimeUsage) != 0) {
          return false;
        }
      } else {
        break;
      }
    }
    return true;
  }

  public void run() {

    try {
      while (!_shutdown) {

        long waitTime = Long.MAX_VALUE;
        long nextFireTime = _timerRegistry.fireTimers();

        if (nextFireTime != 0) {
          waitTime = Math.max(1, nextFireTime - System.currentTimeMillis());
        }

        try {
          // long timeStart = System.currentTimeMillis();
          if (_resolver != null) {
            _resolver.poll();
          }
          // long timeEnd = System.currentTimeMillis();

          // timeStart = System.currentTimeMillis();
          _selector.poll(waitTime, _selectorTimeUsage);
          // timeEnd = System.currentTimeMillis();

          /**
           * if (++_loopCount % 100 == 0) JVMStats.dumpMemoryStats();
           **/
        } catch (IOException e) {
          LOG.error(StringUtils.stringifyException(e));
          e.printStackTrace();
        }
      }
    } catch (Exception e) {
      LOG.fatal("Unhandled Exception in Event Loop:"
          + StringUtils.stringifyException(e));
      System.out.println("Unhandled Exception in Event Loop:"
          + StringUtils.stringifyException(e));
    }
    LOG.info("Event Loop Existing Run Loop");
  }

  public void setTimer(Timer t) {
    _timerRegistry.setTimer(t);
  }

  public void cancelTimer(Timer t) {
    _timerRegistry.cancelTimer(t);
  }

  public void queueAsyncRunnable(final Runnable runnable) {
    setTimer(new Timer(0, false, new Timer.Callback() {

      @Override
      public void timerFired(Timer timer) {
        runnable.run();
      }

    }));
  }
 
 
  public void queueAsyncCallback(final Callback callback) {
    setTimer(new Timer(0, false, new Timer.Callback() {

      @Override
      public void timerFired(Timer timer) {
        callback.execute();
      }

    }));
  }

  public <ResultType> void queueAsyncCallbackWithResult(
      final CallbackWithResult<ResultType> callback, final ResultType result) {
    setTimer(new Timer(0, false, new Timer.Callback() {

      @Override
      public void timerFired(Timer timer) {
        callback.execute(result);
      }

    }));
  }

  @Test
  public void testEventLoop() throws Exception {

    final EventLoop eventLoop = new EventLoop();

    eventLoop.start();
    eventLoop.setTimer(new Timer(1000, false, new Timer.Callback() {

      public void timerFired(Timer timer) {
        System.out.println("Timer 1 Fired");
      }

    }));

    eventLoop.setTimer(new Timer(500, false, new Timer.Callback() {

      public void timerFired(Timer timer) {
        System.out.println("Timer 2 Fired");
      }

    }));

    eventLoop.setTimer(new Timer(3000, false, new Timer.Callback() {

      public void timerFired(Timer timer) {
        System.out.println("Timer 3 Fired");
        eventLoop.stop();
      }

    }));

    System.out.println("Wait for Timer to Fire");
    eventLoop.getEventThread().join();
    System.out.println("Event loop stopped. Shutting down.");
  }
 
}
TOP

Related Classes of org.commoncrawl.async.EventLoop

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.