private boolean maybeWriteResponseMetadata(HttpResponse responseMetadata,
      GenericFutureListener<ChannelFuture> listener) {
    long writeProcessingStartTime = System.currentTimeMillis();
    boolean writtenThisTime = false;
    if (ctx.channel().isActive() && responseMetadataWriteInitiated.compareAndSet(false, true)) {
      // we do some manipulation here for chunking. According to the HTTP spec, we can have either a Content-Length
      // or Transfer-Encoding:chunked, never both. So we check for Content-Length - if it is not there, we add
      // Transfer-Encoding:chunked on 200 response. Note that sending HttpContent chunks data anyway - we are just
      // explicitly specifying this in the header.
      if (!HttpUtil.isContentLengthSet(responseMetadata) && (responseMetadata.status().equals(HttpResponseStatus.OK)
          || responseMetadata.status().equals(HttpResponseStatus.PARTIAL_CONTENT))) {
        // This makes sure that we don't stomp on any existing transfer-encoding.
        HttpUtil.setTransferEncodingChunked(responseMetadata, true);
      } else if (HttpUtil.isContentLengthSet(responseMetadata) && HttpUtil.getContentLength(responseMetadata) == 0
          && !(responseMetadata instanceof FullHttpResponse)) {
        // if the Content-Length is 0, we can send a FullHttpResponse since there is no content expected.
        FullHttpResponse fullHttpResponse =
            new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseMetadata.status());
        fullHttpResponse.headers().set(responseMetadata.headers());
        responseMetadata = fullHttpResponse;
      }
      logger.trace("Sending response with status {} on channel {}", responseMetadata.status(), ctx.channel());
      finalResponseMetadata = responseMetadata;
      ChannelPromise writePromise = ctx.newPromise().addListener(listener);
      ctx.writeAndFlush(responseMetadata, writePromise);
      writtenThisTime = true;
      long writeProcessingTime = System.currentTimeMillis() - writeProcessingStartTime;
      nettyMetrics.responseMetadataProcessingTimeInMs.update(writeProcessingTime);
      if (request != null) {
        request.getMetricsTracker().nioMetricsTracker.markFirstByteSent();
      }
    }
    return writtenThisTime;
  }
Writes response metadata to the channel if not already written previously and channel is active.
@param responseMetadata the {@link HttpResponse} that needs to be written.
@param listener the {@link GenericFutureListener} that needs to be attached to the write.
@return {@code true} if response metadata was written to the channel in this call. {@code false} otherwise.
ambry-rest/src/main/java/com/github/ambry/rest/NettyResponseChannel.java