private Future<Long> writeInternal(Supplier<ByteBuf> retainedBufSupplier, Callback<Long> callback) {
    FutureResult<Long> future = new FutureResult<>();
    ByteBuf buf = null;
    long bytesWritten = 0;
    Exception exception = null;
    try {
      if (!isOpen()) {
        throw new ClosedChannelException();
      } else if (totalBytesWritten.get() > sizeLimitInBytes) {
        throw new RestServiceException("Request is larger than allowed size: " + sizeLimitInBytes,
            RestServiceErrorCode.RequestTooLarge);
      } else {
        synchronized (bufferLock) {
          if (compositeBuffer == null) {
            throw new IllegalStateException("Cannot write more data; content already consumed or channel was closed");
          }
          buf = retainedBufSupplier.get();
          bytesWritten = buf.readableBytes();
          compositeBuffer.addComponent(true, buf);
        }
        if (totalBytesWritten.addAndGet(bytesWritten) > sizeLimitInBytes) {
          exception = new RestServiceException("Request is larger than allowed size: " + sizeLimitInBytes,
              RestServiceErrorCode.RequestTooLarge);
        }
      }
    } catch (Exception e) {
      exception = e;
      if (buf != null) {
        buf.release();
      }
    } finally {
      future.done(bytesWritten, exception);
      if (callback != null) {
        callback.onCompletion(bytesWritten, exception);
      }
    }
    return future;
  }
Internal method for writing to the channel that allows for a pluggable action to be taken to produce a
retained {@link ByteBuf} that can be added to the composite buffer.
@param retainedBufSupplier creates a retained {@link ByteBuf} that can be freely added to a
                           {@link CompositeByteBuf}.
@param callback called once the buffer has been added.
@return a future that is completed once the buffer has been added.
ambry-commons/src/main/java/com/github/ambry/commons/RetainingAsyncWritableChannel.java