mongo 1.8.2 → 1.8.3.rc0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data.tar.gz.sig +0 -0
  2. data/LICENSE +1 -1
  3. data/README.md +2 -7
  4. data/VERSION +1 -1
  5. data/lib/mongo.rb +2 -18
  6. data/lib/mongo/collection.rb +20 -24
  7. data/lib/mongo/cursor.rb +30 -35
  8. data/lib/mongo/db.rb +1 -19
  9. data/lib/mongo/exceptions.rb +0 -19
  10. data/lib/mongo/gridfs/grid.rb +18 -29
  11. data/lib/mongo/gridfs/grid_ext.rb +0 -18
  12. data/lib/mongo/gridfs/grid_file_system.rb +17 -26
  13. data/lib/mongo/gridfs/grid_io.rb +0 -18
  14. data/lib/mongo/legacy.rb +0 -18
  15. data/lib/mongo/mongo_client.rb +11 -33
  16. data/lib/mongo/mongo_replica_set_client.rb +29 -56
  17. data/lib/mongo/mongo_sharded_client.rb +38 -50
  18. data/lib/mongo/networking.rb +5 -4
  19. data/lib/mongo/util/conversions.rb +0 -17
  20. data/lib/mongo/util/core_ext.rb +0 -18
  21. data/lib/mongo/util/node.rb +16 -3
  22. data/lib/mongo/util/pool.rb +46 -36
  23. data/lib/mongo/util/pool_manager.rb +102 -71
  24. data/lib/mongo/util/read_preference.rb +4 -2
  25. data/lib/mongo/util/server_version.rb +0 -17
  26. data/lib/mongo/util/sharding_pool_manager.rb +4 -23
  27. data/lib/mongo/util/socket_util.rb +20 -0
  28. data/lib/mongo/util/ssl_socket.rb +10 -19
  29. data/lib/mongo/util/support.rb +0 -18
  30. data/lib/mongo/util/tcp_socket.rb +1 -9
  31. data/lib/mongo/util/thread_local_variable_manager.rb +0 -18
  32. data/lib/mongo/util/uri_parser.rb +87 -82
  33. data/lib/mongo/util/write_concern.rb +0 -18
  34. data/mongo.gemspec +4 -1
  35. data/test/auxillary/pool_reuse_test.rb +65 -0
  36. data/test/functional/collection_test.rb +92 -3
  37. data/test/functional/connection_test.rb +30 -6
  38. data/test/functional/db_api_test.rb +11 -0
  39. data/test/functional/timeout_test.rb +23 -0
  40. data/test/functional/uri_test.rb +69 -0
  41. data/test/replica_set/client_test.rb +0 -22
  42. data/test/replica_set/cursor_test.rb +11 -5
  43. data/test/replica_set/refresh_test.rb +0 -0
  44. data/test/replica_set/z_cluster_shutdown.rb +13 -0
  45. data/test/sharded_cluster/basic_test.rb +46 -32
  46. data/test/test_helper.rb +26 -1
  47. data/test/threading/basic_test.rb +10 -9
  48. data/test/tools/mongo_config.rb +6 -2
  49. data/test/unit/collection_test.rb +1 -1
  50. data/test/unit/grid_test.rb +20 -13
  51. data/test/unit/mongo_sharded_client_test.rb +32 -0
  52. data/test/unit/pool_manager_test.rb +28 -14
  53. metadata +45 -12
  54. metadata.gz.sig +0 -0
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  module Mongo
20
2
  module GridExt
21
3
  module InstanceMethods
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  module Mongo
20
2
 
21
3
  # A file store built on the GridFS specification featuring
@@ -39,12 +21,12 @@ module Mongo
39
21
 
40
22
  @default_query_opts = {:sort => [['filename', 1], ['uploadDate', -1]], :limit => 1}
41
23
 
42
- # Create indexes only if we're connected to a primary node.
24
+ # This will create indexes only if we're connected to a primary node.
43
25
  connection = @db.connection
44
- if (connection.class == MongoClient && connection.read_primary?) ||
45
- (connection.class == MongoReplicaSetClient && connection.primary)
46
- @files.create_index([['filename', 1], ['uploadDate', -1]])
47
- @chunks.create_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]], :unique => true)
26
+ begin
27
+ @files.ensure_index([['filename', 1], ['uploadDate', -1]])
28
+ @chunks.ensure_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]], :unique => true)
29
+ rescue Mongo::ConnectionFailure
48
30
  end
49
31
  end
50
32
 
@@ -104,9 +86,18 @@ module Mongo
104
86
  opts = opts.dup
