@Override
  public Cacheable read(BucketEntry be) throws IOException {
    long offset = be.offset();
    int length = be.getLength();
    Preconditions.checkArgument(length >= 0, "Length of read can not be less than 0.");
    ByteBuff dstBuff = be.allocator.allocate(length);
    if (length != 0) {
      try {
        accessFile(readAccessor, dstBuff, offset);
        // The buffer created out of the fileChannel is formed by copying the data from the file
        // Hence in this case there is no shared memory that we point to. Even if the BucketCache
        // evicts this buffer from the file the data is already copied and there is no need to
        // ensure that the results are not corrupted before consuming them.
        if (dstBuff.limit() != length) {
          throw new IllegalArgumentIOException(
            "Only " + dstBuff.limit() + " bytes read, " + length + " expected");
        }
      } catch (IOException ioe) {
        dstBuff.release();
        throw ioe;
      }
    }
    if (maintainPersistence) {
      dstBuff.rewind();
      long cachedNanoTime = dstBuff.getLong();
      if (be.getCachedTime() != cachedNanoTime) {
        dstBuff.release();
        throw new HBaseIOException("The cached time recorded within the cached block: "
          + cachedNanoTime + " differs from its bucket entry: " + be.getCachedTime());
      }
      dstBuff.limit(length);
      dstBuff = dstBuff.slice();
    } else {
      dstBuff.rewind();
    }
    return be.wrapAsCacheable(dstBuff);
  }
Transfers data from file to the given byte buffer
@param be an {@link BucketEntry} which maintains an (offset, len, refCnt)
@return the {@link Cacheable} with block data inside.
@throws IOException if any IO error happen.
hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/FileIOEngine.java