@Override
  public int read(ByteBuffer dst) throws IOException {
    checkNotNull(dst);
    checkOpen();
    checkReadable();

    int read = 0; // will definitely either be assigned or an exception will be thrown

    synchronized (this) {
      boolean completed = false;
      try {
        if (!beginBlocking()) {
          return 0; // AsynchronousCloseException will be thrown
        }
        file.readLock().lockInterruptibly();
        try {
          read = file.read(position, dst);
          if (read != -1) {
            position += read;
          }
          file.setLastAccessTime(fileSystemState.now());
          completed = true;
        } finally {
          file.readLock().unlock();
        }
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
      } finally {
        endBlocking(completed);
      }
    }

    return read;
  }
@Test
  public void testRead() throws IOException {
    RegularFile file = regularFile(20);
    FileChannel channel = channel(file, READ);
    assertEquals(0, channel.position());

    ByteBuffer buf = buffer("1234567890");
    ByteBuffer buf2 = buffer("123457890");
    assertEquals(10, channel.read(buf));
    assertEquals(10, channel.position());

    buf.flip();
    assertEquals(10, channel.read(new ByteBuffer[] {buf, buf2}));
    assertEquals(20, channel.position());

    buf.flip();
    buf2.flip();
    file.write(20, new byte[10], 0, 10);
    assertEquals(10, channel.read(new ByteBuffer[] {buf, buf2}, 0, 2));
    assertEquals(30, channel.position());

    buf.flip();
    assertEquals(10, channel.read(buf, 5));
    assertEquals(30, channel.position());

    buf.flip();
    assertEquals(-1, channel.read(buf));
    assertEquals(30, channel.position());
  }