mongo 1.1.5 → 1.2.rc0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -12,7 +12,7 @@ This documentation includes other articles of interest, include:
12
12
  6. [History](http://api.mongodb.org/ruby/current/file.HISTORY.html).
13
13
  7. [Credits](http://api.mongodb.org/ruby/current/file.CREDITS.html).
14
14
 
15
- Here's a quick code sample. Again, see the [MongoDB Ruby Tutorial](file.TUTORIAL.html)
15
+ Here's a quick code sample. Again, see the [MongoDB Ruby Tutorial](http://api.mongodb.org/ruby/current/file.TUTORIAL.html)
16
16
  for much more:
17
17
 
18
18
  require 'rubygems'
data/docs/HISTORY.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # MongoDB Ruby Driver History
2
2
 
3
+ 1.2.rc0
4
+ 2011-1-5
5
+
6
+ Lots of cleanp and minor bug fixes.
7
+ * Issues resolved: http://jira.mongodb.org/browse/RUBY/fixforversion/10222
8
+ * Updated Java BSON to Java driver 2.4.
9
+ * Platform gem for JRuby bson.
10
+
3
11
  ### 1.1.5
4
12
  2010-12-15
5
13
 
data/docs/REPLICA_SETS.md CHANGED
@@ -38,18 +38,14 @@ every half second and time out after thirty seconds.
38
38
 
39
39
  # Ensure retry upon failure
40
40
  def rescue_connection_failure(max_retries=60)
41
- success = false
42
- retries = 0
43
- while !success
44
- begin
45
- yield
46
- success = true
47
- rescue Mongo::ConnectionFailure => ex
48
- retries += 1
49
- raise ex if retries >= max_retries
50
- sleep(0.5)
51
- end
52
- end
41
+ retries = 0
42
+ begin
43
+ yield
44
+ rescue Mongo::ConnectionFailure => ex
45
+ retries += 1
46
+ raise ex if retries > max_retries
47
+ sleep(0.5)
48
+ retry
53
49
  end
54
50
  end
55
51
 
data/lib/mongo.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
 
5
5
  module Mongo
6
- VERSION = "1.1.5"
6
+ VERSION = "1.2.rc0"
7
7
  end
8
8
 
9
9
  module Mongo
@@ -11,6 +11,8 @@ module Mongo
11
11
  DESCENDING = -1
12
12
  GEO2D = '2d'
13
13
 
14
+ DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024
15
+
14
16
  module Constants
15
17
  OP_REPLY = 1
16
18
  OP_MSG = 1000
@@ -24,13 +24,13 @@ module Mongo
24
24
 
25
25
  # Initialize a collection object.
26
26
  #
27
- # @param [DB] db a MongoDB database instance.
28
27
  # @param [String, Symbol] name the name of the collection.
28
+ # @param [DB] db a MongoDB database instance.
29
29
  #
30
- # @option options [:create_pk] :pk (BSON::ObjectId) A primary key factory to use
30
+ # @option opts [:create_pk] :pk (BSON::ObjectId) A primary key factory to use
31
31
  # other than the default BSON::ObjectId.
32
32
  #
33
- # @option options [Boolean, Hash] :safe (false) Set the default safe-mode options
33
+ # @option opts [Boolean, Hash] :safe (false) Set the default safe-mode options
34
34
  # for insert, update, and remove method called on this Collection instance. If no
35
35
  # value is provided, the default value set on this instance's DB will be used. This
36
36
  # default can be overridden for any invocation of insert, update, or remove.
@@ -44,7 +44,13 @@ module Mongo
44
44
  # @return [Collection]
45
45
  #
46
46
  # @core collections constructor_details
47
- def initialize(db, name, options={})
47
+ def initialize(name, db, opts={})
48
+ if db.is_a?(String) && name.is_a?(Mongo::DB)
49
+ warn "Warning: the order of parameters to initialize a collection have changed. " +
50
+ "Please specify the collection name first, followed by the db."
51
+ db, name = name, db
52
+ end
53
+
48
54
  case name
49
55
  when Symbol, String
50
56
  else
@@ -63,10 +69,10 @@ module Mongo
63
69
  raise Mongo::InvalidNSName, "collection names must not start or end with '.'"
64
70
  end
65
71
 
66
- if options.respond_to?(:create_pk) || !options.is_a?(Hash)
72
+ if opts.respond_to?(:create_pk) || !opts.is_a?(Hash)
67
73
  warn "The method for specifying a primary key factory on a Collection has changed.\n" +
68
74
  "Please specify it as an option (e.g., :pk => PkFactory)."
69
- pk_factory = options
75
+ pk_factory = opts
70
76
  else
71
77
  pk_factory = nil
72
78
  end
@@ -77,9 +83,9 @@ module Mongo
77
83
  @cache_time = @db.cache_time
78
84
  @cache = Hash.new(0)
79
85
  unless pk_factory
80
- @safe = options.has_key?(:safe) ? options[:safe] : @db.safe
86
+ @safe = opts.fetch(:safe, @db.safe)
81
87
  end
82
- @pk_factory = pk_factory || options[:pk] || BSON::ObjectId
88
+ @pk_factory = pk_factory || opts[:pk] || BSON::ObjectId
83
89
  @hint = nil
84
90
  end
85
91
 
@@ -96,7 +102,7 @@ module Mongo
96
102
  # the specified sub-collection
97
103
  def [](name)
98
104
  name = "#{self.name}.#{name}"
99
- return Collection.new(db, name) if !db.strict? || db.collection_names.include?(name)
105
+ return Collection.new(name, db) if !db.strict? || db.collection_names.include?(name)
100
106
  raise "Collection #{name} doesn't exist. Currently in strict mode."
101
107
  end
102
108
 
@@ -134,7 +140,7 @@ module Mongo
134
140
  # to Ruby 1.8).
135
141
  #
136
142
  # @option opts [Array, Hash] :fields field names that should be returned in the result
137
- # set ("_id" will always be included). By limiting results to a certain subset of fields,
143
+ # set ("_id" will be included unless explicity excluded). By limiting results to a certain subset of fields,
138
144
  # you can cut down on network traffic and decoding time. If using a Hash, keys should be field
139
145
  # names and values should be either 1 or 0, depending on whether you want to include or exclude
140
146
  # the given field.
@@ -271,10 +277,10 @@ module Mongo
271
277
  # @see DB#remove for options that can be passed to :safe.
272
278
  #
273
279
  # @core insert insert-instance_method
274
- def insert(doc_or_docs, options={})
280
+ def insert(doc_or_docs, opts={})
275
281
  doc_or_docs = [doc_or_docs] unless doc_or_docs.is_a?(Array)
276
282
  doc_or_docs.collect! { |doc| @pk_factory.create_pk(doc) }
277
- safe = options.has_key?(:safe) ? options[:safe] : @safe
283
+ safe = opts.fetch(:safe, @safe)
278
284
  result = insert_documents(doc_or_docs, @name, true, safe)
279
285
  result.size > 1 ? result : result.first
280
286
  end
@@ -310,7 +316,7 @@ module Mongo
310
316
  # @core remove remove-instance_method
311
317
  def remove(selector={}, opts={})
312
318
  # Initial byte is 0.
313
- safe = opts.has_key?(:safe) ? opts[:safe] : @safe
319
+ safe = opts.fetch(:safe, @safe)
314
320
  message = BSON::ByteBuffer.new("\0\0\0\0")
315
321
  BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{@name}")
316
322
  message.put_int(0)
@@ -336,8 +342,8 @@ module Mongo
336
342
  # a hash specifying the fields to be changed in the selected document,
337
343
  # or (in the case of an upsert) the document to be inserted
338
344
  #
339
- # @option [Boolean] :upsert (+false+) if true, performs an upsert (update or insert)
340
- # @option [Boolean] :multi (+false+) update all documents matching the selector, as opposed to
345
+ # @option opts [Boolean] :upsert (+false+) if true, performs an upsert (update or insert)
346
+ # @option opts [Boolean] :multi (+false+) update all documents matching the selector, as opposed to
341
347
  # just the first matching document. Note: only works in MongoDB 1.1.3 or later.
342
348
  # @option opts [Boolean] :safe (+false+)
343
349
  # If true, check that the save succeeded. OperationFailure
@@ -350,14 +356,14 @@ module Mongo
350
356
  # Otherwise, returns true.
351
357
  #
352
358
  # @core update update-instance_method
353
- def update(selector, document, options={})
359
+ def update(selector, document, opts={})
354
360
  # Initial byte is 0.
355
- safe = options.has_key?(:safe) ? options[:safe] : @safe
361
+ safe = opts.fetch(:safe, @safe)
356
362
  message = BSON::ByteBuffer.new("\0\0\0\0")
357
363
  BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{@name}")
358
364
  update_options = 0
359
- update_options += 1 if options[:upsert]
360
- update_options += 2 if options[:multi]
365
+ update_options += 1 if opts[:upsert]
366
+ update_options += 2 if opts[:multi]
361
367
  message.put_int(update_options)
362
368
  message.put_binary(BSON::BSON_CODER.serialize(selector, false, true).to_s)
363
369
  message.put_binary(BSON::BSON_CODER.serialize(document, false, true).to_s)
@@ -415,6 +421,7 @@ module Mongo
415
421
  opts[:dropDups] = opts.delete(:drop_dups) if opts[:drop_dups]
416
422
  field_spec = parse_index_spec(spec)
417
423
  name = opts.delete(:name) || generate_index_name(field_spec)
424
+ name = name.to_s if name
418
425
 
419
426
  generate_indexes(field_spec, name, opts)
420
427
  name
@@ -437,18 +444,15 @@ module Mongo
437
444
  #
438
445
  # @return [String] the name of the index.
439
446
  def ensure_index(spec, opts={})
440
- valid = BSON::OrderedHash.new
441
447
  now = Time.now.utc.to_i
442
448
  field_spec = parse_index_spec(spec)
443
449
 
444
- field_spec.each do |key, value|
445
- cache_key = generate_index_name({key => value})
446
- timeout = @cache[cache_key] || 0
447
- valid[key] = value if timeout <= now
448
- end
450
+ name = opts.delete(:name) || generate_index_name(field_spec)
451
+ name = name.to_s if name
449
452
 
450
- name = opts.delete(:name) || generate_index_name(valid)
451
- generate_indexes(valid, name, opts) if valid.any?
453
+ if !@cache[name] || @cache[name] <= now
454
+ generate_indexes(field_spec, name, opts)
455
+ end
452
456
 
453
457
  # Reset the cache here in case there are any errors inserting. Best to be safe.
454
458
  @cache[name] = now + @cache_time
@@ -461,7 +465,7 @@ module Mongo
461
465
  #
462
466
  # @core indexes
463
467
  def drop_index(name)
464
- @cache[name] = nil
468
+ @cache[name.to_s] = nil
465
469
  @db.drop_index(@name, name)
466
470
  end
467
471
 
@@ -55,16 +55,16 @@ module Mongo
55
55
  # @param [String, Hash] host.
56
56
  # @param [Integer] port specify a port number here if only one host is being specified.
57
57
  #
58
- # @option options [Boolean, Hash] :safe (false) Set the default safe-mode options
58
+ # @option opts [Boolean, Hash] :safe (false) Set the default safe-mode options
59
59
  # propogated to DB objects instantiated off of this Connection. This
60
60
  # default can be overridden upon instantiation of any DB by explicity setting a :safe value
61
61
  # on initialization.
62
- # @option options [Boolean] :slave_ok (false) Must be set to +true+ when connecting
62
+ # @option opts [Boolean] :slave_ok (false) Must be set to +true+ when connecting
63
63
  # to a single, slave node.
64
- # @option options [Logger, #debug] :logger (nil) Logger instance to receive driver operation log.
65
- # @option options [Integer] :pool_size (1) The maximum number of socket connections allowed per
64
+ # @option opts [Logger, #debug] :logger (nil) Logger instance to receive driver operation log.
65
+ # @option opts [Integer] :pool_size (1) The maximum number of socket connections allowed per
66
66
  # connection pool. Note: this setting is relevant only for multi-threaded applications.
67
- # @option options [Float] :timeout (5.0) When all of the connections a pool are checked out,
67
+ # @option opts [Float] :timeout (5.0) When all of the connections a pool are checked out,
68
68
  # this is the number of seconds to wait for a new connection to be released before throwing an exception.
69
69
  # Note: this setting is relevant only for multi-threaded applications (which in Ruby are rare).
70
70
  #
@@ -86,16 +86,16 @@ module Mongo
86
86
  # driver fails to connect to a replica set with that name.
87
87
  #
88
88
  # @core connections
89
- def initialize(host=nil, port=nil, options={})
89
+ def initialize(host=nil, port=nil, opts={})
90
90
  @host_to_try = format_pair(host, port)
91
91
 
92
92
  # Host and port of current master.
93
93
  @host = @port = nil
94
94
 
95
95
  # slave_ok can be true only if one node is specified
96
- @slave_ok = options[:slave_ok]
96
+ @slave_ok = opts[:slave_ok]
97
97
 
98
- setup(options)
98
+ setup(opts)
99
99
  end
100
100
 
101
101
  # DEPRECATED
@@ -109,9 +109,9 @@ module Mongo
109
109
  # @param nodes [Array] An array of arrays, each of which specifies a host and port.
110
110
  # @param opts [Hash] Any of the available options that can be passed to Connection.new.
111
111
  #
112
- # @option options [String] :rs_name (nil) The name of the replica set to connect to. An exception will be
112
+ # @option opts [String] :rs_name (nil) The name of the replica set to connect to. An exception will be
113
113
  # raised if unable to connect to a replica set with this name.
114
- # @option options [Boolean] :read_secondary (false) When true, this connection object will pick a random slave
114
+ # @option opts [Boolean] :read_secondary (false) When true, this connection object will pick a random slave
115
115
  # to send reads to.
116
116
  #
117
117
  # @example
@@ -138,15 +138,19 @@ module Mongo
138
138
  #
139
139
  # @param opts Any of the options available for Connection.new
140
140
  #
141
- # @return [Mongo::Connection]
142
- def self.from_uri(uri, opts={})
143
- nodes, auths = Mongo::URIParser.parse(uri)
144
- opts.merge!({:auths => auths})
145
- if nodes.length == 1
146
- Connection.new(nodes[0][0], nodes[0][1], opts)
147
- elsif nodes.length > 1
148
- nodes << opts
149
- ReplSetConnection.new(*nodes)
141
+ # @return [Mongo::Connection, Mongo::ReplSetConnection]
142
+ def self.from_uri(string, extra_opts={})
143
+ uri = URIParser.new(string)
144
+ opts = uri.connection_options
145
+ opts.merge!(extra_opts)
146
+
147
+ if uri.nodes.length == 1
148
+ opts.merge!({:auths => uri.auths})
149
+ Connection.new(uri.nodes[0][0], uri.nodes[0][1], opts)
150
+ elsif uri.nodes.length > 1
151
+ nodes = uri.nodes.clone
152
+ nodes_with_opts = nodes << opts
153
+ ReplSetConnection.new(*nodes_with_opts)
150
154
  else
151
155
  raise MongoArgumentError, "No nodes specified. Please ensure that you've provided at least one node."
152
156
  end
@@ -259,12 +263,13 @@ module Mongo
259
263
  # See DB#new for valid options hash parameters.
260
264
  #
261
265
  # @param [String] db_name a valid database name.
266
+ # @param [Hash] opts options to be passed to the DB constructor.
262
267
  #
263
268
  # @return [Mongo::DB]
264
269
  #
265
270
  # @core databases db-instance_method
266
- def db(db_name, options={})
267
- DB.new(db_name, self, options)
271
+ def db(db_name, opts={})
272
+ DB.new(db_name, self, opts)
268
273
  end
269
274
 
270
275
  # Shortcut for returning a database. Use DB#db to accept options.
@@ -430,11 +435,19 @@ module Mongo
430
435
  reset_connection
431
436
 
432
437
  config = check_is_master(@host_to_try)
433
- if is_primary?(config)
438
+ if config
439
+ if config['ismaster'] == 1 || config['ismaster'] == true
440
+ @read_primary = true
441
+ elsif @slave_ok
442
+ @read_primary = false
443
+ end
444
+
434
445
  set_primary(@host_to_try)
435
446
  end
436
447
 
437
- if !connected?
448
+ if connected?
449
+ BSON::BSON_CODER.update_max_bson_size(self)
450
+ else
438
451
  raise ConnectionFailure, "Failed to connect to a master node at #{@host_to_try[0]}:#{@host_to_try[1]}"
439
452
  end
440
453
  end
@@ -450,12 +463,29 @@ module Mongo
450
463
  @primary_pool && @primary_pool.host && @primary_pool.port
451
464
  end
452
465
 
466
+ # Determine whether we're reading from a primary node. If false,
467
+ # this connection connects to a secondary node and @slave_ok is true.
468
+ #
469
+ # @return [Boolean]
470
+ def read_primary?
471
+ @read_primary
472
+ end
473
+
453
474
  # Close the connection to the database.
454
475
  def close
455
476
  @primary_pool.close if @primary_pool
456
477
  @primary_pool = nil
457
478
  end
458
479
 
480
+ # Returns the maximum BSON object size as returned by the core server.
481
+ # Use the 4MB default when the server doesn't report this.
482
+ #
483
+ # @return [Integer]
484
+ def max_bson_size
485
+ config = self['admin'].command({:ismaster => 1})
486
+ config['maxBsonObjectSize'] || Mongo::DEFAULT_MAX_BSON_SIZE
487
+ end
488
+
459
489
  # Checkout a socket for reading (i.e., a secondary node).
460
490
  # Note: this is overridden in ReplSetConnection.
461
491
  def checkout_reader
@@ -489,23 +519,22 @@ module Mongo
489
519
  protected
490
520
 
491
521
  # Generic initialization code.
492
- # @protected
493
- def setup(options)
522
+ def setup(opts)
494
523
  # Authentication objects
495
- @auths = options.fetch(:auths, [])
524
+ @auths = opts.fetch(:auths, [])
496
525
 
497
526
  # Lock for request ids.
498
527
  @id_lock = Mutex.new
499
528
 
500
529
  # Pool size and timeout.
501
- @pool_size = options[:pool_size] || 1
502
- @timeout = options[:timeout] || 5.0
530
+ @pool_size = opts[:pool_size] || 1
531
+ @timeout = opts[:timeout] || 5.0
503
532
 
504
533
  # Mutex for synchronizing pool access
505
534
  @connection_mutex = Mutex.new
506
535
 
507
536
  # Global safe option. This is false by default.
508
- @safe = options[:safe] || false
537
+ @safe = opts[:safe] || false
509
538
 
510
539
  # Create a mutex when a new key, in this case a socket,
511
540
  # is added to the hash.
@@ -518,9 +547,9 @@ module Mongo
518
547
  @primary = nil
519
548
  @primary_pool = nil
520
549
 
521
- @logger = options[:logger] || nil
550
+ @logger = opts[:logger] || nil
522
551
 
523
- should_connect = options.fetch(:connect, true)
552
+ should_connect = opts.fetch(:connect, true)
524
553
  connect if should_connect
525
554
  end
526
555
 
@@ -552,16 +581,6 @@ module Mongo
552
581
  @primary = nil
553
582
  end
554
583
 
555
- # Primary is defined as either a master node or a slave if
556
- # :slave_ok has been set to +true+.
557
- #
558
- # If a primary node is discovered, we set the the @host and @port and
559
- # apply any saved authentication.
560
- # TODO: simplify
561
- def is_primary?(config)
562
- config && (config['ismaster'] == 1 || config['ismaster'] == true) || @slave_ok
563
- end
564
-
565
584
  def check_is_master(node)
566
585
  begin
567
586
  host, port = *node
@@ -673,7 +692,7 @@ module Mongo
673
692
  #
674
693
  # Note: this method modifies message by reference.
675
694
  #
676
- # @returns [Integer] the request id used in the header
695
+ # @return [Integer] the request id used in the header
677
696
  def add_message_headers(message, operation)
678
697
  headers = [
679
698
  # Message size.
data/lib/mongo/cursor.rb CHANGED
@@ -33,26 +33,26 @@ module Mongo
33
33
  # @return [Cursor]
34
34
  #
35
35
  # @core cursors constructor_details
36
- def initialize(collection, options={})
36
+ def initialize(collection, opts={})
37
37
  @db = collection.db
38
38
  @collection = collection
39
39
  @connection = @db.connection
40
40
  @logger = @connection.logger
41
41
 
42
- @selector = options[:selector] || {}
43
- @fields = convert_fields_for_query(options[:fields])
44
- @skip = options[:skip] || 0
45
- @limit = options[:limit] || 0
46
- @order = options[:order]
47
- @hint = options[:hint]
48
- @snapshot = options[:snapshot]
49
- @timeout = options.has_key?(:timeout) ? options[:timeout] : true
50
- @explain = options[:explain]
51
- @socket = options[:socket]
52
- @tailable = options[:tailable] || false
42
+ @selector = opts[:selector] || {}
43
+ @fields = convert_fields_for_query(opts[:fields])
44
+ @skip = opts[:skip] || 0
45
+ @limit = opts[:limit] || 0
46
+ @order = opts[:order]
47
+ @hint = opts[:hint]
48
+ @snapshot = opts[:snapshot]
49
+ @timeout = opts.fetch(:timeout, true)
50
+ @explain = opts[:explain]
51
+ @socket = opts[:socket]
52
+ @tailable = opts[:tailable] || false
53
53
  @closed = false
54
54
  @query_run = false
55
- batch_size(options[:batch_size] || 0)
55
+ batch_size(opts[:batch_size] || 0)
56
56
 
57
57
  @full_collection_name = "#{@collection.db.name}.#{@collection.name}"
58
58
  @cache = []