protected void putBlob(BlobProperties blobProperties, byte[] userMetadata, ReadableStreamChannel channel,
      PutBlobOptions options, FutureResult<String> futureResult, Callback<String> callback,
      QuotaChargeCallback quotaChargeCallback) {
    if (!putManager.isOpen()) {
      handlePutManagerClosed(blobProperties, false, futureResult, callback);
    } else {
      putManager.submitPutBlobOperation(blobProperties, userMetadata, channel, options, futureResult, callback,
          quotaChargeCallback);
      routerCallback.onPollReady();
    }
  }
Requests for a new blob to be put asynchronously and invokes the {@link Callback} when the request completes.
@param blobProperties The properties of the blob.
@param userMetadata Optional user metadata about the blob. This can be null.
@param channel The {@link ReadableStreamChannel} that contains the content of the blob.
@param options The {@link PutBlobOptions} associated with the request. This cannot be null.
@param futureResult A future that would contain the BlobId eventually.
@param callback The {@link Callback} which will be invoked on the completion of the request .
ambry-router/src/main/java/com/github/ambry/router/OperationController.java