Package com.bah.geterdun

Source Code of com.bah.geterdun.WriteAheadLog$Factory

package com.bah.geterdun;

import java.io.Closeable;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import net.openhft.koloboke.collect.map.hash.HashIntObjMaps;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FsConstants;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RawLocalFileSystem;
import org.apache.hadoop.io.Writable;

import com.bah.geterdun.HeaderManagement.HeaderBasedInitialization;
import com.bah.geterdun.LogResolver.CorruptLogException;

class WriteAheadLog<EVENT> implements Closeable {

  public static class NeedsRotationException extends Exception {

    private static final long serialVersionUID = 8899834790240724127L;

  }

  public static class Factory<EVENT> {

    private final Class<EVENT> eventClass;
    private final HeaderManagement headerManagement;
    private final LogResolver<EVENT> logResolver;
    private final CorruptionHandler corruptionHandler;

    Factory(Class<EVENT> eventClass, HeaderManagement headerManagement,
        LogResolver<EVENT> logResolver, CorruptionHandler corruptionHandler) {
      this.eventClass = eventClass;
      this.headerManagement = headerManagement;
      this.logResolver = logResolver;
      this.corruptionHandler = corruptionHandler;
    }

    Factory(Class<EVENT> eventClass, CorruptionHandler corruptionHandler) {
      this(eventClass, new HeaderManagement(), new LogResolver<EVENT>(),
          corruptionHandler);
    }

    public WriteAheadLog<EVENT> getLog(String location) throws IOException {
      return new WriteAheadLog<EVENT>(location, eventClass, headerManagement,
          logResolver, corruptionHandler);
    }
  }

  static final int TYPE_BEGIN = 0;
  static final int TYPE_COMMIT = 1;

  private String location;
  private FSDataOutputStream output;
  private int counter;
  private Map<Integer, EVENT> uncommittedEvents = HashIntObjMaps
      .newMutableMap();
  private Lock writeLock = new ReentrantLock();

  WriteAheadLog(String location, Class<EVENT> eventClass,
      HeaderManagement headerManagement, LogResolver<EVENT> logResolver,
      CorruptionHandler corruptionHandler) throws IOException {
    this.location = location;
    Path path = new Path(location);
    FileSystem fs;
    if (location.startsWith("file:/")) {
      fs = new RawLocalFileSystem() {
        {
          setConf(new Configuration());
          initialize(FsConstants.LOCAL_FS_URI, getConf());
        }
      };

      fs.setConf(new Configuration());
    } else {
      fs = path.getFileSystem(new Configuration());
    }
    HeaderBasedInitialization inOut;
    if (!fs.exists(path)) {
      inOut = headerManagement.createAndWriteHeader(fs, path, eventClass);
    } else {
      inOut = headerManagement.verifyHeaderAndOpen(fs, path, eventClass);
    }
    try {
      counter = logResolver.resolveUncommittedEvents(inOut.getIn(), uncommittedEvents,
          eventClass, fs.getFileStatus(path).getLen(), location);
      inOut.getIn().close();
      output = inOut.getOut();
    } catch (CorruptLogException e) {
      corruptionHandler.handleCorruption(e);
    }

  }

  public void commit(int eventId) throws IOException {
    writeLock.lock();
    try {
      if (eventId > counter) {
        throw new IOException("Cannot commit an ID that has not been created.");
      }
      output.writeInt(TYPE_COMMIT);
      output.writeInt(eventId);
      output.hsync();
      uncommittedEvents.remove(eventId);
    } finally {
      writeLock.unlock();
    }
  }

  public String getPath() {
    return location;
  }

  public int begin(EVENT event) throws IOException, NeedsRotationException {
    writeLock.lock();
    try {
      if (needsRotation()) {
        throw new NeedsRotationException();
      }
      int eventId = ++counter;
      output.writeInt(TYPE_BEGIN);
      output.writeInt(eventId);
      // TODO: support other types besides writable
      ((Writable) event).write(output);
      output.hsync();
      uncommittedEvents.put(eventId, event);
      return eventId;
    } finally {
      writeLock.unlock();
    }
  }

  public boolean needsRotation() {
    return counter == Integer.MAX_VALUE || counter < 0;
  }

  public void close() throws IOException {
    writeLock.lock();
    try {
      if (output != null) {
        output.close();
      }
    } finally {
      writeLock.unlock();
    }
  }

  /**
   * Returns a deep copy of the uncommitted events for this write ahead log at
   * the time of method invocation.
   *
   * @return An iterable copy of the uncommitted events for this write ahead
   *         log.
   */
  public Iterable<Entry<Integer, EVENT>> getUncommittedEvents() {
    writeLock.lock();
    try {
      return HashIntObjMaps.newImmutableMap(uncommittedEvents).entrySet();
    } finally {
      writeLock.unlock();
    }
  }

  public boolean isFullyCommitted() {
    return uncommittedEvents.size() == 0;
  }

  public int getCounter() {
    return counter;
  }

}
TOP

Related Classes of com.bah.geterdun.WriteAheadLog$Factory

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.