105
87
  opts.merge!(default_grid_io_opts(filename))
106
88
  if mode == 'w'
107
- versions = opts.delete(:versions)
108
- if opts.delete(:delete_old) || (versions && versions < 1)
109
- versions = 1
89
+ begin
90
+ # Ensure there are the appropriate indexes, as state may have changed since instantiation of self.
91
+ # Recall that index definitions are cached with ensure_index so this statement won't unneccesarily repeat index creation.
92
+ @files.ensure_index([['filename', 1], ['uploadDate', -1]])
93
+ @chunks.ensure_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]], :unique => true)
94
+ versions = opts.delete(:versions)
95
+ if opts.delete(:delete_old) || (versions && versions < 1)
96
+ versions = 1
97
+ end
98
+ rescue Mongo::ConnectionFailure => e
99
+ raise e, "Failed to create necessary indexes and write data."
100
+ return
110
101
  end
111
102
  end
112
103
  file = GridIO.new(@files, @chunks, filename, mode, opts)
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  require 'digest/md5'
20
2
 
21
3
  module Mongo
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  module Mongo
20
2
  module LegacyWriteConcern
21
3
  @legacy_write_concern = true
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  require 'set'
20
2
  require 'socket'
21
3
  require 'thread'
@@ -128,9 +110,6 @@ module Mongo
128
110
  opts = args.last.is_a?(Hash) ? args.pop : {}
129
111
  @host, @port = parse_init(args[0], args[1], opts)
130
112
 
131
- # Default maximum BSON object size
132
- @max_bson_size = Mongo::DEFAULT_MAX_BSON_SIZE
133
-
134
113
  # Lock for request ids.
135
114
  @id_lock = Mutex.new
136
115
 
@@ -181,7 +160,7 @@ module Mongo
181
160
 
182
161
  # Initialize a connection to MongoDB using the MongoDB URI spec.
183
162
  #
184
- # Since MongoClient.new cannot be used with any <code>ENV["MONGODB_URI"]</code> that has multiple hosts (implying a replicaset),
163
+ # Since MongoClient.new cannot be used with any <code>ENV["MONGODB_URI"]</code> that has multiple hosts (implying a replicaset),
185
164
  # you may use this when the type of your connection varies by environment and should be determined solely from <code>ENV["MONGODB_URI"]</code>.
186
165
  #
187
166
  # @param uri [String]
@@ -471,7 +450,8 @@ module Mongo
471
450
  @mongos = true
472
451
  end
473
452
 
474
- @max_bson_size = config['maxBsonObjectSize'] || Mongo::DEFAULT_MAX_BSON_SIZE
453
+ @max_bson_size = config['maxBsonObjectSize']
454
+ @max_message_size = config['maxMessageSizeBytes']
475
455
  set_primary(host_port)
476
456
  end
477
457
 
@@ -479,10 +459,7 @@ module Mongo
479
459
  raise ConnectionFailure, "Failed to connect to a master node at #{host_port.join(":")}"
480
460
  end
481
461
  end
482
-
483
- # Ensures that the alias carries over to the overridden connect method when using
484
- # the replica set or sharded clients.
485
- def reconnect; connect end
462
+ alias :reconnect :connect
486
463
 
487
464
  # It's possible that we defined connected as all nodes being connected???
488
465
  # NOTE: Do check if this needs to be more stringent.
@@ -514,10 +491,7 @@ module Mongo
514
491
  def read_primary?
515
492
  @read_primary
516
493
  end
517
-
518
- # Ensures that the alias carries over to the overridden connect method when using
519
- # the replica set or sharded clients.
520
- def primary?; read_primary? end
494
+ alias :primary? :read_primary?
521
495
 
522
496
  # The socket pool that this connection reads from.
523
497
  #
@@ -538,7 +512,11 @@ module Mongo
538
512
  #
539
513
  # @return [Integer]
540
514
  def max_bson_size
541
- @max_bson_size
515
+ @max_bson_size || DEFAULT_MAX_BSON_SIZE
516
+ end
517
+
518
+ def max_message_size
519
+ @max_message_size || DEFAULT_MAX_MESSAGE_SIZE
542
520
  end
543
521
 
544
522
  # Checkout a socket for reading (i.e., a secondary node).
@@ -559,7 +537,7 @@ module Mongo
559
537
  # Note: this is overridden in MongoReplicaSetClient.
560
538
  def checkin(socket)
561
539
  if @primary_pool && socket && socket.pool
562
- socket.pool.checkin(socket)
540
+ socket.checkin
563
541
  end
