/**
   * Flush the buffer by looping until the {@link Buffer} is empty
   *
   * @param connection the {@link org.glassfish.grizzly.Connection}.
   * @param dstAddress the destination address.
   * @param message
   * @param currentResult the result of the write operation
   * @param timeout operation timeout value value
   * @param timeunit the timeout unit
   * @return The number of bytes written.
   * @throws java.io.IOException
   */
  protected long write0(
      final NIOConnection connection,
      final SocketAddress dstAddress,
      final WritableMessage message,
      final WriteResult<WritableMessage, SocketAddress> currentResult,
      final long timeout,
      final TimeUnit timeunit)
      throws IOException {

    final SelectableChannel channel = connection.getChannel();
    final long writeTimeout = TimeUnit.MILLISECONDS.convert(timeout, timeunit);

    SelectionKey key = null;
    Selector writeSelector = null;
    int attempts = 0;
    int bytesWritten = 0;

    try {
      synchronized (connection) {
        while (message.hasRemaining()) {
          long len = writeNow0(connection, dstAddress, message, currentResult);

          if (len > 0) {
            attempts = 0;
            bytesWritten += len;
          } else {
            attempts++;
            if (writeSelector == null) {
              writeSelector = transport.getTemporarySelectorIO().getSelectorPool().poll();

              if (writeSelector == null) {
                // Continue using the main one.
                continue;
              }
              key = channel.register(writeSelector, SelectionKey.OP_WRITE);
            } else {
              writeSelector.selectedKeys().clear();
            }

            if (writeSelector.select(writeTimeout) == 0) {
              if (attempts > 2) {
                throw new IOException("Client disconnected");
              }
            }
          }
        }
      }
    } finally {
      transport.getTemporarySelectorIO().recycleTemporaryArtifacts(writeSelector, key);
    }

    return bytesWritten;
  }