@Override
  public Data read(int valueId, boolean checkAccess) throws IOException {
    int offset = valueId;
    AppendMemoryBuffer buffer = appendBuffer;
    if (buffer != null
        && (long)offset >= buffer.startingOffsetInFile) {
      AppendMemoryBuffer copyForRead = buffer.copy();

      int bufferOffset = offset - copyForRead.startingOffsetInFile;
      if (bufferOffset > copyForRead.bufferPosition) {
        throw new NoDataException("Requested address(=" + offset + ") points to un-existed data: " + appendBuffer);
      }

      UnsyncByteArrayInputStream is = new UnsyncByteArrayInputStream(
        copyForRead.getAppendBuffer(),
        bufferOffset,
        copyForRead.getBufferPosition()
      );
      return dataDescriptor.read(new DataInputStream(is));
    }

    if (offset >= fileLength) {
      throw new NoDataException("Requested address(=" + offset + ") points to un-existed data (file length: " + fileLength + ")");
    }
    // we do not need to flushAppendBuffer() since we store complete records
    MyDataIS rs = TLOCAL_READ_STREAMS.get();

    rs.setup(storage, offset, fileLength, checkAccess);
    return dataDescriptor.read(rs);
  }
@Override
  public Data read(int valueId, boolean checkAccess)