com.mongodb.Mongo Maven / Gradle / Ivy
Show all versions of mongodb-driver Show documentation
/*
* Copyright 2008-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mongodb;
import com.mongodb.annotations.ThreadSafe;
import com.mongodb.binding.ConnectionSource;
import com.mongodb.binding.ReadWriteBinding;
import com.mongodb.binding.SingleServerBinding;
import com.mongodb.client.ClientSession;
import com.mongodb.client.internal.MongoClientDelegate;
import com.mongodb.client.internal.MongoIterableImpl;
import com.mongodb.client.internal.OperationExecutor;
import com.mongodb.client.internal.SimpleMongoClient;
import com.mongodb.connection.BufferProvider;
import com.mongodb.connection.Cluster;
import com.mongodb.connection.ClusterConnectionMode;
import com.mongodb.connection.ClusterDescription;
import com.mongodb.connection.ClusterSettings;
import com.mongodb.connection.Connection;
import com.mongodb.connection.DefaultClusterFactory;
import com.mongodb.connection.ServerDescription;
import com.mongodb.connection.SocketStreamFactory;
import com.mongodb.event.ClusterListener;
import com.mongodb.internal.connection.PowerOfTwoBufferPool;
import com.mongodb.internal.session.ServerSessionPool;
import com.mongodb.internal.thread.DaemonThreadFactory;
import com.mongodb.lang.Nullable;
import com.mongodb.operation.BatchCursor;
import com.mongodb.operation.CurrentOpOperation;
import com.mongodb.operation.FsyncUnlockOperation;
import com.mongodb.operation.ListDatabasesOperation;
import com.mongodb.operation.ReadOperation;
import org.bson.BsonBoolean;
import org.bson.codecs.configuration.CodecRegistry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.mongodb.ReadPreference.primary;
import static com.mongodb.client.internal.Crypts.createCrypt;
import static com.mongodb.connection.ClusterConnectionMode.MULTIPLE;
import static com.mongodb.connection.ClusterType.REPLICA_SET;
import static com.mongodb.internal.event.EventListenerHelper.getCommandListener;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.Collections.unmodifiableList;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.bson.internal.CodecRegistryHelper.createRegistry;
/**
* A database connection with internal connection pooling. For most applications, you should have one Mongo instance for the entire
* JVM.
*
* Note: This class has been superseded by {@code MongoClient}, and may be deprecated in a future release.
*
* @see MongoClient
* @see ReadPreference
* @see WriteConcern
* @deprecated Replaced by {@link MongoClient}. Any non-deprecated methods will be moved to MongoClient. The rest will be removed along
* with this class.
*/
@ThreadSafe
@Deprecated
public class Mongo {
static final String ADMIN_DATABASE_NAME = "admin";
private final ConcurrentMap dbCache = new ConcurrentHashMap();
private volatile WriteConcern writeConcern;
private volatile ReadPreference readPreference;
private final ReadConcern readConcern;
private final MongoClientOptions options;
private final List credentialsList;
@SuppressWarnings("deprecation")
private final Bytes.OptionHolder optionHolder;
private final BufferProvider bufferProvider = new PowerOfTwoBufferPool();
private final ConcurrentLinkedQueue orphanedCursors = new ConcurrentLinkedQueue();
private final ExecutorService cursorCleaningService;
private final MongoClientDelegate delegate;
private final AtomicBoolean closed;
/**
* Creates a Mongo instance based on a (single) mongodb node (localhost, default port)
*
* @throws MongoException if there's a failure
* @deprecated Replaced by {@link MongoClient#MongoClient()})
*/
@Deprecated
public Mongo() {
this(new ServerAddress(), createLegacyOptions());
}
/**
* Creates a Mongo instance based on a (single) mongodb node (default port)
*
* @param host server to connect to
* @deprecated Replaced by {@link MongoClient#MongoClient(String)}
*/
@Deprecated
public Mongo(final String host) {
this(new ServerAddress(host), createLegacyOptions());
}
/**
* Creates a Mongo instance based on a (single) mongodb node (default port)
*
* @param host server to connect to
* @param options default query options
* @deprecated Replaced by {@link MongoClient#MongoClient(String, MongoClientOptions)}
*/
@Deprecated
public Mongo(final String host,
@SuppressWarnings("deprecation")
final MongoOptions options) {
this(new ServerAddress(host), options.toClientOptions());
}
/**
* Creates a Mongo instance based on a (single) mongodb node
*
* @param host the host address of the database
* @param port the port on which the database is running
* @deprecated Replaced by {@link MongoClient#MongoClient(String, int)}
*/
@Deprecated
public Mongo(final String host, final int port) {
this(new ServerAddress(host, port), createLegacyOptions());
}
/**
* Creates a Mongo instance based on a (single) mongodb node
*
* @param address the database address
* @see com.mongodb.ServerAddress
* @deprecated Replaced by {@link MongoClient#MongoClient(ServerAddress)}
*/
@Deprecated
public Mongo(final ServerAddress address) {
this(address, createLegacyOptions());
}
/**
* Creates a Mongo instance based on a (single) mongo node using a given ServerAddress
*
* @param address the database address
* @param options default query options
* @see com.mongodb.ServerAddress
* @deprecated Replaced by {@link MongoClient#MongoClient(ServerAddress, MongoClientOptions)}
*/
@Deprecated
public Mongo(final ServerAddress address,
@SuppressWarnings("deprecation")
final MongoOptions options) {
this(address, options.toClientOptions());
}
/**
* Creates a Mongo in paired mode.
*
* This will also work for a replica set and will find all members (the master will be used by default).
*
* @param left left side of the pair
* @param right right side of the pair
* @see com.mongodb.ServerAddress
* @deprecated Please use {@link MongoClient#MongoClient(java.util.List)} instead.
*/
@Deprecated
public Mongo(final ServerAddress left, final ServerAddress right) {
this(asList(left, right), createLegacyOptions());
}
/**
* Creates a Mongo connection in paired mode.
*
* This will also work for a replica set and will find all members (the master will be used by default).
*
* @param left left side of the pair
* @param right right side of the pair
* @param options the optional settings for the Mongo instance
* @see com.mongodb.ServerAddress
* @deprecated Please use {@link MongoClient#MongoClient(java.util.List, MongoClientOptions)} instead.
*/
@Deprecated
public Mongo(final ServerAddress left, final ServerAddress right,
@SuppressWarnings("deprecation")
final MongoOptions options) {
this(asList(left, right), options.toClientOptions());
}
/**
* Creates an instance based on a list of replica set members or mongos servers. For a replica set it will discover all members.
* For a list with a single seed, the driver will still discover all members of the replica set. For a direct
* connection to a replica set member, with no discovery, use the {@link #Mongo(ServerAddress)} constructor instead.
*
* When there is more than one server to choose from based on the type of request (read or write) and the read preference (if it's a
* read request), the driver will randomly select a server to send a request. This applies to both replica sets and sharded clusters.
* The servers to randomly select from are further limited by the local threshold. See
* {@link MongoClientOptions#getLocalThreshold()}
*
* @param seeds Put as many servers as you can in the list and the system will figure out the rest. This can either be a list of mongod
* servers in the same replica set or a list of mongos servers in the same sharded cluster.
* @see MongoClientOptions#getLocalThreshold()
* @deprecated Replaced by {@link MongoClient#MongoClient(java.util.List)}
*/
@Deprecated
public Mongo(final List seeds) {
this(seeds, createLegacyOptions());
}
/**
* Creates an instance based on a list of replica set members or mongos servers. For a replica set it will discover all members.
* For a list with a single seed, the driver will still discover all members of the replica set. For a direct
* connection to a replica set member, with no discovery, use the {@link #Mongo(ServerAddress, MongoClientOptions)} constructor
* instead.
*
* When there is more than one server to choose from based on the type of request (read or write) and the read preference (if it's a
* read request), the driver will randomly select a server to send a request. This applies to both replica sets and sharded clusters.
* The servers to randomly select from are further limited by the local threshold. See
* {@link MongoClientOptions#getLocalThreshold()}
*
* @param seeds Put as many servers as you can in the list and the system will figure out the rest. This can either be a list of mongod
* servers in the same replica set or a list of mongos servers in the same sharded cluster.
* @param options the options
* @see MongoClientOptions#getLocalThreshold()
* @deprecated Replaced by {@link MongoClient#MongoClient(java.util.List, MongoClientOptions)}
*/
@Deprecated
public Mongo(final List seeds,
@SuppressWarnings("deprecation")
final MongoOptions options) {
this(seeds, options.toClientOptions());
}
/**
* Creates a Mongo described by a URI. If only one address is used it will only connect to that node, otherwise it will discover all
* nodes. If the URI contains database credentials, the database will be authenticated lazily on first use with those credentials.
*
* Examples:
*
* - mongodb://localhost
* - mongodb://fred:foobar@localhost/
*
*
* @param uri URI to connect to, optionally containing additional information like credentials
* @throws MongoException if there's a failure
* @mongodb.driver.manual reference/connection-string Connection String URI Format
* @see MongoURI
* @deprecated Replaced by {@link MongoClient#MongoClient(MongoClientURI)}
*/
@Deprecated
public Mongo(
@SuppressWarnings("deprecation")
final MongoURI uri) {
this(uri.toClientURI());
}
Mongo(final List seedList, final MongoClientOptions options) {
this(seedList, Collections.emptyList(), options);
}
Mongo(final ServerAddress serverAddress, final MongoClientOptions options) {
this(serverAddress, Collections.emptyList(), options);
}
Mongo(final ServerAddress serverAddress, final List credentialsList, final MongoClientOptions options) {
this(serverAddress, credentialsList, options, null);
}
Mongo(final ServerAddress serverAddress, final List credentialsList, final MongoClientOptions options,
@Nullable final MongoDriverInformation mongoDriverInformation) {
this(createCluster(serverAddress, credentialsList, options, mongoDriverInformation), options, credentialsList);
}
Mongo(final List seedList, final List credentialsList, final MongoClientOptions options) {
this(seedList, credentialsList, options, null);
}
Mongo(final List seedList, final List credentialsList, final MongoClientOptions options,
@Nullable final MongoDriverInformation mongoDriverInformation) {
this(createCluster(seedList, credentialsList, options, mongoDriverInformation), options, credentialsList);
}
Mongo(final MongoClientURI mongoURI) {
this(mongoURI, null);
}
Mongo(final MongoClientURI mongoURI, @Nullable final MongoDriverInformation mongoDriverInformation) {
this(createCluster(mongoURI, mongoDriverInformation), mongoURI.getOptions(),
mongoURI.getCredentials() != null ? asList(mongoURI.getCredentials()) : Collections.emptyList());
}
@SuppressWarnings("deprecation")
Mongo(final Cluster cluster, final MongoClientOptions options, final List credentialsList) {
this.options = options;
this.readPreference = options.getReadPreference();
this.writeConcern = options.getWriteConcern();
this.readConcern = options.getReadConcern();
this.optionHolder = new Bytes.OptionHolder(null);
this.credentialsList = unmodifiableList(credentialsList);
AutoEncryptionSettings autoEncryptionSettings = options.getAutoEncryptionSettings();
this.delegate = new MongoClientDelegate(cluster,
createRegistry(options.getCodecRegistry(), options.getUuidRepresentation()),
credentialsList, this,
autoEncryptionSettings == null ? null : createCrypt(asSimpleMongoClient(), autoEncryptionSettings));
cursorCleaningService = options.isCursorFinalizerEnabled() ? createCursorCleaningService() : null;
this.closed = new AtomicBoolean();
}
// bit of a hack, but it works because only MongoClient subclass will ever make use of this
SimpleMongoClient asSimpleMongoClient() {
throw new UnsupportedOperationException();
}
/**
* Sets the default write concern to use for write operations executed on any {@link DBCollection} created indirectly from this
* instance, via a {@link DB} instance created from {@link #getDB(String)}.
*
*
* Note that changes to the default write concern made via this method will NOT affect the write concern of
* {@link com.mongodb.client.MongoDatabase} instances created via {@link MongoClient#getDatabase(String)}
*
*
* @param writeConcern write concern to use
* @deprecated Set the default write concern with either {@link MongoClientURI} or {@link MongoClientOptions}
*/
@Deprecated
public void setWriteConcern(final WriteConcern writeConcern) {
this.writeConcern = writeConcern;
}
/**
* Gets the write concern
*
* @return the write concern
*/
public WriteConcern getWriteConcern() {
return writeConcern;
}
/**
* Gets the read concern
*
* @return the read concern
*/
public ReadConcern getReadConcern() {
return readConcern;
}
/**
* Sets the default read preference to use for reads operations executed on any {@link DBCollection} created indirectly from this
* instance, via a {@link DB} instance created from {@link #getDB(String)}.
*
*
* Note that changes to the default read preference made via this method will NOT affect the read preference of
* {@link com.mongodb.client.MongoDatabase} instances created via {@link MongoClient#getDatabase(String)}
*
* @param readPreference Read Preference to use
* @deprecated Set the default read preference with either {@link MongoClientURI} or {@link MongoClientOptions}
*/
@Deprecated
public void setReadPreference(final ReadPreference readPreference) {
this.readPreference = readPreference;
}
/**
* Gets the default read preference
*
* @return the default read preference
*/
public ReadPreference getReadPreference() {
return readPreference;
}
/**
* Gets a list of all server addresses used when this Mongo was created
*
* @return list of server addresses
* @throws MongoException if there's a failure
*/
@Deprecated
public List getAllAddress() {
return delegate.getCluster().getSettings().getHosts();
}
/**
* Gets the list of server addresses currently seen by this client. This includes addresses auto-discovered from a replica set.
*
* @return list of server addresses
* @throws MongoException if there's a failure
*/
@Deprecated
public List getServerAddressList() {
return delegate.getServerAddressList();
}
private ClusterDescription getClusterDescription() {
return delegate.getCluster().getDescription();
}
/**
* Gets the address of the current master
*
* @return the address
*/
@Deprecated
@SuppressWarnings("deprecation")
@Nullable
public ServerAddress getAddress() {
ClusterDescription description = getClusterDescription();
if (description.getPrimaries().isEmpty()) {
return null;
}
return description.getPrimaries().get(0).getAddress();
}
/**
* Returns the mongo options.
*
* Changes to {@code MongoOptions} that are done after connection are not reflected.
*
* @return the mongo options
* @deprecated Please use {@link MongoClient} class to connect to server and corresponding {@link
* com.mongodb.MongoClient#getMongoClientOptions()}
*/
@SuppressWarnings("deprecation")
@Deprecated
public MongoOptions getMongoOptions() {
return new MongoOptions(getMongoClientOptions());
}
/**
* Get the status of the replica set cluster.
*
* @return replica set status information
*/
@SuppressWarnings("deprecation")
@Deprecated
@Nullable
public ReplicaSetStatus getReplicaSetStatus() {
ClusterDescription clusterDescription = getClusterDescription();
return clusterDescription.getType() == REPLICA_SET && clusterDescription.getConnectionMode() == MULTIPLE
? new ReplicaSetStatus(delegate.getCluster()) : null; // this is intended behavior in 2.x
}
/**
* Gets a list of the names of all databases on the connected server.
*
* @return list of database names
* @throws MongoException if the operation fails
* @deprecated Replaced with {@link com.mongodb.MongoClient#listDatabaseNames()}
*/
@Deprecated
public List getDatabaseNames() {
return new MongoIterableImpl(null, createOperationExecutor(), ReadConcern.DEFAULT, primary(),
options.getRetryReads()) {
@Override
public ReadOperation> asReadOperation() {
return new ListDatabasesOperation(MongoClient.getCommandCodec());
}
}.map(new Function() {
@Override
public String apply(final DBObject result) {
return (String) result.get("name");
}
}).into(new ArrayList());
}
/**
* Gets a database object. Users should use {@link com.mongodb.MongoClient#getDatabase(String)} instead.
*
*
* The {@link DB} class has been superseded by {@link com.mongodb.client.MongoDatabase}. The deprecation of this method effectively
* deprecates the {@link DB}, {@link DBCollection}, and {@link DBCursor} classes, among others; but in order to give users time to
* migrate to the new API without experiencing a huge number of compiler warnings, those classes have not yet been formally
* deprecated.
*
*
* @param dbName the name of the database to retrieve
* @return a DB representing the specified database
* @throws IllegalArgumentException if the name is invalid
* @see MongoNamespace#checkDatabaseNameValidity(String)
* @deprecated This method is not currently scheduled for removal, but prefer {@link com.mongodb.MongoClient#getDatabase(String)} for
* new code. Note that {@link DB} and {@link com.mongodb.client.MongoDatabase} can be used together in the same application, whith the
* same {@link MongoClient} instance.
*/
@Deprecated // NOT CURRENTLY INTENDED FOR REMOVAL
public DB getDB(final String dbName) {
DB db = dbCache.get(dbName);
if (db != null) {
return db;
}
db = new DB(this, dbName, createOperationExecutor());
DB temp = dbCache.putIfAbsent(dbName, db);
if (temp != null) {
return temp;
}
return db;
}
/**
* Returns the list of databases used by the driver since this Mongo instance was created. This may include DBs that exist in the client
* but not yet on the server.
*
* @return a collection of database objects
*/
@Deprecated
public Collection getUsedDatabases() {
return dbCache.values();
}
/**
* Drops the database if it exists.
*
* @param dbName name of database to drop
* @throws MongoException if the operation fails
*/
public void dropDatabase(final String dbName) {
getDB(dbName).dropDatabase();
}
/**
* Closes all resources associated with this instance, in particular any open network connections. Once called, this instance and any
* databases obtained from it can no longer be used.
*/
public void close() {
if (!closed.getAndSet(true)) {
delegate.close();
if (cursorCleaningService != null) {
cursorCleaningService.shutdownNow();
}
}
}
/**
* Makes it possible to run read queries on secondary nodes
*
* @see ReadPreference#secondaryPreferred()
* @deprecated Replaced with {@code ReadPreference.secondaryPreferred()}
*/
@SuppressWarnings("deprecation")
@Deprecated
public void slaveOk() {
addOption(Bytes.QUERYOPTION_SLAVEOK);
}
/**
* Set the default query options for reads operations executed on any {@link DBCollection} created indirectly from this
* instance, via a {@link DB} instance created from {@link #getDB(String)}.
*
*
* Note that changes to query options made via this method will NOT affect
* {@link com.mongodb.client.MongoDatabase} instances created via {@link MongoClient#getDatabase(String)}
*
*
* @param options value to be set
* @deprecated Set options on instances of {@link DBCursor}
*/
@Deprecated
public void setOptions(final int options) {
optionHolder.set(options);
}
/**
* Reset the default query options for reads operations executed on any {@link DBCollection} created indirectly from this
* instance, via a {@link DB} instance created from {@link #getDB(String)}.
*
* @deprecated Reset options instead on instances of {@link DBCursor}
*/
@Deprecated
public void resetOptions() {
optionHolder.reset();
}
/**
* Add the default query option for reads operations executed on any {@link DBCollection} created indirectly from this
* instance, via a {@link DB} instance created from {@link #getDB(String)}.
*
*
* Note that changes to query options made via this method will NOT affect
* {@link com.mongodb.client.MongoDatabase} instances created via {@link MongoClient#getDatabase(String)}
*
*
* @param option value to be added to current options
* @deprecated Add options instead on instances of {@link DBCursor}
*/
@Deprecated
public void addOption(final int option) {
optionHolder.add(option);
}
/**
* Gets the default query options for reads operations executed on any {@link DBCollection} created indirectly from this
* instance, via a {@link DB} instance created from {@link #getDB(String)}.
*
* @return an int representing the options to be used by queries
* @deprecated Get options instead from instances of {@link DBCursor}
*/
@Deprecated
public int getOptions() {
return optionHolder.get();
}
/**
* Forces the master server to fsync the RAM data to disk This is done automatically by the server at intervals, but can be forced for
* better reliability.
*
* @param async if true, the fsync will be done asynchronously on the server.
* @return result of the command execution
* @throws MongoException if there's a failure
* @mongodb.driver.manual reference/command/fsync/ fsync command
*/
@Deprecated
public CommandResult fsync(final boolean async) {
DBObject command = new BasicDBObject("fsync", 1);
if (async) {
command.put("async", 1);
}
return getDB(ADMIN_DATABASE_NAME).command(command);
}
/**
* Forces the master server to fsync the RAM data to disk, then lock all writes. The database will be read-only after this command
* returns.
*
* @return result of the command execution
* @throws MongoException if there's a failure
* @mongodb.driver.manual reference/command/fsync/ fsync command
*/
@Deprecated
public CommandResult fsyncAndLock() {
DBObject command = new BasicDBObject("fsync", 1);
command.put("lock", 1);
return getDB(ADMIN_DATABASE_NAME).command(command);
}
/**
* Unlocks the database, allowing the write operations to go through. This command may be asynchronous on the server, which means there
* may be a small delay before the database becomes writable.
*
* @return {@code DBObject} in the following form {@code {"ok": 1,"info": "unlock completed"}}
* @throws MongoException if there's a failure
* @mongodb.driver.manual reference/command/fsync/ fsync command
*/
@Deprecated
public DBObject unlock() {
return DBObjects.toDBObject(createOperationExecutor().execute(new FsyncUnlockOperation(), readPreference, readConcern));
}
/**
* Returns true if the database is locked (read-only), false otherwise.
*
* @return result of the command execution
* @throws MongoException if the operation fails
* @mongodb.driver.manual reference/command/fsync/ fsync command
*/
@Deprecated
public boolean isLocked() {
return createOperationExecutor().execute(new CurrentOpOperation(), ReadPreference.primary(), readConcern)
.getBoolean("fsyncLock", BsonBoolean.FALSE).getValue();
}
@Override
public String toString() {
return "Mongo{"
+ "options=" + getMongoClientOptions()
+ '}';
}
/**
* Gets the maximum size for a BSON object supported by the current master server. Note that this value may change over time depending
* on which server is master.
*
* @return the maximum size, or 0 if not obtained from servers yet.
* @throws MongoException if there's a failure
*/
@Deprecated
@SuppressWarnings("deprecation")
public int getMaxBsonObjectSize() {
List primaries = getClusterDescription().getPrimaries();
return primaries.isEmpty() ? ServerDescription.getDefaultMaxDocumentSize() : primaries.get(0).getMaxDocumentSize();
}
/**
* Gets a {@code String} representation of current connection point, i.e. master.
*
* @return server address in a host:port form
*/
@Deprecated
@Nullable
public String getConnectPoint() {
ServerAddress master = getAddress();
return master != null ? String.format("%s:%d", master.getHost(), master.getPort()) : null;
}
private static MongoClientOptions createLegacyOptions() {
return MongoClientOptions.builder().legacyDefaults().build();
}
private static Cluster createCluster(final MongoClientURI mongoURI, @Nullable final MongoDriverInformation mongoDriverInformation) {
List credentialList = mongoURI.getCredentials() != null
? singletonList(mongoURI.getCredentials()) : Collections.emptyList();
return createCluster(getClusterSettings(ClusterSettings.builder().applyConnectionString(mongoURI.getProxied()),
mongoURI.getOptions()), credentialList, mongoURI.getOptions(), mongoDriverInformation);
}
private static Cluster createCluster(final List seedList,
final List credentialsList, final MongoClientOptions options,
@Nullable final MongoDriverInformation mongoDriverInformation) {
return createCluster(getClusterSettings(seedList, options, ClusterConnectionMode.MULTIPLE), credentialsList, options,
mongoDriverInformation);
}
private static Cluster createCluster(final ServerAddress serverAddress, final List credentialsList,
final MongoClientOptions options, @Nullable final MongoDriverInformation mongoDriverInformation) {
return createCluster(getClusterSettings(singletonList(serverAddress), options, getSingleServerClusterMode(options)),
credentialsList, options, mongoDriverInformation);
}
private static Cluster createCluster(final ClusterSettings clusterSettings, final List credentialsList,
final MongoClientOptions options, @Nullable final MongoDriverInformation mongoDriverInformation) {
MongoDriverInformation.Builder builder = mongoDriverInformation == null ? MongoDriverInformation.builder()
: MongoDriverInformation.builder(mongoDriverInformation);
return new DefaultClusterFactory().createCluster(clusterSettings,
options.getServerSettings(),
options.getConnectionPoolSettings(),
new SocketStreamFactory(options.getSocketSettings(),
options.getSslSettings(),
options.getSocketFactory()),
new SocketStreamFactory(options.getHeartbeatSocketSettings(),
options.getSslSettings(),
options.getSocketFactory()),
credentialsList,
getCommandListener(options.getCommandListeners()),
options.getApplicationName(),
builder.driverName("legacy").build(),
options.getCompressorList());
}
private static ClusterSettings getClusterSettings(final ClusterSettings.Builder builder, final MongoClientOptions options) {
builder.requiredReplicaSetName(options.getRequiredReplicaSetName())
.serverSelectionTimeout(options.getServerSelectionTimeout(), MILLISECONDS)
.localThreshold(options.getLocalThreshold(), MILLISECONDS)
.serverSelector(options.getServerSelector())
.description(options.getDescription())
.maxWaitQueueSize(options.getConnectionPoolSettings().getMaxWaitQueueSize());
for (ClusterListener clusterListener: options.getClusterListeners()) {
builder.addClusterListener(clusterListener);
}
return builder.build();
}
private static ClusterSettings getClusterSettings(final List seedList, final MongoClientOptions options,
final ClusterConnectionMode clusterConnectionMode) {
return getClusterSettings(ClusterSettings.builder()
.hosts(new ArrayList(seedList))
.mode(clusterConnectionMode), options);
}
Cluster getCluster() {
return delegate.getCluster();
}
MongoClientDelegate getDelegate() {
return delegate;
}
CodecRegistry getCodecRegistry() {
return delegate.getCodecRegistry();
}
ServerSessionPool getServerSessionPool() {
return delegate.getServerSessionPool();
}
@SuppressWarnings("deprecation")
Bytes.OptionHolder getOptionHolder() {
return optionHolder;
}
BufferProvider getBufferProvider() {
return bufferProvider;
}
MongoClientOptions getMongoClientOptions() {
return options;
}
List getCredentialsList() {
return credentialsList;
}
void addOrphanedCursor(final ServerCursor serverCursor, final MongoNamespace namespace) {
orphanedCursors.add(new ServerCursorAndNamespace(serverCursor, namespace));
}
OperationExecutor createOperationExecutor() {
return delegate.getOperationExecutor();
}
@Nullable
ClientSession createClientSession(final ClientSessionOptions options) {
return delegate.createClientSession(options, readConcern, writeConcern, readPreference);
}
private ExecutorService createCursorCleaningService() {
ScheduledExecutorService newTimer = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory("CleanCursors"));
newTimer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
cleanCursors();
}
}, 1, 1, SECONDS);
return newTimer;
}
private void cleanCursors() {
ServerCursorAndNamespace cur;
while ((cur = orphanedCursors.poll()) != null) {
ReadWriteBinding binding = new SingleServerBinding(delegate.getCluster(), cur.serverCursor.getAddress());
try {
ConnectionSource source = binding.getReadConnectionSource();
try {
Connection connection = source.getConnection();
try {
connection.killCursor(cur.namespace, singletonList(cur.serverCursor.getId()));
} finally {
connection.release();
}
} finally {
source.release();
}
} finally {
binding.release();
}
}
}
private static ClusterConnectionMode getSingleServerClusterMode(final MongoClientOptions options) {
if (options.getRequiredReplicaSetName() == null) {
return ClusterConnectionMode.SINGLE;
} else {
return ClusterConnectionMode.MULTIPLE;
}
}
private static class ServerCursorAndNamespace {
private final ServerCursor serverCursor;
private final MongoNamespace namespace;
ServerCursorAndNamespace(final ServerCursor serverCursor, final MongoNamespace namespace) {
this.serverCursor = serverCursor;
this.namespace = namespace;
}
}
/**
* Mongo.Holder can be used as a static place to hold several instances of Mongo. Security is not enforced at this level, and needs to
* be done on the application side.
*/
@Deprecated
public static class Holder {
private static final Holder INSTANCE = new Holder();
private final ConcurrentMap clients = new ConcurrentHashMap();
/**
* Get the only instance of {@code Holder}.
*
* @return the singleton instance of {@code Holder}
*/
public static Holder singleton() {
return INSTANCE;
}
/**
* Attempts to find an existing MongoClient instance matching that URI in the holder, and returns it if exists. Otherwise creates a
* new Mongo instance based on this URI and adds it to the holder.
*
* @param uri the Mongo URI
* @return the client
* @throws MongoException if there's a failure
* @deprecated Please use {@link #connect(MongoClientURI)} instead.
*/
@SuppressWarnings("deprecation")
@Deprecated
public Mongo connect(final MongoURI uri) {
return connect(uri.toClientURI());
}
/**
* Attempts to find an existing MongoClient instance matching that URI in the holder, and returns it if exists. Otherwise creates a
* new Mongo instance based on this URI and adds it to the holder.
*
* @param uri the Mongo URI
* @return the client
* @throws MongoException if there's a failure
*/
public Mongo connect(final MongoClientURI uri) {
String key = toKey(uri);
Mongo client = clients.get(key);
if (client == null) {
Mongo newbie = new MongoClient(uri);
client = clients.putIfAbsent(key, newbie);
if (client == null) {
client = newbie;
} else {
newbie.close();
}
}
return client;
}
private String toKey(final MongoClientURI uri) {
return uri.toString();
}
}
}