564
542
  end
565
543
 
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  module Mongo
20
2
 
21
3
  # Instantiates and manages connections to a MongoDB replica set.
@@ -151,7 +133,6 @@ module Mongo
151
133
 
152
134
  # No connection manager by default.
153
135
  @manager = nil
154
- @old_managers = []
155
136
 
156
137
  # Lock for request ids.
157
138
  @id_lock = Mutex.new
@@ -183,15 +164,26 @@ module Mongo
183
164
  # Initiate a connection to the replica set.
184
165
  def connect
185
166
  log(:info, "Connecting...")
186
- @connect_mutex.synchronize do
187
- return if @connected
188
167
 
189
- seeds = @manager.nil? ? @seeds : @manager.seeds
190
- @manager = PoolManager.new(self, seeds)
168
+ # Prevent recursive connection attempts from the same thread.
169
+ # This is done rather than using a Monitor to prevent potentially recursing
170
+ # infinitely while attempting to connect and continually failing. Instead, fail fast.
171
+ raise ConnectionFailure, "Failed to get node data." if thread_local[:locks][:connecting] == true
191
172
 
192
- thread_local[:managers][self] = @manager
193
-
194
- @manager.connect
173
+ @connect_mutex.synchronize do
174
+ return if @connected
175
+ begin
176
+ thread_local[:locks][:connecting] = true
177
+ if @manager
178
+ @manager.refresh! @seeds
179
+ else
180
+ @manager = PoolManager.new(self, @seeds)
181
+ thread_local[:managers][self] = @manager
182
+ @manager.connect
183
+ end
184
+ ensure
185
+ thread_local[:locks][:connecting] = false
186
+ end
195
187
  @refresh_version += 1
196
188
 
197
189
  if @manager.pools.empty?
@@ -235,15 +227,7 @@ module Mongo
235
227
  # to get the refresh lock.
236
228
  def hard_refresh!
237
229
  log(:info, "Initiating hard refresh...")
238
- discovered_seeds = @manager.seeds
239
- new_manager = PoolManager.new(self, discovered_seeds | @seeds)
240
- new_manager.connect
241
-
242
- thread_local[:managers][self] = new_manager
243
-
244
- # TODO: make sure that connect has succeeded
245
- @old_managers << @manager
246
- @manager = new_manager
230
+ @manager.refresh! @seeds
247
231
 
248
232
  @refresh_version += 1
249
233
  return true
@@ -286,6 +270,7 @@ module Mongo
286
270
  def read_primary?
287
271
  @manager.read_pool == @manager.primary_pool
288
272
  end
273
+ alias :primary? :read_primary?
289
274
 
290
275
  # Close the connection to the database.
291
276
  def close(opts={})
@@ -343,12 +328,11 @@ module Mongo
343
328
  end
344
329
 
345
330
  if socket
346
- socket
331
+ return socket
347
332
  else
348
333
  @connected = false
349
334
  raise ConnectionFailure.new("Could not checkout a socket.")
350
335
  end
351
- socket
352
336
  end
353
337
 
354
338
  def checkout_reader(mode=@read, tag_sets=@tag_sets, acceptable_latency=@acceptable_latency)
@@ -368,7 +352,7 @@ module Mongo
368
352
  # Checkin a socket used for reading.
369
353
  def checkin(socket)
370
354
  if socket && socket.pool
371
- socket.pool.checkin(socket)
355
+ socket.checkin
372
356
  end
373
357
  sync_refresh
374
358
  end
@@ -435,11 +419,13 @@ module Mongo
435
419
  end
436
420
 
437
421
  def max_bson_size
438
- if local_manager && local_manager.max_bson_size
439
- local_manager.max_bson_size
440
- else
441
- Mongo::DEFAULT_MAX_BSON_SIZE
442
- end
422
+ return local_manager.max_bson_size if local_manager
423
+ DEFAULT_MAX_BSON_SIZE
424
+ end
425
+
426
+ def max_message_size
427
+ return local_manager.max_message_size if local_manager
428
+ DEFAULT_MAX_MESSAGE_SIZE
443
429
  end
444
430
 
445
431
  private
@@ -480,18 +466,6 @@ module Mongo
480
466
  super opts
481
467
  end
482
468
 
483
- def prune_managers
484
- @old_managers.each do |manager|
485
- if manager != @manager
486
- if manager.closed?
487
- @old_managers.delete(manager)
488
- else
489
- manager.close(:soft => true)
490
- end
491
- end
492
- end
493
- end
494
-
495
469
  def sync_refresh
