code: @Override
    public synchronized int read(byte[] buf, int offset, int length) throws IOException {
      long startTime = System.nanoTime();
      Preconditions.checkNotNull(buf, "buf must not be null");
      if (offset < 0 || length < 0 || length > buf.length - offset) {
        throw new IndexOutOfBoundsException();
      }
  
      int numRead = channel.read(ByteBuffer.wrap(buf, offset, length));
  
      if (numRead > 0) {
        // -1 means we actually read 0 bytes, but requested at least one byte.
        statistics.incrementBytesRead(numRead);
        totalBytesRead += numRead;
      }
  
      long duration = System.nanoTime() - startTime;
      ghfs.increment(GoogleHadoopFileSystemBase.Counter.READ);
      ghfs.increment(GoogleHadoopFileSystemBase.Counter.READ_TIME, duration);
      return numRead;
    }
docs: Reads up to length bytes from the underlying store and stores them starting at the specified
  offset in the given buffer. Less than length bytes may be returned.
  
  @param buf The buffer into which data is returned.
  @param offset The offset at which data is written.
  @param length Maximum number of bytes to read.
  @return Number of bytes read or -1 on EOF.
  @throws IOException if an IO error occurs.