// Path: src/main/java/com/bah/lucene/blockcache_v2/CacheValue.java
// public interface CacheValue {
// 
//   /**
//    * The actual size of the the underlying resource.
//    * 
//    * @return the size.
//    */
//   int size();
// 
//   /**
//    * The length of the data in this block.
//    * 
//    * @return the length.
//    */
//   int length();
// 
//   /**
//    * Writes data out to a given position in this block.
//    * 
//    * @param position
//    *          the position.
//    * @param buf
//    *          the buffer.
//    * @param offset
//    *          the offset in the buffer.
//    * @param length
//    *          the length of bytes to write.
//    */
//   void write(int position, byte[] buf, int offset, int length);
// 
//   /**
//    * Reads data into the buffer given the position.
//    * 
//    * @param position
//    *          the position to read.
//    * @param buf
//    *          the buffer to read into.
//    * @param offset
//    *          the offset within the buffer.
//    * @param length
//    *          the length of data to read.
//    */
//   void read(int position, byte[] buf, int offset, int length);
// 
//   /**
//    * Reads a byte from the given position.
//    * 
//    * @param position
//    *          the position.
//    * @return the byte.
//    */
//   byte read(int position);
// 
//   /**
//    * Increments the reference.
//    */
//   void incRef();
// 
//   /**
//    * Decrements the reference.
//    */
//   void decRef();
// 
//   /**
//    * Gets the reference count.
//    */
//   long refCount();
// 
//   /**
//    * Releases any underlying resources.
//    */
//   void release();
// 
//   /**
//    * Reads a short from the given position.
//    * 
//    * @param position
//    *          the {@link Position} to read from.
//    * @return the short.
//    */
//   short readShort(int position);
// 
//   /**
//    * Reads a int from the given position.
//    * 
//    * @param position
//    *          the {@link Position} to read from.
//    * @return the int.
//    */
//   int readInt(int position);
// 
//   /**
//    * Reads a long from the given position.
//    * 
//    * @param position
//    *          the {@link Position} to read from.
//    * @return the long.
//    */
//   long readLong(int position);
// 
//   /**
//    * This method will trim the existing {@link CacheValue} and produce
//    * potentially a new {@link CacheValue} with the same data up to the length
//    * provided. Also if a new {@link CacheValue} is produced then this method is
//    * responsible to calling release on the old {@link CacheValue}.
//    * 
//    * @param length
//    *          the valid amount of data in the {@link CacheValue}.
//    * @return new trim {@link CacheValue} that has been trimmed if needed.
//    */
//   CacheValue trim(int length);
// 
// }


import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicLong;
import com.bah.lucene.blockcache_v2.CacheValue;
  protected void readInternal(int position, byte[] buf, int offset, int length) {
    copyToArray(resolveAddress(position), buf, offset, length);
  }

  @Override
  protected byte readInternal(int position) {
    return _unsafe.getByte(resolveAddress(position));
  }

  private long resolveAddress(int position) {
    return _address + position;
  }

  @Override
  public void release() {
    if (!_released) {
      _unsafe.freeMemory(_address);
      _released = true;
      _offHeapMemorySize.addAndGet(0 - _capacity);
    } else {
      new Throwable().printStackTrace();
    }
  }

  @Override
  public int size() {
    return _capacity;
  }

  @Override
// Path: src/main/java/com/bah/lucene/blockcache_v2/CacheValue.java
// public interface CacheValue {
// 
//   /**
//    * The actual size of the the underlying resource.
//    * 
//    * @return the size.
//    */
//   int size();
// 
//   /**
//    * The length of the data in this block.
//    * 
//    * @return the length.
//    */
//   int length();
// 
//   /**
//    * Writes data out to a given position in this block.
//    * 
//    * @param position
//    *          the position.
//    * @param buf
//    *          the buffer.
//    * @param offset
//    *          the offset in the buffer.
//    * @param length
//    *          the length of bytes to write.
//    */
//   void write(int position, byte[] buf, int offset, int length);
// 
//   /**
//    * Reads data into the buffer given the position.
//    * 
//    * @param position
//    *          the position to read.
//    * @param buf
//    *          the buffer to read into.
//    * @param offset
//    *          the offset within the buffer.
//    * @param length
//    *          the length of data to read.
//    */
//   void read(int position, byte[] buf, int offset, int length);
// 
//   /**
//    * Reads a byte from the given position.
//    * 
//    * @param position
//    *          the position.
//    * @return the byte.
//    */
//   byte read(int position);
// 
//   /**
//    * Increments the reference.
//    */
//   void incRef();
// 
//   /**
//    * Decrements the reference.
//    */
//   void decRef();
// 
//   /**
//    * Gets the reference count.
//    */
//   long refCount();
// 
//   /**
//    * Releases any underlying resources.
//    */
//   void release();
// 
//   /**
//    * Reads a short from the given position.
//    * 
//    * @param position
//    *          the {@link Position} to read from.
//    * @return the short.
//    */
//   short readShort(int position);
// 
//   /**
//    * Reads a int from the given position.
//    * 
//    * @param position
//    *          the {@link Position} to read from.
//    * @return the int.
//    */
//   int readInt(int position);
// 
//   /**
//    * Reads a long from the given position.
//    * 
//    * @param position
//    *          the {@link Position} to read from.
//    * @return the long.
//    */
//   long readLong(int position);
// 
//   /**
//    * This method will trim the existing {@link CacheValue} and produce
//    * potentially a new {@link CacheValue} with the same data up to the length
//    * provided. Also if a new {@link CacheValue} is produced then this method is
//    * responsible to calling release on the old {@link CacheValue}.
//    * 
//    * @param length
//    *          the valid amount of data in the {@link CacheValue}.
//    * @return new trim {@link CacheValue} that has been trimmed if needed.
//    */
//   CacheValue trim(int length);
// 
// }


// Path: src/main/java/com/bah/lucene/blockcache_v2/cachevalue/UnsafeCacheValue.java
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicLong;
import com.bah.lucene.blockcache_v2.CacheValue;

  protected void readInternal(int position, byte[] buf, int offset, int length) {
    copyToArray(resolveAddress(position), buf, offset, length);
  }

  @Override
  protected byte readInternal(int position) {
    return _unsafe.getByte(resolveAddress(position));
  }

  private long resolveAddress(int position) {
    return _address + position;
  }

  @Override
  public void release() {
    if (!_released) {
      _unsafe.freeMemory(_address);
      _released = true;
      _offHeapMemorySize.addAndGet(0 - _capacity);
    } else {
      new Throwable().printStackTrace();
    }
  }

  @Override
  public int size() {
    return _capacity;
  }

  @Override
  public CacheValue trim(int length) {