496
470
  if @refresh_mode == :sync &&
497
471
  ((Time.now - @last_refresh) > @refresh_interval)
@@ -501,7 +475,6 @@ module Mongo
501
475
  if @refresh_mutex.try_lock
502
476
  begin
503
477
  refresh
504
- prune_managers
505
478
  ensure
506
479
  @refresh_mutex.unlock
507
480
  end
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  module Mongo
20
2
 
21
3
  # Instantiates and manages connections to a MongoDB sharded cluster for high availability.
@@ -34,11 +16,8 @@ module Mongo
34
16
 
35
17
  if nodes.empty? and ENV.has_key?('MONGODB_URI')
36
18
  parser = URIParser.new ENV['MONGODB_URI']
37
- if parser.direct?
38
- raise MongoArgumentError, "Mongo::MongoShardedClient.new called with no arguments, but ENV['MONGODB_URI'] implies a direct connection."
39
- end
40
19
  opts = parser.connection_options.merge! opts
41
- nodes = [parser.nodes]
20
+ nodes = parser.node_strings
42
21
  end
43
22
 
44
23
  unless nodes.length > 0
@@ -59,7 +38,6 @@ module Mongo
59
38
 
60
39
  # No connection manager by default.
61
40
  @manager = nil
62
- @old_managers = []
63
41
 
64
42
  # Lock for request ids.
65
43
  @id_lock = Mutex.new
@@ -80,7 +58,7 @@ module Mongo
80
58
  end
81
59
 
82
60
  def valid_opts
83
- GENERIC_OPTS + SHARDED_CLUSTER_OPTS
61
+ GENERIC_OPTS + SHARDED_CLUSTER_OPTS + READ_PREFERENCE_OPTS + WRITE_CONCERN_OPTS
84
62
  end
85
63
 
86
64
  def inspect
@@ -92,14 +70,26 @@ module Mongo
92
70
  def connect(force = !@connected)
93
71
  return unless force
94
72
  log(:info, "Connecting...")
95
- @connect_mutex.synchronize do
96
- discovered_seeds = @manager ? @manager.seeds : []
97
- @old_managers << @manager if @manager
98
- @manager = ShardingPoolManager.new(self, discovered_seeds | @seeds)
99
73
 
100
- thread_local[:managers][self] = @manager
74
+ # Prevent recursive connection attempts from the same thread.
75
+ # This is done rather than using a Monitor to prevent potentially recursing
76
+ # infinitely while attempting to connect and continually failing. Instead, fail fast.
77
+ raise ConnectionFailure, "Failed to get node data." if thread_local[:locks][:connecting]
78
+
79
+ @connect_mutex.synchronize do
80
+ begin
81
+ thread_local[:locks][:connecting] = true
82
+ if @manager
83
+ @manager.refresh! @seeds
84
+ else
85
+ @manager = ShardingPoolManager.new(self, @seeds)
86
+ thread_local[:managers][self] = @manager
87
+ @manager.connect
88
+ end
89
+ ensure
90
+ thread_local[:locks][:connecting] = false
91
+ end
101
92
 
102
- @manager.connect
103
93
  @refresh_version += 1
104
94
  @last_refresh = Time.now
105
95
  @connected = true
@@ -134,27 +124,25 @@ module Mongo
134
124
  end
135
125
 
136
126
  def checkout(&block)
137
- 2.times do
138
- if connected?
139
- sync_refresh
140
- else
141
- connect
142
- end
143
-
144
- begin
145
- socket = block.call
146
- rescue => ex
147
- checkin(socket) if socket
148
- raise ex
149
- end
150
-
151
- if socket
152
- return socket
153
- else
154
- @connected = false
155
- #raise ConnectionFailure.new("Could not checkout a socket.")
156
- end
127
+ tries = 0
128
+ begin
129
+ super(&block)
130
+ rescue ConnectionFailure
131
+ tries +=1
132
+ tries < 2 ? retry : raise
157
133
  end
158
134
  end
135
+
136
+ # Initialize a connection to MongoDB using the MongoDB URI spec.
137
+ #
138
+ # @param uri [ String ] string of the format:
139
+ # mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]
140
+ #
141
+ # @param opts [ Hash ] Any of the options available for MongoShardedClient.new
142
+ #
143
+ # @return [ Mongo::MongoShardedClient ] The sharded client.
144
+ def self.from_uri(uri = ENV['MONGODB_URI'], options = {})
145
+ URIParser.new(uri).connection(options, false, true)
146
+ end
159
147
  end
160
148
  end