forked from mongodb/mongo-java-driver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMongoClient.java
894 lines (818 loc) · 36.9 KB
/
MongoClient.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
/*
* 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.client.ChangeStreamIterable;
import com.mongodb.client.ClientSession;
import com.mongodb.client.ListDatabasesIterable;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import com.mongodb.client.internal.Clusters;
import com.mongodb.client.internal.MongoClientImpl;
import com.mongodb.client.internal.OperationExecutor;
import com.mongodb.connection.ClusterConnectionMode;
import com.mongodb.connection.ClusterDescription;
import com.mongodb.connection.ClusterSettings;
import com.mongodb.event.ClusterListener;
import com.mongodb.internal.IgnorableRequestContext;
import com.mongodb.internal.TimeoutContext;
import com.mongodb.internal.TimeoutSettings;
import com.mongodb.internal.binding.ConnectionSource;
import com.mongodb.internal.binding.ReadWriteBinding;
import com.mongodb.internal.binding.SingleServerBinding;
import com.mongodb.internal.connection.Cluster;
import com.mongodb.internal.connection.Connection;
import com.mongodb.internal.connection.NoOpSessionContext;
import com.mongodb.internal.connection.OperationContext;
import com.mongodb.internal.connection.StreamFactoryFactory;
import com.mongodb.internal.diagnostics.logging.Logger;
import com.mongodb.internal.diagnostics.logging.Loggers;
import com.mongodb.internal.session.ServerSessionPool;
import com.mongodb.internal.thread.DaemonThreadFactory;
import com.mongodb.internal.validator.NoOpFieldNameValidator;
import com.mongodb.lang.Nullable;
import org.bson.BsonArray;
import org.bson.BsonDocument;
import org.bson.BsonInt64;
import org.bson.BsonString;
import org.bson.Document;
import org.bson.codecs.BsonDocumentCodec;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.conversions.Bson;
import java.io.Closeable;
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 java.util.stream.Collectors;
import static com.mongodb.assertions.Assertions.notNull;
import static com.mongodb.internal.connection.ClientMetadataHelper.createClientMetadataDocument;
import static com.mongodb.internal.connection.ServerAddressHelper.createServerAddress;
import static com.mongodb.internal.connection.ServerAddressHelper.getInetAddressResolver;
import static com.mongodb.internal.connection.StreamFactoryHelper.getSyncStreamFactoryFactory;
import static java.lang.String.format;
import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.SECONDS;
/**
* <p>A MongoDB client with internal connection pooling. For most applications, you should have one MongoClient instance for the entire
* JVM.
* <p>The following are equivalent, and all connect to the local database running on the default port:</p>
* <pre>
* new MongoClient()
* new MongoClient("mongodb://localhost")
* new MongoClient("mongodb://localhost:27017");
* new MongoClient(MongoClientSettings.builder()
* .applyConnectionString("mongodb://localhost")
* .build())
* </pre>
* <p>You can connect to a <a href="https://www.mongodb.com/docs/manual/replication/">replica set</a> by passing a
* list of servers to a MongoClient constructor. For example:</p>
* <pre>
* new MongoClient("mongodb://localhost:27017,localhost:27018,localhost:27019")
* new MongoClient(MongoClientSettings.builder()
* .applyConnectionString("mongodb://localhost:27017,localhost:27018,localhost:27019")
* .build())
* </pre>
* <p>You can connect to a sharded cluster using the same constructor invocations. MongoClient will auto-detect whether the servers are a
* list of replica set members or a list of mongos servers.</p>
*
* <p>By default, all read and write operations will be made on the primary, but it's possible to read from secondaries by changing the read
* preference:</p>
* <pre>
* new MongoClient("mongodb://localhost:27017,localhost:27018,localhost:27019?readPreference=primary")
* new MongoClient(MongoClientSettings.builder()
* .applyConnectionString("mongodb://localhost:27017,localhost:27018,localhost:27019/?readPreference=primary")
* .build())
* new MongoClient(MongoClientSettings.builder()
* .applyConnectionString("mongodb://localhost:27017,localhost:27018,localhost:27019")
* .readPreference(ReadPreference.primary())
* .build())
* </pre>
* <p>By default, all write operations will wait for acknowledgment by the server, as the default write concern is {@code
* WriteConcern.ACKNOWLEDGED}. It's possible to change this with a setting:</p>
* <pre>
* new MongoClient("mongodb://localhost:27017,localhost:27018,localhost:27019?w=majority")
* new MongoClient(MongoClientSettings.builder()
* .applyConnectionString("mongodb://localhost:27017,localhost:27018,localhost:27019/?w=majority")
* .build())
* new MongoClient(MongoClientSettings.builder()
* .applyConnectionString("mongodb://localhost:27017,localhost:27018,localhost:27019")
* .writeConcern(WriteConcern.MAJORITY)
* .build())
* </pre>
* <p>In general, users of this class will pick up all of the default options specified in {@code MongoClientSettings}.
*
* @see ConnectionString
* @see MongoClientSettings
* @since 2.10.0
*/
public class MongoClient implements Closeable {
private static final Logger LOGGER = Loggers.getLogger("client");
private final ConcurrentMap<String, DB> dbCache = new ConcurrentHashMap<>();
private final MongoClientOptions options;
private final ConcurrentLinkedQueue<ServerCursorAndNamespace> orphanedCursors = new ConcurrentLinkedQueue<>();
private final ExecutorService cursorCleaningService;
private final MongoClientImpl delegate;
private final AtomicBoolean closed;
/**
* Gets the default codec registry. It includes the following providers:
*
* <ul>
* <li>{@link org.bson.codecs.ValueCodecProvider}</li>
* <li>{@link org.bson.codecs.BsonValueCodecProvider}</li>
* <li>{@link com.mongodb.DBRefCodecProvider}</li>
* <li>{@link com.mongodb.DBObjectCodecProvider}</li>
* <li>{@link org.bson.codecs.DocumentCodecProvider}</li>
* <li>{@link org.bson.codecs.CollectionCodecProvider}</li>
* <li>{@link org.bson.codecs.IterableCodecProvider}</li>
* <li>{@link org.bson.codecs.MapCodecProvider}</li>
* <li>{@link com.mongodb.client.model.geojson.codecs.GeoJsonCodecProvider}</li>
* <li>{@link com.mongodb.client.gridfs.codecs.GridFSFileCodecProvider}</li>
* <li>{@link org.bson.codecs.jsr310.Jsr310CodecProvider}</li>
* <li>{@link org.bson.codecs.JsonObjectCodecProvider}</li>
* <li>{@link org.bson.codecs.BsonCodecProvider}</li>
* </ul>
*
* @return the default codec registry
* @see MongoClientOptions#getCodecRegistry()
* @see MongoClientSettings#getDefaultCodecRegistry()
* @since 3.0
*/
public static CodecRegistry getDefaultCodecRegistry() {
return com.mongodb.MongoClientSettings.getDefaultCodecRegistry();
}
/**
* Creates an instance based on a (single) MongoDB server ({@code "mongodb://127.0.0.1:27017"}).
*/
public MongoClient() {
this(new ConnectionString("mongodb://127.0.0.1"));
}
/**
* Creates a MongoClient instance based on a connection string.
*
* @param connectionString server to connect to in connection string format. For backwards compatibility, the
* {@code "mongodb://"} prefix can be omitted
* @see ConnectionString
*/
public MongoClient(final String connectionString) {
this(connectionString.contains("://")
? new ConnectionString(connectionString) : new ConnectionString("mongodb://" + connectionString));
}
/**
* Create a new client with the given connection string.
*
* <p>
* For each of the settings classed configurable via {@link MongoClientSettings}, the connection string is applied by calling the
* {@code applyConnectionString} method on an instance of setting's builder class, building the setting, and adding it to an instance of
* {@link com.mongodb.MongoClientSettings.Builder}.
* </p>
*
* @param connectionString the connection string
* @see com.mongodb.MongoClientSettings.Builder#applyConnectionString(ConnectionString)
* @since 4.2
*/
public MongoClient(final ConnectionString connectionString) {
this(connectionString, null);
}
/**
* Create a new client with the given connection string.
*
* <p>
* For each of the settings classed configurable via {@link MongoClientSettings}, the connection string is applied by calling the
* {@code applyConnectionString} method on an instance of setting's builder class, building the setting, and adding it to an instance of
* {@link com.mongodb.MongoClientSettings.Builder}.
* </p>
*
* <p>Note: Intended for driver and library authors to associate extra driver metadata with the connections.</p>
*
* @param connectionString the settings
* @param mongoDriverInformation any driver information to associate with the MongoClient
* @since 4.2
*/
public MongoClient(final ConnectionString connectionString,
@Nullable final MongoDriverInformation mongoDriverInformation) {
this(MongoClientSettings.builder().applyConnectionString(connectionString).build(), mongoDriverInformation);
}
/**
* Create a new client with the given client settings.
*
* @param settings the settings
* @since 4.2
*/
public MongoClient(final MongoClientSettings settings) {
this(settings, null);
}
/**
* Creates a new client with the given client settings.
*
* <p>Note: Intended for driver and library authors to associate extra driver metadata with the connections.</p>
*
* @param settings the settings
* @param mongoDriverInformation any driver information to associate with the MongoClient
* @since 4.2
*/
public MongoClient(final MongoClientSettings settings, @Nullable final MongoDriverInformation mongoDriverInformation) {
this(settings, null, mongoDriverInformation);
}
private MongoClient(final MongoClientSettings settings,
@Nullable final MongoClientOptions options,
@Nullable final MongoDriverInformation mongoDriverInformation) {
notNull("settings", settings);
MongoDriverInformation wrappedMongoDriverInformation = wrapMongoDriverInformation(mongoDriverInformation);
StreamFactoryFactory syncStreamFactoryFactory = getSyncStreamFactoryFactory(
settings.getTransportSettings(),
getInetAddressResolver(settings));
Cluster cluster = Clusters.createCluster(
settings,
wrappedMongoDriverInformation,
syncStreamFactoryFactory);
delegate = new MongoClientImpl(cluster, settings, wrappedMongoDriverInformation, syncStreamFactoryFactory);
this.options = options != null ? options : MongoClientOptions.builder(settings).build();
cursorCleaningService = this.options.isCursorFinalizerEnabled() ? createCursorCleaningService() : null;
this.closed = new AtomicBoolean();
BsonDocument clientMetadataDocument = createClientMetadataDocument(settings.getApplicationName(), mongoDriverInformation);
LOGGER.info(format("MongoClient with metadata %s created with settings %s", clientMetadataDocument.toJson(), settings));
}
private static MongoDriverInformation wrapMongoDriverInformation(@Nullable final MongoDriverInformation mongoDriverInformation) {
return (mongoDriverInformation == null ? MongoDriverInformation.builder() : MongoDriverInformation.builder(mongoDriverInformation))
.driverName("legacy").build();
}
/**
* Creates an instance based on a (single) mongodb node (default port).
*
* @param host server to connect to in format host[:port]
* @param options default query options
*/
public MongoClient(final String host, final MongoClientOptions options) {
this(createServerAddress(host), options);
}
/**
* Creates an instance based on a (single) mongodb node.
*
* @param host the database's host address
* @param port the port on which the database is running
*/
public MongoClient(final String host, final int port) {
this(createServerAddress(host, port));
}
/**
* Creates an instance based on a (single) mongodb node
*
* @param addr the database address
* @see com.mongodb.ServerAddress
*/
public MongoClient(final ServerAddress addr) {
this(addr, MongoClientOptions.builder().build());
}
/**
* Creates an instance based on a (single) mongo node using a given ServerAddress and default options.
*
* @param addr the database address
* @param options default options
* @see com.mongodb.ServerAddress
*/
public MongoClient(final ServerAddress addr, final MongoClientOptions options) {
this(addr, null, options);
}
/**
* Creates an instance based on a (single) mongo node using a given server address, credential, and options
*
* @param addr the database address
* @param credential the credential used to authenticate all connections
* @param options default options
* @see com.mongodb.ServerAddress
* @since 3.6
*/
public MongoClient(final ServerAddress addr, @Nullable final MongoCredential credential, final MongoClientOptions options) {
this(addr, credential, options, null);
}
/**
* <p>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 #MongoClient(ServerAddress)} constructor instead.</p>
*
* <p>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()}</p>
*
* @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()
*/
public MongoClient(final List<ServerAddress> seeds) {
this(seeds, MongoClientOptions.builder().build());
}
/**
* <p>Construct 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 #MongoClient(ServerAddress, MongoClientOptions)} constructor
* instead.</p>
*
* <p>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()}</p>
*
* @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()
*/
public MongoClient(final List<ServerAddress> seeds, final MongoClientOptions options) {
this(seeds, null, options);
}
/**
* <p>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 #MongoClient(ServerAddress, MongoCredential, MongoClientOptions)} constructor instead.</p>
*
* <p>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()}</p>
*
* @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 credential the credential used to authenticate all connections
* @param options the options
* @see MongoClientOptions#getLocalThreshold()
* @since 3.6
*/
public MongoClient(final List<ServerAddress> seeds, @Nullable final MongoCredential credential, final MongoClientOptions options) {
this(seeds, credential, options, null);
}
/**
* Creates an instance described by a URI. If only one address is used it will only connect to that node, otherwise it will discover all
* nodes.
*
* @param uri the URI
* @throws MongoException if theres a failure
*/
public MongoClient(final MongoClientURI uri) {
this(uri, null);
}
/**
* Creates an instance described by a URI.
*
* <p>Note: Intended for driver and library authors to associate extra driver metadata with the connections.</p>
*
* @param uri the URI
* @param mongoDriverInformation any driver information to associate with the MongoClient
* @throws MongoException if theres a failure
* @since 3.4
*/
public MongoClient(final MongoClientURI uri, @Nullable final MongoDriverInformation mongoDriverInformation) {
this(uri.getOptions().asMongoClientSettings(
uri.getProxied().isSrvProtocol()
? null : uri.getProxied().getHosts().stream().map(ServerAddress::new).collect(Collectors.toList()),
uri.getProxied().isSrvProtocol()
? uri.getProxied().getHosts().get(0) : null,
getClusterConnectionMode(uri.getProxied()),
uri.getCredentials()),
uri.getOptions(),
mongoDriverInformation);
}
private static ClusterConnectionMode getClusterConnectionMode(final ConnectionString connectionString) {
return ClusterSettings.builder().applyConnectionString(connectionString).build().getMode();
}
/**
* Creates a MongoClient to a single node using a given ServerAddress.
*
* <p>Note: Intended for driver and library authors to associate extra driver metadata with the connections.</p>
*
* @param addr the database address
* @param credential the credential used to authenticate all connections
* @param options default options
* @param mongoDriverInformation any driver information to associate with the MongoClient
* @see com.mongodb.ServerAddress
* @since 3.6
*/
public MongoClient(final ServerAddress addr, @Nullable final MongoCredential credential, final MongoClientOptions options,
@Nullable final MongoDriverInformation mongoDriverInformation) {
this(options.asMongoClientSettings(singletonList(addr), null, ClusterConnectionMode.SINGLE, credential), options,
mongoDriverInformation);
}
/**
* Creates a MongoClient
*
* <p>Note: Intended for driver and library authors to associate extra driver metadata with the connections.</p>
*
* @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 credential the credential used to authenticate all connections
* @param options the options
* @param mongoDriverInformation any driver information to associate with the MongoClient
* @since 3.6
*/
public MongoClient(final List<ServerAddress> seeds, @Nullable final MongoCredential credential, final MongoClientOptions options,
@Nullable final MongoDriverInformation mongoDriverInformation) {
this(options.asMongoClientSettings(seeds, null, ClusterConnectionMode.MULTIPLE, credential), options, mongoDriverInformation);
}
/**
* Gets the options that this client uses to connect to server.
*
* <p>Note: {@link MongoClientOptions} is immutable.</p>
*
* @return the options
*/
public MongoClientOptions getMongoClientOptions() {
return options;
}
/**
* Gets the credential that this client authenticates all connections with
*
* @return the credential, which may be null in unsecured deployments
* @since 3.9
*/
@Nullable
public MongoCredential getCredential() {
return delegate.getSettings().getCredential();
}
/**
* Get a list of the database names
*
* @return an iterable containing all the names of all the databases
* @mongodb.driver.manual reference/command/listDatabases List Databases
* @since 3.0
*/
public MongoIterable<String> listDatabaseNames() {
return delegate.listDatabaseNames();
}
/**
* Get a list of the database names
*
* @param clientSession the client session with which to associate this operation
* @return an iterable containing all the names of all the databases
* @mongodb.server.release 3.6
* @mongodb.driver.manual reference/command/listDatabases List Databases
* @since 3.6
*/
public MongoIterable<String> listDatabaseNames(final ClientSession clientSession) {
return delegate.listDatabaseNames(clientSession);
}
/**
* Gets the list of databases
*
* @return the list of databases
* @since 3.0
*/
public ListDatabasesIterable<Document> listDatabases() {
return delegate.listDatabases();
}
/**
* Gets the list of databases
*
* @param clazz the class to cast the database documents to
* @param <T> the type of the class to use instead of {@code Document}.
* @return the list of databases
* @since 3.0
*/
public <T> ListDatabasesIterable<T> listDatabases(final Class<T> clazz) {
return delegate.listDatabases(clazz);
}
/**
* Gets the list of databases
*
* @param clientSession the client session with which to associate this operation
* @return the list of databases
* @mongodb.server.release 3.6
* @since 3.6
*/
public ListDatabasesIterable<Document> listDatabases(final ClientSession clientSession) {
return delegate.listDatabases(clientSession);
}
/**
* Gets the list of databases
*
* @param clientSession the client session with which to associate this operation
* @param clazz the class to cast the database documents to
* @param <T> the type of the class to use instead of {@code Document}.
* @return the list of databases
* @mongodb.server.release 3.6
* @since 3.6
*/
public <T> ListDatabasesIterable<T> listDatabases(final ClientSession clientSession, final Class<T> clazz) {
return delegate.listDatabases(clientSession, clazz);
}
/**
* @param databaseName the name of the database to retrieve
* @return a {@code MongoDatabase} representing the specified database
* @throws IllegalArgumentException if databaseName is invalid
* @see MongoNamespace#checkDatabaseNameValidity(String)
*/
public MongoDatabase getDatabase(final String databaseName) {
return delegate.getDatabase(databaseName);
}
/**
* Creates a client session with default session options.
*
* @return the client session
* @throws MongoClientException if the MongoDB cluster to which this client is connected does not support sessions
* @mongodb.server.release 3.6
* @since 3.8
*/
public ClientSession startSession() {
return delegate.startSession();
}
/**
* Creates a client session.
*
* @param options the options for the client session
* @return the client session
* @throws MongoClientException if the MongoDB cluster to which this client is connected does not support sessions
* @mongodb.server.release 3.6
* @since 3.6
*/
public ClientSession startSession(final ClientSessionOptions options) {
return delegate.startSession(options);
}
/**
* Creates a change stream for this client.
*
* @return the change stream iterable
* @mongodb.server.release 4.0
* @mongodb.driver.dochub core/changestreams Change Streams
* @since 3.8
*/
public ChangeStreamIterable<Document> watch() {
return delegate.watch();
}
/**
* Creates a change stream for this client.
*
* @param resultClass the class to decode each document into
* @param <TResult> the target document type of the iterable.
* @return the change stream iterable
* @mongodb.server.release 4.0
* @mongodb.driver.dochub core/changestreams Change Streams
* @since 3.8
*/
public <TResult> ChangeStreamIterable<TResult> watch(final Class<TResult> resultClass) {
return delegate.watch(resultClass);
}
/**
* Creates a change stream for this client.
*
* @param pipeline the aggregation pipeline to apply to the change stream
* @return the change stream iterable
* @mongodb.server.release 4.0
* @mongodb.driver.dochub core/changestreams Change Streams
* @since 3.8
*/
public ChangeStreamIterable<Document> watch(final List<? extends Bson> pipeline) {
return delegate.watch(pipeline);
}
/**
* Creates a change stream for this client.
*
* @param pipeline the aggregation pipeline to apply to the change stream
* @param resultClass the class to decode each document into
* @param <TResult> the target document type of the iterable.
* @return the change stream iterable
* @mongodb.server.release 4.0
* @mongodb.driver.dochub core/changestreams Change Streams
* @since 3.8
*/
public <TResult> ChangeStreamIterable<TResult> watch(final List<? extends Bson> pipeline, final Class<TResult> resultClass) {
return delegate.watch(pipeline, resultClass);
}
/**
* Creates a change stream for this client.
*
* @param clientSession the client session with which to associate this operation
* @return the change stream iterable
* @mongodb.server.release 4.0
* @mongodb.driver.dochub core/changestreams Change Streams
* @since 3.8
*/
public ChangeStreamIterable<Document> watch(final ClientSession clientSession) {
return delegate.watch(clientSession);
}
/**
* Creates a change stream for this client.
*
* @param clientSession the client session with which to associate this operation
* @param resultClass the class to decode each document into
* @param <TResult> the target document type of the iterable.
* @return the change stream iterable
* @mongodb.server.release 4.0
* @mongodb.driver.dochub core/changestreams Change Streams
* @since 3.8
*/
public <TResult> ChangeStreamIterable<TResult> watch(final ClientSession clientSession, final Class<TResult> resultClass) {
return delegate.watch(clientSession, resultClass);
}
/**
* Creates a change stream for this client.
*
* @param clientSession the client session with which to associate this operation
* @param pipeline the aggregation pipeline to apply to the change stream
* @return the change stream iterable
* @mongodb.server.release 4.0
* @mongodb.driver.dochub core/changestreams Change Streams
* @since 3.8
*/
public ChangeStreamIterable<Document> watch(final ClientSession clientSession, final List<? extends Bson> pipeline) {
return delegate.watch(clientSession, pipeline);
}
/**
* Creates a change stream for this client.
*
* @param clientSession the client session with which to associate this operation
* @param pipeline the aggregation pipeline to apply to the change stream
* @param resultClass the class to decode each document into
* @param <TResult> the target document type of the iterable.
* @return the change stream iterable
* @mongodb.server.release 4.0
* @mongodb.driver.dochub core/changestreams Change Streams
* @since 3.8
*/
public <TResult> ChangeStreamIterable<TResult> watch(final ClientSession clientSession, final List<? extends Bson> pipeline,
final Class<TResult> resultClass) {
return delegate.watch(clientSession, pipeline, resultClass);
}
/**
* Gets the current cluster description.
*
* <p>
* This method will not block, meaning that it may return a {@link ClusterDescription} whose {@code clusterType} is unknown
* and whose {@link com.mongodb.connection.ServerDescription}s are all in the connecting state. If the application requires
* notifications after the driver has connected to a member of the cluster, it should register a {@link ClusterListener} via
* the {@link ClusterSettings} in {@link com.mongodb.MongoClientSettings}.
* </p>
*
* @return the current cluster description
* @see ClusterSettings.Builder#addClusterListener(ClusterListener)
* @see com.mongodb.MongoClientSettings.Builder#applyToClusterSettings(com.mongodb.Block)
* @since 4.2
*/
public ClusterDescription getClusterDescription() {
return delegate.getClusterDescription();
}
/**
* Gets the write concern
*
* @return the write concern
*/
public WriteConcern getWriteConcern() {
return options.getWriteConcern();
}
/**
* Gets the read concern
*
* @return the read concern
*/
public ReadConcern getReadConcern() {
return options.getReadConcern();
}
/**
* Gets the default read preference
*
* @return the default read preference
*/
public ReadPreference getReadPreference() {
return options.getReadPreference();
}
/**
* Gets a database object. Users should use {@link com.mongodb.MongoClient#getDatabase(String)} instead.
*
* <p>
* 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.
* </p>
*
* @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, with the
* same 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, getOperationExecutor());
DB temp = dbCache.putIfAbsent(dbName, db);
if (temp != null) {
return temp;
}
return db;
}
/**
* 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();
}
}
}
@Override
public String toString() {
return "MongoClient{"
+ "options=" + options
+ '}';
}
Cluster getCluster() {
return delegate.getCluster();
}
CodecRegistry getCodecRegistry() {
return delegate.getCodecRegistry();
}
ServerSessionPool getServerSessionPool() {
return delegate.getServerSessionPool();
}
@Nullable
ExecutorService getCursorCleaningService() {
return cursorCleaningService;
}
void addOrphanedCursor(final ServerCursor serverCursor, final MongoNamespace namespace) {
orphanedCursors.add(new ServerCursorAndNamespace(serverCursor, namespace));
}
// Leave as package-protected so that unit tests can spy on it.
OperationExecutor getOperationExecutor() {
return delegate.getOperationExecutor();
}
MongoClientImpl getDelegate() {
return delegate;
}
TimeoutSettings getTimeoutSettings() {
return delegate.getTimeoutSettings();
}
private ExecutorService createCursorCleaningService() {
ScheduledExecutorService newTimer = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory("CleanCursors"));
newTimer.scheduleAtFixedRate(this::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(),
new OperationContext(IgnorableRequestContext.INSTANCE, NoOpSessionContext.INSTANCE,
new TimeoutContext(getTimeoutSettings()), options.getServerApi()));
try {
ConnectionSource source = binding.getReadConnectionSource();
try {
Connection connection = source.getConnection();
try {
BsonDocument killCursorsCommand = new BsonDocument("killCursors", new BsonString(cur.namespace.getCollectionName()))
.append("cursors", new BsonArray(singletonList(new BsonInt64(cur.serverCursor.getId()))));
connection.command(cur.namespace.getDatabaseName(), killCursorsCommand, NoOpFieldNameValidator.INSTANCE,
ReadPreference.primary(), new BsonDocumentCodec(), source.getOperationContext());
} finally {
connection.release();
}
} finally {
source.release();
}
} finally {
binding.release();
}
}
}
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;
}
}
}