public static void serializeHeader(ByteBuffer outputBuffer, long totalSize, int blobPropertiesRecordRelativeOffset,
        int updateRecordRelativeOffset, int userMetadataRecordRelativeOffset, int blobRecordRelativeOffset)
        throws MessageFormatException {
      checkHeaderConstraints(totalSize, blobPropertiesRecordRelativeOffset, updateRecordRelativeOffset,
          userMetadataRecordRelativeOffset, blobRecordRelativeOffset);
      int startOffset = outputBuffer.position();
      outputBuffer.putShort(Message_Header_Version_V1);
      outputBuffer.putLong(totalSize);
      outputBuffer.putInt(blobPropertiesRecordRelativeOffset);
      outputBuffer.putInt(updateRecordRelativeOffset);
      outputBuffer.putInt(userMetadataRecordRelativeOffset);
      outputBuffer.putInt(blobRecordRelativeOffset);
      CRC32 crc = new CRC32();
      crc.update(outputBuffer.array(), startOffset, getHeaderSize() - Crc_Size);
      outputBuffer.putLong(crc.getValue());
      logger.trace("serializing header : version {} size {} blobpropertiesrecordrelativeoffset {} "
              + "updaterecordrelativeoffset {} usermetadatarecordrelativeoffset {} blobrecordrelativeoffset {} crc {}",
          Message_Header_Version_V1, totalSize, blobPropertiesRecordRelativeOffset, updateRecordRelativeOffset,
          userMetadataRecordRelativeOffset, blobPropertiesRecordRelativeOffset, crc.getValue());
    }
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|         |              |               |           |               |           |           |
| version | payload size | Blob Property | Update    | User Metadata | Blob      | Crc       |
|(2 bytes)|   (8 bytes)  | Relative      | Relative  | Relative      | Relative  | (8 bytes) |
|         |              | Offset        | Offset    | Offset        | Offset    |           |
|         |              | (4 bytes)     | (4 bytes) | (4 bytes)     | (4 bytes) |           |
|         |              |               |           |               |           |           |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 version         - The version of the message header

 payload size    - The size of the message payload.
                   (Blob prop record size or update record size) + user metadata size + blob size

 blob property   - The offset at which the blob property record is located relative to this message. Only one of
 relative offset   blob property/update relative offset field can exist. Non existence is indicated by -1

 update          - The offset at which the update record is located relative to this message. Only one of blob
 relative offset   property/update relative offset field can exist. Non existence is indicated by -1

 user metadata   - The offset at which the user metadata record is located relative to this message. This exist
 relative offset   only when blob property record and blob record exist

 blob metadata   - The offset at which the blob record is located relative to this message. This exist only when
 relative offset   blob property record and user metadata record exist

 crc             - The crc of the message header
ambry-messageformat/src/main/java/com/github/ambry/messageformat/MessageFormatRecord.java