/** * {@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); }
/** * {@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); } }