mongo 1.10.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/LICENSE +190 -0
  5. data/README.md +149 -0
  6. data/Rakefile +31 -0
  7. data/VERSION +1 -0
  8. data/bin/mongo_console +43 -0
  9. data/ext/jsasl/target/jsasl.jar +0 -0
  10. data/lib/mongo.rb +90 -0
  11. data/lib/mongo/bulk_write_collection_view.rb +380 -0
  12. data/lib/mongo/collection.rb +1164 -0
  13. data/lib/mongo/collection_writer.rb +364 -0
  14. data/lib/mongo/connection.rb +19 -0
  15. data/lib/mongo/connection/node.rb +239 -0
  16. data/lib/mongo/connection/pool.rb +347 -0
  17. data/lib/mongo/connection/pool_manager.rb +325 -0
  18. data/lib/mongo/connection/sharding_pool_manager.rb +67 -0
  19. data/lib/mongo/connection/socket.rb +18 -0
  20. data/lib/mongo/connection/socket/socket_util.rb +37 -0
  21. data/lib/mongo/connection/socket/ssl_socket.rb +95 -0
  22. data/lib/mongo/connection/socket/tcp_socket.rb +86 -0
  23. data/lib/mongo/connection/socket/unix_socket.rb +39 -0
  24. data/lib/mongo/cursor.rb +719 -0
  25. data/lib/mongo/db.rb +735 -0
  26. data/lib/mongo/exception.rb +88 -0
  27. data/lib/mongo/functional.rb +21 -0
  28. data/lib/mongo/functional/authentication.rb +318 -0
  29. data/lib/mongo/functional/logging.rb +85 -0
  30. data/lib/mongo/functional/read_preference.rb +174 -0
  31. data/lib/mongo/functional/sasl_java.rb +48 -0
  32. data/lib/mongo/functional/uri_parser.rb +374 -0
  33. data/lib/mongo/functional/write_concern.rb +66 -0
  34. data/lib/mongo/gridfs.rb +18 -0
  35. data/lib/mongo/gridfs/grid.rb +112 -0
  36. data/lib/mongo/gridfs/grid_ext.rb +53 -0
  37. data/lib/mongo/gridfs/grid_file_system.rb +163 -0
  38. data/lib/mongo/gridfs/grid_io.rb +484 -0
  39. data/lib/mongo/legacy.rb +140 -0
  40. data/lib/mongo/mongo_client.rb +702 -0
  41. data/lib/mongo/mongo_replica_set_client.rb +523 -0
  42. data/lib/mongo/mongo_sharded_client.rb +159 -0
  43. data/lib/mongo/networking.rb +370 -0
  44. data/lib/mongo/utils.rb +19 -0
  45. data/lib/mongo/utils/conversions.rb +110 -0
  46. data/lib/mongo/utils/core_ext.rb +70 -0
  47. data/lib/mongo/utils/server_version.rb +69 -0
  48. data/lib/mongo/utils/support.rb +80 -0
  49. data/lib/mongo/utils/thread_local_variable_manager.rb +25 -0
  50. data/mongo.gemspec +36 -0
  51. data/test/functional/authentication_test.rb +35 -0
  52. data/test/functional/bulk_api_stress_test.rb +133 -0
  53. data/test/functional/bulk_write_collection_view_test.rb +1129 -0
  54. data/test/functional/client_test.rb +565 -0
  55. data/test/functional/collection_test.rb +2073 -0
  56. data/test/functional/collection_writer_test.rb +83 -0
  57. data/test/functional/conversions_test.rb +163 -0
  58. data/test/functional/cursor_fail_test.rb +63 -0
  59. data/test/functional/cursor_message_test.rb +57 -0
  60. data/test/functional/cursor_test.rb +625 -0
  61. data/test/functional/db_api_test.rb +819 -0
  62. data/test/functional/db_connection_test.rb +27 -0
  63. data/test/functional/db_test.rb +344 -0
  64. data/test/functional/grid_file_system_test.rb +285 -0
  65. data/test/functional/grid_io_test.rb +252 -0
  66. data/test/functional/grid_test.rb +273 -0
  67. data/test/functional/pool_test.rb +62 -0
  68. data/test/functional/safe_test.rb +98 -0
  69. data/test/functional/ssl_test.rb +29 -0
  70. data/test/functional/support_test.rb +62 -0
  71. data/test/functional/timeout_test.rb +58 -0
  72. data/test/functional/uri_test.rb +330 -0
  73. data/test/functional/write_concern_test.rb +118 -0
  74. data/test/helpers/general.rb +50 -0
  75. data/test/helpers/test_unit.rb +317 -0
  76. data/test/replica_set/authentication_test.rb +35 -0
  77. data/test/replica_set/basic_test.rb +174 -0
  78. data/test/replica_set/client_test.rb +341 -0
  79. data/test/replica_set/complex_connect_test.rb +77 -0
  80. data/test/replica_set/connection_test.rb +138 -0
  81. data/test/replica_set/count_test.rb +64 -0
  82. data/test/replica_set/cursor_test.rb +212 -0
  83. data/test/replica_set/insert_test.rb +140 -0
  84. data/test/replica_set/max_values_test.rb +145 -0
  85. data/test/replica_set/pinning_test.rb +55 -0
  86. data/test/replica_set/query_test.rb +73 -0
  87. data/test/replica_set/read_preference_test.rb +214 -0
  88. data/test/replica_set/refresh_test.rb +175 -0
  89. data/test/replica_set/replication_ack_test.rb +94 -0
  90. data/test/replica_set/ssl_test.rb +32 -0
  91. data/test/sharded_cluster/basic_test.rb +197 -0
  92. data/test/shared/authentication/basic_auth_shared.rb +286 -0
  93. data/test/shared/authentication/bulk_api_auth_shared.rb +259 -0
  94. data/test/shared/authentication/gssapi_shared.rb +164 -0
  95. data/test/shared/authentication/sasl_plain_shared.rb +96 -0
  96. data/test/shared/ssl_shared.rb +235 -0
  97. data/test/test_helper.rb +56 -0
  98. data/test/threading/basic_test.rb +120 -0
  99. data/test/tools/mongo_config.rb +608 -0
  100. data/test/tools/mongo_config_test.rb +160 -0
  101. data/test/unit/client_test.rb +347 -0
  102. data/test/unit/collection_test.rb +166 -0
  103. data/test/unit/connection_test.rb +325 -0
  104. data/test/unit/cursor_test.rb +299 -0
  105. data/test/unit/db_test.rb +136 -0
  106. data/test/unit/grid_test.rb +76 -0
  107. data/test/unit/mongo_sharded_client_test.rb +48 -0
  108. data/test/unit/node_test.rb +93 -0
  109. data/test/unit/pool_manager_test.rb +142 -0
  110. data/test/unit/read_pref_test.rb +115 -0
  111. data/test/unit/read_test.rb +159 -0
  112. data/test/unit/safe_test.rb +158 -0
  113. data/test/unit/sharding_pool_manager_test.rb +84 -0
  114. data/test/unit/write_concern_test.rb +175 -0
  115. metadata +260 -0
  116. metadata.gz.sig +0 -0
