@Override
  public T execute(final InternalConnection connection) {
    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug(
          format(
              "Sending command {%s : %s} to database %s on connection [%s] to server %s",
              getCommandName(),
              command.values().iterator().next(),
              namespace.getDatabaseName(),
              connection.getDescription().getConnectionId(),
              connection.getDescription().getServerAddress()));
    }
    long startTimeNanos = System.nanoTime();
    CommandMessage commandMessage =
        new CommandMessage(
            namespace.getFullName(),
            command,
            slaveOk,
            fieldNameValidator,
            ProtocolHelper.getMessageSettings(connection.getDescription()));
    ResponseBuffers responseBuffers = null;
    try {
      sendMessage(commandMessage, connection);
      responseBuffers = connection.receiveMessage(commandMessage.getId());
      if (!ProtocolHelper.isCommandOk(
          new BsonBinaryReader(new ByteBufferBsonInput(responseBuffers.getBodyByteBuffer())))) {
        throw getCommandFailureException(
            getResponseDocument(responseBuffers, commandMessage, new BsonDocumentCodec()),
            connection.getDescription().getServerAddress());
      }

      T retval = getResponseDocument(responseBuffers, commandMessage, commandResultDecoder);

      if (commandListener != null) {
        sendSucceededEvent(
            connection.getDescription(),
            startTimeNanos,
            commandMessage,
            getResponseDocument(responseBuffers, commandMessage, new RawBsonDocumentCodec()));
      }
      LOGGER.debug("Command execution completed");
      return retval;
    } catch (RuntimeException e) {
      sendFailedEvent(connection.getDescription(), startTimeNanos, commandMessage, e);
      throw e;
    } finally {
      if (responseBuffers != null) {
        responseBuffers.close();
      }
    }
  }
 @Override
 public void executeAsync(
     final InternalConnection connection, final SingleResultCallback<T> callback) {
   long startTimeNanos = System.nanoTime();
   CommandMessage message =
       new CommandMessage(
           namespace.getFullName(),
           command,
           slaveOk,
           fieldNameValidator,
           ProtocolHelper.getMessageSettings(connection.getDescription()));
   boolean sentStartedEvent = false;
   try {
     if (LOGGER.isDebugEnabled()) {
       LOGGER.debug(
           format(
               "Asynchronously sending command {%s : %s} to database %s on connection [%s] to server %s",
               getCommandName(),
               command.values().iterator().next(),
               namespace.getDatabaseName(),
               connection.getDescription().getConnectionId(),
               connection.getDescription().getServerAddress()));
     }
     ByteBufferBsonOutput bsonOutput = new ByteBufferBsonOutput(connection);
     int documentPosition =
         ProtocolHelper.encodeMessageWithMetadata(message, bsonOutput).getFirstDocumentPosition();
     sendStartedEvent(connection, bsonOutput, message, documentPosition);
     sentStartedEvent = true;
     SingleResultCallback<ResponseBuffers> receiveCallback =
         new CommandResultCallback(callback, message, connection.getDescription(), startTimeNanos);
     connection.sendMessageAsync(
         bsonOutput.getByteBuffers(),
         message.getId(),
         new SendMessageCallback<T>(
             connection,
             bsonOutput,
             message,
             getCommandName(),
             startTimeNanos,
             commandListener,
             callback,
             receiveCallback));
   } catch (Throwable t) {
     if (sentStartedEvent) {
       sendFailedEvent(connection.getDescription(), startTimeNanos, message, t);
     }
     callback.onResult(null, t);
   }
 }