/** * Creates the delegate connection factory. * * @return The delegate connection factory. */ private synchronized ConnectionFactory createDelegate() { if (myDelegate == null) { bootstrap(); if (myDelegate == null) { LOG.warn("Could not bootstrap a connection to the MongoDB servers."); throw new CannotConnectException( "Could not bootstrap a connection to the MongoDB servers."); } } return myDelegate; }
/** * 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); } }