private NetworkSend write(SelectionKey key, Transmission transmission) {
    long startTimeToWriteInMs = time.milliseconds();
    NetworkSend networkSend = null;
    try {
      networkSend = transmission.getNetworkSend();
      boolean sendComplete = transmission.write();
      if (sendComplete) {
        logger.trace("Finished writing, registering for read on connection {}", transmission.getRemoteSocketAddress());
        // Release the NetworkSend resource here, not in the SocketNetworkClient, because SocketServer uses Selector
        // as well, and SocketServer doesn't has a callback to release the resource.
        networkSend.getPayload().release();
        transmission.onSendComplete();
        metrics.sendInFlight.dec();
        transmission.clearSend();
        key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE | SelectionKey.OP_READ);
      }
      return networkSend;
    } catch (IOException e) {
      // We have key information if we log IOException here.
      handleReadWriteIOException(e, key);
      if (networkSend != null && networkSend.shouldReleaseOnError()) {
        networkSend.getPayload().release();
      }
      return null;
    } finally {
      long writeTime = time.milliseconds() - startTimeToWriteInMs;
      logger.trace("SocketServer time spent on write per key {} = {}", transmission.getConnectionId(), writeTime);
    }
  }
Process writes to ready sockets
@return the {@link NetworkSend} if no IOException during write().
ambry-network/src/main/java/com/github/ambry/network/Selector.java