public static int readFileToByteBuf(FileChannel fileChannel, ByteBuf buffer, long offset, int size)
      throws IOException {
    // If the writable bytes in ByteBuf is less then the given size, ByteBuf would expand its capacity.
    // Put a check here to make sure that we don't expand the capacity.
    if (buffer.writableBytes() < size) {
      throw new IllegalArgumentException(
          "ByteBuf doesn't have enough writable bytes [" + buffer.writableBytes() + "<" + size + "]");
    }
    int bytesRead = 0;
    while (bytesRead < size) {
      int readSize = buffer.writeBytes(fileChannel, offset + bytesRead, size - bytesRead);
      if (readSize == -1 || readSize == 0) {
        return bytesRead;
      }
      bytesRead += readSize;
    }
    return bytesRead;
  }
Read "size" of bytes from a file channel to a {@link ByteBuf}. If "size" length of bytes can't be read because of
EOF, this method would return already read bytes.
@param fileChannel The file channel to read bytes
@param buffer The target {@link ByteBuf} to write bytes to.
@param offset The offset of the file channel to read bytes from.
@param size The size to read
@return The real bytes read from the file channel
@throws IOException
ambry-utils/src/main/java/com/github/ambry/utils/Utils.java