@Override
  protected void prepareBuffer() {
    // bufferToSend now is the header ByteBuf, it will store serialized header, without blob content and crc
    bufferToSend = PooledByteBufAllocator.DEFAULT.ioBuffer(sizeExcludingBlobAndCrcSize());
    writeHeader();
    int crcStart = bufferToSend.writerIndex();
    bufferToSend.writeBytes(blobId.toBytes());
    BlobPropertiesSerDe.serializeBlobProperties(bufferToSend, properties);
    bufferToSend.writeInt(usermetadata.capacity());
    bufferToSend.writeBytes(usermetadata);
    bufferToSend.writeShort((short) blobType.ordinal());
    short keyLength = blobEncryptionKey == null ? 0 : (short) blobEncryptionKey.remaining();
    bufferToSend.writeShort(keyLength);
    if (keyLength > 0) {
      bufferToSend.writeBytes(blobEncryptionKey);
    }
    if (versionId >= PUT_REQUEST_VERSION_V5) {
      bufferToSend.writeByte(isCompressed ? 1 : 0);
    }
    bufferToSend.writeLong(blobSize);

    // Now compute crc for the put request.
    crc.update(bufferToSend.nioBuffer(crcStart, bufferToSend.writerIndex() - crcStart));
    for (ByteBuffer bb : blob.nioBuffers()) {
      crc.update(bb);
      // change it back to 0 since we are going to write it to the channel later.
      bb.position(0);
    }
    crcByteBuf = PooledByteBufAllocator.DEFAULT.ioBuffer(CRC_SIZE_IN_BYTES);
    crcByteBuf.writeLong(crc.getValue());

    // Now construct the real bufferToSend, which should be a composite ByteBuf.
    CompositeByteBuf compositeByteBuf = bufferToSend.alloc().compositeHeapBuffer(2 + blob.nioBufferCount());
    compositeByteBuf.addComponent(true, bufferToSend);
    if (blob instanceof CompositeByteBuf) {
      Iterator<ByteBuf> iter = ((CompositeByteBuf) blob).iterator();
      while (iter.hasNext()) {
        compositeByteBuf.addComponent(true, iter.next());
      }
    } else {
      compositeByteBuf.addComponent(true, blob);
    }
    compositeByteBuf.addComponent(true, crcByteBuf);
    blob = null;
    crcByteBuf = null;
    bufferToSend = compositeByteBuf;
  }
Construct the bufferToSend to serialize request metadata and other blob related information. The newly constructed
bufferToSend will not include the blob content as it's carried by the {@code blob} field in this class.
ambry-protocol/src/main/java/com/github/ambry/protocol/PutRequest.java