private ByteBuf combineBuffer(ByteBuf byteBuf, boolean outputDirectBuffer, boolean compressorRequireMatchingBuffer) {
    // We need to copy the buffer if the source and target buffer mismatch, and they are required to match.
    boolean mustCopyBuffer = compressorRequireMatchingBuffer && (outputDirectBuffer != byteBuf.isDirect());

    // If the source buffer is already has 1 buffer, create an index duplicate (not the buffer).
    if (byteBuf.nioBufferCount() == 1 && !mustCopyBuffer) {
      return byteBuf.retainedDuplicate();
    }

    // Copy the buffer out without changing index.
    ByteBuf newBuffer = outputDirectBuffer ? byteBufAllocator.directBuffer(byteBuf.readableBytes()):
        byteBufAllocator.heapBuffer(byteBuf.readableBytes());
    byteBuf.getBytes(byteBuf.readerIndex(), newBuffer);
    return newBuffer;
  }
Convert a ByteBuf to a single buffer.  If source buffer is already single buffer, just return it.
If it is consisted of multiple buffers, combine them into 1 direct buffer.
Since this method may copy the source buffer, it generates a buffer that matches the compressor requirement based
on outputDirectBuffer and compressorRequireMatchingBuffer parameters.

@param byteBuf The source buffer to read from.
@param outputDirectBuffer Whether the output buffer must be direct buffer.
                          True means output is direct buffer; False means output is Heap buffer.
@param compressorRequireMatchingBuffer Whether the source buffer and output buffer must match.
@return The new buffer.  The new buffer must be released when done reading.
ambry-router/src/main/java/com/github/ambry/router/CompressionService.java