/**
   * {@inheritDoc}
   *
   * <p>Overridden to return the 'n' field in the reply document.
   *
   * @see AbstractReplyCallback#convert(Reply)
   */
  @Override
  protected Integer convert(final Reply reply) throws MongoDbException {
    final List<Document> results = reply.getResults();
    if (results.size() == 1) {
      final Document doc = results.get(0);
      final Element nElem = doc.get(myName);
      return Integer.valueOf(toInt(nElem));
    }

    return Integer.valueOf(-1);
  }
  /**
   * Test method for {@link BasicMongoClientMetrics#receive(String, long, Message, Reply, long)} .
   */
  @Test
  public void testReceive() {
    final Message mockSentMessage = createMock(Message.class);
    final Reply mockReply = createMock(Reply.class);

    final BasicMongoClientMetrics metrics = new BasicMongoClientMetrics();

    // One for the DB and one for the collection.
    expect(mockReply.size()).andReturn(202).times(5);
    expect(mockSentMessage.getOperationName()).andReturn("operation");
    expect(mockSentMessage.getDatabaseName()).andReturn("db");
    expect(mockSentMessage.getCollectionName()).andReturn("collection");
    expectLastCall();

    replay(mockSentMessage, mockReply);

    metrics.receive("server1", 0L, mockSentMessage, mockReply, TimeUnit.MILLISECONDS.toNanos(1));

    metrics.close();

    verify(mockSentMessage, mockReply);
  }
 /**
  * {@inheritDoc}
  *
  * <p>Creates an exception from the {@link Reply} if the 'n' field is missing.
  *
  * @param reply The raw reply.
  * @return The exception created.
  */
 @Override
 protected MongoDbException asError(final Reply reply) {
   MongoDbException error = super.asError(reply);
   if (error == null) {
     final List<Document> results = reply.getResults();
     if (results.size() == 1) {
       final Document doc = results.get(0);
       final Element nElem = doc.get(myName);
       if (toInt(nElem) < 0) {
         error = new ReplyException(reply, "Missing '" + myName + "' field in reply.");
       }
     }
   }
   return error;
 }
  /**
   * Re-bootstraps the environment. Normally this method is only called once during the constructor
   * of the factory to initialize the delegate but users can reset the delegate by manually invoking
   * this method.
   *
   * <p>A bootstrap will issue one commands to the first working MongoDB process. The reply to the
   * {@link IsMaster} command is used to detect connecting to a mongos <tt>process</tt> and by
   * extension a Sharded configuration.
   *
   * <p>If not using a Sharded configuration then the server status is checked for a <tt>repl</tt>
   * element. If present a Replication Set configuration is assumed.
   *
   * <p>If neither a Sharded or Replication Set is being used then a plain socket connection factory
   * is used.
   */
  protected void bootstrap() {
    final SocketConnectionFactory socketFactory = createSocketFactory(myConfig);
    socketFactory.setMetrics(myMetrics);

    ProxiedConnectionFactory factory = socketFactory;

    // Authentication has to be right on top of the physical
    // connection.
    if (myConfig.isAuthenticating()) {
      factory = new AuthenticationConnectionFactory(factory, myConfig);
    }

    try {
      // Use the socket factories cluster.
      final Cluster cluster = socketFactory.getCluster();
      for (final InetSocketAddress addr : myConfig.getServerAddresses()) {
        Connection conn = null;
        final FutureReplyCallback future = new FutureReplyCallback();
        try {
          conn = factory.connect(cluster.add(addr), myConfig);

          conn.send(new IsMaster(), future);
          final Reply reply = future.get();

          // Close the connection now that we have the reply.
          IOUtils.close(conn);

          final List<Document> results = reply.getResults();
          if (!results.isEmpty()) {
            final Document doc = results.get(0);

            if (isMongos(doc)) {
              LOG.debug("Sharded bootstrap to {}.", addr);
              cluster.clear(); // not needed.
              myDelegate = bootstrapSharded(factory);
            } else if (isReplicationSet(doc)) {
              LOG.debug("Replica-set bootstrap to {}.", addr);
              cluster.clear(); // not needed.
              myDelegate = bootstrapReplicaSet(factory);
            } else {
              LOG.debug("Simple MongoDB bootstrap to {}.", addr);
              myDelegate = factory;
            }
            factory = null; // Don't close.
            return;
          }
        } catch (final IOException ioe) {
          LOG.warn(ioe, "I/O error during bootstrap to {}.", addr);
        } catch (final InterruptedException e) {
          LOG.warn(e, "Interrupted during bootstrap to {}.", addr);
        } catch (final ExecutionException e) {
          LOG.warn(e, "Error during bootstrap to {}.", addr);
        } finally {
          IOUtils.close(
              conn, Level.WARNING, "I/O error shutting down bootstrap connection to " + addr + ".");
        }
      }
    } finally {
      IOUtils.close(factory);
    }
  }