@@ -0,0 +1,140 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module LegacyWriteConcern
17
+ @legacy_write_concern = true
18
+
19
+ def safe=(value)
20
+ @write_concern = value
21
+ end
22
+
23
+ def safe
24
+ if @write_concern[:w] == 0
25
+ return false
26
+ elsif @write_concern[:w] == 1
27
+ return true
28
+ else
29
+ return @write_concern
30
+ end
31
+ end
32
+
33
+ def self.from_uri(uri = ENV['MONGODB_URI'], extra_opts={})
34
+ parser = URIParser.new uri
35
+ parser.connection(extra_opts, true)
36
+ end
37
+ end
38
+ end
39
+
40
+ module Mongo
41
+ # @deprecated Use Mongo::MongoClient instead. Support will be removed after
42
+ # v2.0. Please see old documentation for the Connection class.
43
+ class Connection < MongoClient
44
+ include Mongo::LegacyWriteConcern
45
+
46
+ def initialize(*args)
47
+ if args.last.is_a?(Hash)
48
+ opts = args.pop
49
+ write_concern_from_legacy(opts)
50
+ args.push(opts)
51
+ end
52
+ super
53
+ end
54
+ end
55
+
56
+ # @deprecated Use Mongo::MongoReplicaSetClient instead. Support will be
57
+ # removed after v2.0. Please see old documentation for the
58
+ # ReplSetConnection class.
59
+ class ReplSetConnection < MongoReplicaSetClient
60
+ include Mongo::LegacyWriteConcern
61
+
62
+ def initialize(*args)
63
+ if args.last.is_a?(Hash)
64
+ opts = args.pop
65
+ write_concern_from_legacy(opts)
66
+ args.push(opts)
67
+ end
68
+ super
69
+ end
70
+ end
71
+
72
+ # @deprecated Use Mongo::MongoShardedClient instead. Support will be removed
73
+ # after v2.0. Please see old documentation for the ShardedConnection class.
74
+ class ShardedConnection < MongoShardedClient
75
+ include Mongo::LegacyWriteConcern
76
+
77
+ def initialize(*args)
78
+ if args.last.is_a?(Hash)
79
+ opts = args.pop
80
+ write_concern_from_legacy(opts)
81
+ args.push(opts)
82
+ end
83
+ super
84
+ end
85
+ end
86
+
87
+ class MongoClient
88
+ # @deprecated This method is no longer in use and never needs to be called
89
+ # directly. Support will be removed after v2.0
90
+ def authenticate_pools
91
+ @primary_pool.authenticate_existing
92
+ end
93
+
94
+ # @deprecated This method is no longer in use and never needs to be called
95
+ # directly. Support will be removed after v2.0
96
+ def logout_pools(database)
97
+ @primary_pool.logout_existing(database)
98
+ end
99
+
100
+ # @deprecated This method is no longer in use and never needs to be called
101
+ # directly. Support will be removed after v2.0
102
+ def apply_saved_authentication
103
+ true
104
+ end
105
+ end
106
+
107
+ class MongoReplicaSetClient
108
+ # @deprecated This method is no longer in use and never needs to be called
109
+ # directly. Support will be removed after v2.0
110
+ def authenticate_pools
111
+ @manager.pools.each { |pool| pool.authenticate_existing }
112
+ end
113
+
114
+ # @deprecated This method is no longer in use and never needs to be called
115
+ # directly. Support will be removed after v2.0
116
+ def logout_pools(database)
117
+ @manager.pools.each { |pool| pool.logout_existing(database) }
118
+ end
119
+ end
120
+
121
+ class DB
122
+ # @deprecated Please use MongoClient#issue_authentication instead. Support
123
+ # will be removed after v2.0
124
+ def issue_authentication(username, password, save_auth=true, opts={})
125
+ auth = Authentication.validate_credentials({
126
+ :db_name => self.name,
127
+ :username => username,
128
+ :password => password
129
+ })
130
+ opts[:save_auth] = save_auth
131
+ @client.issue_authentication(auth, opts)
132
+ end
133
+
134
+ # @deprecated Please use MongoClient#issue_logout instead. Support will be
135
+ # removed after v2.0
136
+ def issue_logout(opts={})
137
+ @client.issue_logout(self.name, opts)
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,702 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+
17
+ # Instantiates and manages self.connections to MongoDB.
18
+ class MongoClient
19
+ include Mongo::Logging
20
+ include Mongo::Networking
21
+ include Mongo::WriteConcern
22
+ include Mongo::Authentication
23
+
24
+ # Wire version
25
+ RELEASE_2_4_AND_BEFORE = 0 # Everything before we started tracking.
26
+ AGG_RETURNS_CURSORS = 1 # The aggregation command may now be requested to return cursors.
27
+ BATCH_COMMANDS = 2 # insert, update, and delete batch command
28
+ MAX_WIRE_VERSION = BATCH_COMMANDS # supported by this client implementation
29
+ MIN_WIRE_VERSION = RELEASE_2_4_AND_BEFORE # supported by this client implementation
30
+
31
+ # Server command headroom
32
+ COMMAND_HEADROOM = 16_384
33
+ APPEND_HEADROOM = COMMAND_HEADROOM / 2
34
+ SERIALIZE_HEADROOM = APPEND_HEADROOM / 2
35
+
36
+ DEFAULT_MAX_WRITE_BATCH_SIZE = 1000
37
+
38
+ Mutex = ::Mutex
39
+ ConditionVariable = ::ConditionVariable
40
+
41
+ DEFAULT_HOST = 'localhost'
42
+ DEFAULT_PORT = 27017
43
+ DEFAULT_DB_NAME = 'test'
44
+ GENERIC_OPTS = [:auths, :logger, :connect, :db_name]
45
+ TIMEOUT_OPTS = [:timeout, :op_timeout, :connect_timeout]
46
+ SSL_OPTS = [:ssl, :ssl_key, :ssl_cert, :ssl_verify, :ssl_ca_cert, :ssl_key_pass_phrase]
47
+ POOL_OPTS = [:pool_size, :pool_timeout]
48
+ READ_PREFERENCE_OPTS = [:read, :tag_sets, :secondary_acceptable_latency_ms]
49
+ WRITE_CONCERN_OPTS = [:w, :j, :fsync, :wtimeout]
50
+ CLIENT_ONLY_OPTS = [:slave_ok]
51
+
52
+ mongo_thread_local_accessor :connections
53
+
54
+ attr_reader :logger,
55
+ :size,
56
+ :auths,
57
+ :primary,
58
+ :write_concern,
59
+ :host_to_try,
60
+ :pool_size,
61
+ :connect_timeout,
62
+ :pool_timeout,
63
+ :primary_pool,
64
+ :socket_class,
65
+ :socket_opts,
66
+ :op_timeout,
67
+ :tag_sets,
68
+ :acceptable_latency,
69
+ :read,
70
+ :max_wire_version,
71
+ :min_wire_version,
72
+ :max_write_batch_size
73
+
74
+ # Create a connection to single MongoDB instance.
75
+ #
76
+ # If no args are provided, it will check <code>ENV["MONGODB_URI"]</code>.
77
+ #
78
+ # You may specify whether connection to slave is permitted.
79
+ # In all cases, the default host is "localhost" and the default port is 27017.
80
+ #
81
+ # If you're connecting to a replica set, you'll need to use MongoReplicaSetClient.new instead.
82
+ #
83
+ # Once connected to a replica set, you can find out which nodes are primary, secondary, and
84
+ # arbiters with the corresponding accessors: MongoClient#primary, MongoClient#secondaries, and
85
+ # MongoClient#arbiters. This is useful if your application needs to connect manually to nodes other
86
+ # than the primary.
87
+ #
88
+ # @overload initialize(host, port, opts={})
89
+ # @param [String] host hostname for the target MongoDB server.
90
+ # @param [Integer] port specify a port number here if only one host is being specified.
91
+ # @param [Hash] opts hash of optional settings and configuration values.
92
+ #
93
+ # @option opts [String, Integer, Symbol] :w (1) Set default number of nodes to which a write
94
+ # should be acknowledged.
95
+ # @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout.
96
+ # @option opts [Boolean] :j (false) If true, block until write operations have been committed
97
+ # to the journal. Cannot be used in combination with 'fsync'. Prior to MongoDB 2.6 this option was
98
+ # ignored if the server was running without journaling. Starting with MongoDB 2.6, write operations will
99
+ # fail with an exception if this option is used when the server is running without journaling.
100
+ # @option opts [Boolean] :fsync (false) If true, and the server is running without journaling, blocks until
101
+ # the server has synced all data files to disk. If the server is running with journaling, this acts the same as
102
+ # the 'j' option, blocking until write operations have been committed to the journal.
103
+ # Cannot be used in combination with 'j'.
104
+ #
105
+ # Notes about Write-Concern Options:
106
+ # Write concern options are propagated to objects instantiated from this MongoClient.
107
+ # These defaults can be overridden upon instantiation of any object by explicitly setting an options hash
108
+ # on initialization.
109
+ #
110
+ # @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
111
+ # @option opts [String] :ssl_cert (nil) The certificate file used to identify the local connection against MongoDB.
112
+ # @option opts [String] :ssl_key (nil) The private keyfile used to identify the local connection against MongoDB.
113
+ # Note that even if the key is stored in the same file as the certificate, both need to be explicitly specified.
114
+ # @option opts [String] :ssl_key_pass_phrase (nil) A passphrase for the private key.
115
+ # @option opts [Boolean] :ssl_verify (nil) Specifies whether or not peer certification validation should occur.
116
+ # @option opts [String] :ssl_ca_cert (nil) The ca_certs file contains a set of concatenated "certification authority"
117
+ # certificates, which are used to validate certificates passed from the other end of the connection.
118
+ # Required for :ssl_verify.
119
+ # @option opts [Boolean] :slave_ok (false) Must be set to +true+ when connecting
120
+ # to a single, slave node.
121
+ # @option opts [Logger, #debug] :logger (nil) A Logger instance for debugging driver ops. Note that
122
+ # logging negatively impacts performance; therefore, it should not be used for high-performance apps.
123
+ # @option opts [Integer] :pool_size (1) The maximum number of socket self.connections allowed per
124
+ # connection pool. Note: this setting is relevant only for multi-threaded applications.
125
+ # @option opts [Float] :pool_timeout (5.0) When all of the self.connections a pool are checked out,
126
+ # this is the number of seconds to wait for a new connection to be released before throwing an exception.
127
+ # Note: this setting is relevant only for multi-threaded applications.
128
+ # @option opts [Float] :op_timeout (nil) The number of seconds to wait for a read operation to time out.
129
+ # Disabled by default.
130
+ # @option opts [Float] :connect_timeout (nil) The number of seconds to wait before timing out a
131
+ # connection attempt.
132
+ #
133
+ # @example localhost, 27017 (or <code>ENV["MONGODB_URI"]</code> if available)
134
+ # MongoClient.new
135
+ #
136
+ # @example localhost, 27017
137
+ # MongoClient.new("localhost")
138
+ #
139
+ # @example localhost, 3000, max 5 self.connections, with max 5 seconds of wait time.
140
+ # MongoClient.new("localhost", 3000, :pool_size => 5, :pool_timeout => 5)
141
+ #
142
+ # @example localhost, 3000, where this node may be a slave
143
+ # MongoClient.new("localhost", 3000, :slave_ok => true)
144
+ #
145
+ # @example Unix Domain Socket
146
+ # MongoClient.new("/var/run/mongodb.sock")
147
+ #
148
+ # @see http://api.mongodb.org/ruby/current/file.REPLICA_SETS.html Replica sets in Ruby
149
+ #
150
+ # @raise [ReplicaSetConnectionError] This is raised if a replica set name is specified and the
151
+ # driver fails to connect to a replica set with that name.
152
+ #
153
+ # @raise [MongoArgumentError] If called with no arguments and <code>ENV["MONGODB_URI"]</code> implies a replica set.
154
+ def initialize(*args)
155
+ opts = args.last.is_a?(Hash) ? args.pop : {}
156
+ @host, @port = parse_init(args[0], args[1], opts)
157
+
158
+ # Lock for request ids.
159
+ @id_lock = Mutex.new
160
+
161
+ # Connection pool for primary node
162
+ @primary = nil
163
+ @primary_pool = nil
164
+ @mongos = false
165
+
166
+ # Not set for direct connection
167
+ @tag_sets = []
168
+ @acceptable_latency = 15
169
+
170
+ @max_bson_size = nil
171
+ @max_message_size = nil
172
+ @max_wire_version = nil
173
+ @min_wire_version = nil
174
+ @max_write_batch_size = nil
175
+
176
+ check_opts(opts)
177
+ setup(opts.dup)
178
+ end
179
+
180
+ # DEPRECATED
181
+ #
182
+ # Initialize a connection to a MongoDB replica set using an array of seed nodes.
183
+ #
184
+ # The seed nodes specified will be used on the initial connection to the replica set, but note
185
+ # that this list of nodes will be replaced by the list of canonical nodes returned by running the
186
+ # is_master command on the replica set.
187
+ #
188
+ # @param nodes [Array] An array of arrays, each of which specifies a host and port.
189
+ # @param opts [Hash] Any of the available options that can be passed to MongoClient.new.
190
+ #
191
+ # @option opts [String] :rs_name (nil) The name of the replica set to connect to. An exception will be
192
+ # raised if unable to connect to a replica set with this name.
193
+ # @option opts [Boolean] :read_secondary (false) When true, this connection object will pick a random slave
194
+ # to send reads to.
195
+ #
196
+ # @example
197
+ # Mongo::MongoClient.multi([["db1.example.com", 27017], ["db2.example.com", 27017]])
198
+ #
199
+ # @example This connection will read from a random secondary node.
200
+ # Mongo::MongoClient.multi([["db1.example.com", 27017], ["db2.example.com", 27017], ["db3.example.com", 27017]],
201
+ # :read_secondary => true)
202
+ #
203
+ # @return [Mongo::MongoClient]
204
+ #
205
+ # @deprecated
206
+ def self.multi(nodes, opts={})
207
+ warn 'MongoClient.multi is now deprecated and will be removed in v2.0. Please use MongoReplicaSetClient.new instead.'
208
+ MongoReplicaSetClient.new(nodes, opts)
209
+ end
210
+
211
+ # Initialize a connection to MongoDB using the MongoDB URI spec.
212
+ #
213
+ # Since MongoClient.new cannot be used with any <code>ENV["MONGODB_URI"]</code> that has multiple hosts (implying a replicaset),
214
+ # you may use this when the type of your connection varies by environment and should be determined solely from <code>ENV["MONGODB_URI"]</code>.
215
+ #
216
+ # @param uri [String]
217
+ # A string of the format mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]
218
+ #
219
+ # @param [Hash] extra_opts Any of the options available for MongoClient.new
220
+ #
221
+ # @return [Mongo::MongoClient, Mongo::MongoReplicaSetClient]
222
+ def self.from_uri(uri = ENV['MONGODB_URI'], extra_opts={})
223
+ parser = URIParser.new(uri)
224
+ parser.connection(extra_opts)
225
+ end
226
+
227
+ # The host name used for this connection.
228
+ #
229
+ # @return [String]
230
+ def host
231
+ @primary_pool.host
232
+ end
233
+
234
+ # The port used for this connection.
235
+ #
236
+ # @return [Integer]
237
+ def port
238
+ @primary_pool.port
239
+ end
240
+
241
+ def host_port
242
+ [@host, @port]
243
+ end
244
+
245
+ # Flush all pending writes to datafiles.
246
+ #
247
+ # @return [BSON::OrderedHash] the command response
248
+ def lock!
249
+ cmd = BSON::OrderedHash.new
250
+ cmd[:fsync] = 1
251
+ cmd[:lock] = true
252
+ self['admin'].command(cmd)
253
+ end
254
+
255
+ # Is this database locked against writes?
256
+ #
257
+ # @return [Boolean]
258
+ def locked?
259
+ [1, true].include? self['admin']['$cmd.sys.inprog'].find_one['fsyncLock']
260
+ end
261
+
262
+ # Unlock a previously fsync-locked mongod process.
263
+ #
264
+ # @return [BSON::OrderedHash] command response
265
+ def unlock!
266
+ self['admin']['$cmd.sys.unlock'].find_one
267
+ end
268
+
269
+ # Return a hash with all database names
270
+ # and their respective sizes on disk.
271
+ #
272
+ # @return [Hash]
273
+ def database_info
274
+ doc = self['admin'].command({:listDatabases => 1})
275
+ doc['databases'].inject({}) do |info, db|
276
+ info[db['name']] = db['sizeOnDisk'].to_i
277
+ info
278
+ end
279
+ end
280
+
281
+ # Return an array of database names.
282
+ #
283
+ # @return [Array]
284
+ def database_names
285
+ database_info.keys
286
+ end
287
+
288
+ # Return a database with the given name.
289
+ # See DB#new for valid options hash parameters.
290
+ #
291
+ # @param name [String] The name of the database.
292
+ # @param opts [Hash] A hash of options to be passed to the DB constructor.
293
+ #
294
+ # @return [DB] The DB instance.
295
+ def db(name = nil, opts = {})
296
+ DB.new(name || @db_name || DEFAULT_DB_NAME, self, opts)
297
+ end
298
+
299
+ # Shortcut for returning a database. Use MongoClient#db to accept options.
300
+ #
301
+ # @param name [String] The name of the database.
302
+ #
303
+ # @return [DB] The DB instance.
304
+ def [](name)
305
+ DB.new(name, self)
306
+ end
307
+
308
+ def refresh; end
309
+
310
+ def pinned_pool
311
+ @primary_pool
312
+ end
313
+
314
+ def pin_pool(pool, read_prefs); end
315
+
316
+ def unpin_pool; end
317
+
318
+ # Drop a database.
319
+ #
320
+ # @param database [String] name of an existing database.
321
+ def drop_database(database)
322
+ self[database].command(:dropDatabase => 1)
323
+ end
324
+
325
+ # Copy the database +from+ to +to+ on localhost. The +from+ database is
326
+ # assumed to be on localhost, but an alternate host can be specified.
327
+ #
328
+ # @param from [String] name of the database to copy from.
329
+ # @param to [String] name of the database to copy to.
330
+ # @param from_host [String] host of the 'from' database.
331
+ # @param username [String] username (applies to 'from' db)
332
+ # @param password [String] password (applies to 'from' db)
333
+ #
334
+ # @note This command only supports the MONGODB-CR authentication mechanism.
335
+ def copy_database(from, to, from_host=DEFAULT_HOST, username=nil, password=nil)
336
+ oh = BSON::OrderedHash.new
337
+ oh[:copydb] = 1
338
+ oh[:fromhost] = from_host
339
+ oh[:fromdb] = from
340
+ oh[:todb] = to
341
+ if username || password
342
+ unless username && password
343
+ raise MongoArgumentError,
344
+ 'Both username and password must be supplied for authentication.'
345
+ end
346
+ nonce_cmd = BSON::OrderedHash.new
347
+ nonce_cmd[:copydbgetnonce] = 1
348
+ nonce_cmd[:fromhost] = from_host
349
+ result = self['admin'].command(nonce_cmd)
350
+ oh[:nonce] = result['nonce']
351
+ oh[:username] = username
352
+ oh[:key] = Mongo::Authentication.auth_key(username, password, oh[:nonce])
353
+ end
354
+ self['admin'].command(oh)
355
+ end
356
+
357
+ # Checks if a server is alive. This command will return immediately
358
+ # even if the server is in a lock.
359
+ #
360
+ # @return [Hash]
361
+ def ping
362
+ self['admin'].command({:ping => 1})
363
+ end
364
+
365
+ # Get the build information for the current connection.
366
+ #
367
+ # @return [Hash]
368
+ def server_info
369
+ self['admin'].command({:buildinfo => 1})
370
+ end
371
+
372
+ # Get the build version of the current server.
373
+ #
374
+ # @return [Mongo::ServerVersion]
375
+ # object allowing easy comparability of version.
376
+ def server_version
377
+ ServerVersion.new(server_info['version'])
378
+ end
379
+
380
+ # Is it okay to connect to a slave?
381
+ #
382
+ # @return [Boolean]
383
+ def slave_ok?
384
+ @slave_ok
385
+ end
386
+
387
+ def mongos?
388
+ @mongos
389
+ end
390
+
391
+ # Create a new socket and attempt to connect to master.
392
+ # If successful, sets host and port to master and returns the socket.
393
+ #
394
+ # If connecting to a replica set, this method will replace the
395
+ # initially-provided seed list with any nodes known to the set.
396
+ #
397
+ # @raise [ConnectionFailure] if unable to connect to any host or port.
398
+ def connect
399
+ close
400
+ config = check_is_master(host_port)
401
+ if config
402
+ if config['ismaster'] == 1 || config['ismaster'] == true
403
+ @read_primary = true
404
+ elsif @slave_ok
405
+ @read_primary = false
406
+ end
407
+
408
+ if config.has_key?('msg') && config['msg'] == 'isdbgrid'
409
+ @mongos = true
410
+ end
411
+
412
+ @max_bson_size = config['maxBsonObjectSize']
413
+ @max_message_size = config['maxMessageSizeBytes']
414
+ @max_wire_version = config['maxWireVersion']
415
+ @min_wire_version = config['minWireVersion']
416
+ @max_write_batch_size = config['maxWriteBatchSize']
417
+ check_wire_version_in_range
418
+ set_primary(host_port)
419
+ end
420
+
421
+ unless connected?
422
+ raise ConnectionFailure,
423
+ "Failed to connect to a master node at #{host_port.join(":")}"
424
+ end
425
+
426
+ true
427
+ end
428
+ alias :reconnect :connect
429
+
430
+ # It's possible that we defined connected as all nodes being connected???
431
+ # NOTE: Do check if this needs to be more stringent.
432
+ # Probably not since if any node raises a connection failure, all nodes will be closed.
433
+ def connected?
434
+ !!(@primary_pool && !@primary_pool.closed?)
435
+ end
436
+
437
+ # Determine if the connection is active. In a normal case the *server_info* operation
438
+ # will be performed without issues, but if the connection was dropped by the server or
439
+ # for some reason the sockets are unsynchronized, a ConnectionFailure will be raised and
440
+ # the return will be false.
441
+ #
442
+ # @return [Boolean]
443
+ def active?
444
+ return false unless connected?
445
+
446
+ ping
447
+ true
448
+
449
+ rescue ConnectionFailure
450
+ false
451
+ end
452
+
453
+ # Determine whether we're reading from a primary node. If false,
454
+ # this connection connects to a secondary node and @slave_ok is true.
455
+ #
456
+ # @return [Boolean]
457
+ def read_primary?
458
+ @read_primary
459
+ end
460
+ alias :primary? :read_primary?
461
+
462
+ # The socket pool that this connection reads from.
463
+ #
464
+ # @return [Mongo::Pool]
465
+ def read_pool
466
+ @primary_pool
467
+ end
468
+
469
+ # Close the connection to the database.
470
+ def close
471
+ @primary_pool.close if @primary_pool
472
+ @primary_pool = nil
473
+ @primary = nil
474
+ end
475
+
476
+ # Returns the maximum BSON object size as returned by the core server.
477
+ # Use the 4MB default when the server doesn't report this.
478
+ #
479
+ # @return [Integer]
480
+ def max_bson_size
481
+ @max_bson_size || DEFAULT_MAX_BSON_SIZE
482
+ end
483
+
484
+ def max_message_size
485
+ @max_message_size || max_bson_size * MESSAGE_SIZE_FACTOR
486
+ end
487
+
488
+ def max_wire_version
489
+ @max_wire_version || 0
490
+ end
491
+
492
+ def min_wire_version
493
+ @min_wire_version || 0
494
+ end
495
+
496
+ def max_write_batch_size
497
+ @max_write_batch_size || DEFAULT_MAX_WRITE_BATCH_SIZE
498
+ end
499
+
500
+ def wire_version_feature?(feature)
501
+ min_wire_version <= feature && feature <= max_wire_version
502
+ end
503
+
504
+ def primary_wire_version_feature?(feature)
505
+ min_wire_version <= feature && feature <= max_wire_version
506
+ end
507
+
508
+ def use_write_command?(write_concern)
509
+ write_concern[:w] != 0 && primary_wire_version_feature?(Mongo::MongoClient::BATCH_COMMANDS)
510
+ end
511
+
512
+ # Checkout a socket for reading (i.e., a secondary node).
513
+ # Note: this is overridden in MongoReplicaSetClient.
514
+ def checkout_reader(read_preference)
515
+ connect unless connected?
516
+ @primary_pool.checkout
517
+ end
518
+
519
+ # Checkout a socket for writing (i.e., a primary node).
520
+ # Note: this is overridden in MongoReplicaSetClient.
521
+ def checkout_writer
522
+ connect unless connected?
523
+ @primary_pool.checkout
524
+ end
525
+
526
+ # Check a socket back into its pool.
527
+ # Note: this is overridden in MongoReplicaSetClient.
528
+ def checkin(socket)
529
+ if @primary_pool && socket && socket.pool
530
+ socket.checkin
531
+ end
532
+ end
533
+
534
+ # Internal method for checking isMaster() on a given node.
535
+ #
536
+ # @param node [Array] Port and host for the target node
537
+ # @return [Hash] Response from isMaster()
538
+ #
539
+ # @private
540
+ def check_is_master(node)
541
+ begin
542
+ host, port = *node
543
+ config = nil
544
+ socket = @socket_class.new(host, port, @op_timeout, @connect_timeout, @socket_opts)
545
+ if @connect_timeout
546
+ Timeout::timeout(@connect_timeout, OperationTimeout) do
547
+ config = self['admin'].command({:isMaster => 1}, :socket => socket)
548
+ end
549
+ else
550
+ config = self['admin'].command({:isMaster => 1}, :socket => socket)
551
+ end
552
+ rescue OperationFailure, SocketError, SystemCallError, IOError
553
+ close
554
+ ensure
555
+ socket.close unless socket.nil? || socket.closed?
556
+ end
557
+ config
558
+ end
559
+
560
+ protected
561
+
562
+ def valid_opts
563
+ GENERIC_OPTS +
564
+ CLIENT_ONLY_OPTS +
565
+ POOL_OPTS +
566
+ READ_PREFERENCE_OPTS +
567
+ WRITE_CONCERN_OPTS +
568
+ TIMEOUT_OPTS +
569
+ SSL_OPTS
570
+ end
571
+
572
+ def check_opts(opts)
573
+ bad_opts = opts.keys.reject { |opt| valid_opts.include?(opt) }
574
+
575
+ unless bad_opts.empty?
576
+ bad_opts.each {|opt| warn "#{opt} is not a valid option for #{self.class}"}
577
+ end
578
+ end
579
+
580
+ # Parse option hash
581
+ def setup(opts)
582
+ @slave_ok = opts.delete(:slave_ok)
583
+ @ssl = opts.delete(:ssl)
584
+ @unix = @host ? @host.end_with?('.sock') : false
585
+
586
+ # if ssl options are present, but ssl is nil/false raise for misconfig
587
+ ssl_opts = opts.keys.select { |k| k.to_s.start_with?('ssl') }
588
+ if ssl_opts.size > 0 && !@ssl
589
+ raise MongoArgumentError, "SSL has not been enabled (:ssl=false) " +
590
+ "but the following SSL related options were " +
591
+ "specified: #{ssl_opts.join(', ')}"
592
+ end
593
+
594
+ @socket_opts = {}
595
+ if @ssl
596
+ # construct ssl socket opts
597
+ @socket_opts[:key] = opts.delete(:ssl_key)
598
+ @socket_opts[:cert] = opts.delete(:ssl_cert)
599
+ @socket_opts[:verify] = opts.delete(:ssl_verify)
600
+ @socket_opts[:ca_cert] = opts.delete(:ssl_ca_cert)
601
+ @socket_opts[:key_pass_phrase] = opts.delete(:ssl_key_pass_phrase)
602
+
603
+ # verify peer requires ca_cert, raise if only one is present
604
+ if @socket_opts[:verify] && !@socket_opts[:ca_cert]
605
+ raise MongoArgumentError,
606
+ 'If :ssl_verify_mode has been specified, then you must include ' +
607
+ ':ssl_ca_cert in order to perform server validation.'
608
+ end
609
+
610
+ # if we have a keyfile passphrase but no key file, raise
611
+ if @socket_opts[:key_pass_phrase] && !@socket_opts[:key]
612
+ raise MongoArgumentError,
613
+ 'If :ssl_key_pass_phrase has been specified, then you must include ' +
614
+ ':ssl_key, the passphrase-protected keyfile.'
615
+ end
616
+
617
+ @socket_class = Mongo::SSLSocket
618
+ elsif @unix
619
+ @socket_class = Mongo::UNIXSocket
620
+ else
621
+ @socket_class = Mongo::TCPSocket
622
+ end
623
+
624
+ @db_name = opts.delete(:db_name)
625
+ @auths = opts.delete(:auths) || Set.new
626
+
627
+ # Pool size and timeout.
628
+ @pool_size = opts.delete(:pool_size) || 1
629
+ if opts[:timeout]
630
+ warn 'The :timeout option has been deprecated ' +
631
+ 'and will be removed in the 2.0 release. ' +
632
+ 'Use :pool_timeout instead.'
633
+ end
634
+ @pool_timeout = opts.delete(:pool_timeout) || opts.delete(:timeout) || 5.0
635
+
636
+ # Timeout on socket read operation.
637
+ @op_timeout = opts.delete(:op_timeout)
638
+
639
+ # Timeout on socket connect.
640
+ @connect_timeout = opts.delete(:connect_timeout) || 30
641
+
642
+ @logger = opts.delete(:logger)
643
+ if @logger
644
+ write_logging_startup_message
645
+ end
646
+
647
+ # Determine read preference
648
+ if defined?(@slave_ok) && (@slave_ok) || defined?(@read_secondary) && @read_secondary
649
+ @read = :secondary_preferred
650
+ else
651
+ @read = opts.delete(:read) || :primary
652
+ end
653
+ Mongo::ReadPreference::validate(@read)
654
+
655
+ @tag_sets = opts.delete(:tag_sets) || []
656
+ @acceptable_latency = opts.delete(:secondary_acceptable_latency_ms) || 15
657
+
658
+ # Connection level write concern options.
659
+ @write_concern = get_write_concern(opts)
660
+
661
+ connect if opts.fetch(:connect, true)
662
+ end
663
+
664
+ private
665
+
666
+ # Parses client initialization info from MONGODB_URI env variable
667
+ def parse_init(host, port, opts)
668
+ if host.nil? && port.nil? && ENV.has_key?('MONGODB_URI')
669
+ parser = URIParser.new(ENV['MONGODB_URI'])
670
+ if parser.replicaset?
671
+ raise MongoArgumentError,
672
+ 'ENV[\'MONGODB_URI\'] implies a replica set.'
673
+ end
674
+ opts.merge!(parser.connection_options)
675
+ [parser.host, parser.port]
676
+ else
677
+ host = host[1...-1] if host && host[0,1] == '[' # ipv6 support
678
+ [host || DEFAULT_HOST, port || DEFAULT_PORT]
679
+ end
680
+ end
681
+
682
+ # Set the specified node as primary
683
+ def set_primary(node)
684
+ host, port = *node
685
+ @primary = [host, port]
686
+ @primary_pool = Pool.new(self, host, port, :size => @pool_size, :timeout => @pool_timeout)
687
+ end
688
+
689
+ # calculate wire version in range
690
+ def check_wire_version_in_range
691
+ unless MIN_WIRE_VERSION <= max_wire_version &&
692
+ MAX_WIRE_VERSION >= min_wire_version
693
+ close
694
+ raise ConnectionFailure,
695
+ "Client wire-version range #{MIN_WIRE_VERSION} to " +
696
+ "#{MAX_WIRE_VERSION} does not support server range " +
697
+ "#{min_wire_version} to #{max_wire_version}, please update " +
698
+ "clients or servers"
699
+ end
700
+ end
701
+ end
702
+ end