protected IoBuffer getNextBuffer(FileRegion fileRegion) throws IOException {
    if (fileRegion.getRemainingBytes() <= 0L) {
      return null;
    }

    int bufferSize = (int) Math.min(getWriteBufferSize(), fileRegion.getRemainingBytes());
    IoBuffer buffer = IoBuffer.allocate(bufferSize);

    int bytesRead = fileRegion.getFileChannel().read(buffer.buf(), fileRegion.getPosition());
    fileRegion.update(bytesRead);

    buffer.flip();
    return buffer;
  }
  private int writeFile(
      S session, WriteRequest req, boolean hasFragmentation, int maxLength, long currentTime)
      throws Exception {
    int localWrittenBytes;
    FileRegion region = (FileRegion) req.getMessage();

    if (region.getRemainingBytes() > 0) {
      int length;

      if (hasFragmentation) {
        length = (int) Math.min(region.getRemainingBytes(), maxLength);
      } else {
        length = (int) Math.min(Integer.MAX_VALUE, region.getRemainingBytes());
      }

      localWrittenBytes = transferFile(session, region, length);
      region.update(localWrittenBytes);
    } else {
      localWrittenBytes = 0;
    }

    session.increaseWrittenBytes(localWrittenBytes, currentTime);

    if ((region.getRemainingBytes() <= 0) || (!hasFragmentation && (localWrittenBytes != 0))) {
      fireMessageSent(session, req);
    }

    return localWrittenBytes;
  }