mongo 1.8.3 → 1.8.4.rc0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9292e4cac6a44329fb7c7940421fe07ff8e787bd
4
- data.tar.gz: 14a5d525f6fd6cefe6694576e02d841d2882994b
5
- SHA512:
6
- metadata.gz: b58e0adafd2a3b6522a74c87c8aaae7ea7ae2968fc8fa83b1fe0851accc74df459e683d3755a5d96d84509d19b6b3e11c55d35a6ed4024997b28d847dd587233
7
- data.tar.gz: a910cea9b47023cd6bca4771557d00e435f2acc9234acafcfd43445e82ab947e941bca3db71afb2030aeedb1454e0956bf530b8e82b6b606b5a9d5b9fd404e1b
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YjU5N2Y3NjIxZDMyODFiMDI3MWYzODQ1MzNiMDk2YjgxZmQwY2EyYg==
5
+ data.tar.gz: !binary |-
6
+ MTEwZTgzOWQ3MzkyNGNhNmQ3ZDY2YzE0ZGVkMDc0MTJhNWRlOWM4Yg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NjYwYTlmNDYwNTZkZjZiMmQyZTUzNzgxOTM5NGMwMWQ0YjY5MDE3M2M3YmUx
10
+ MmI3MWNmN2QxMTgwMTZiMTdjNzMyODJhZjAzYTg1M2VkMTI4OTI5ZjNlMjdl
11
+ NTVlY2E0MDc5MTY3ZmNjOTBhZmFkMjA2MDlkYjAzYjgyNTMyNWE=
12
+ data.tar.gz: !binary |-
13
+ MGJlZGJlMjk5NWFhYjI1MjhiYjYwMmVkZjViZTdiNDE0ZjY0YWEwZmIxZDRj
14
+ NzEyYjk5N2Y1MDMyNWM4ZmU1YTM0ODA2ZDQ3ZTQwNTdhNTRmOGNhZmEwNjA3
15
+ ZTZlNzM5YzRiYmJkN2JlM2VmYTEzNWJhOThjYTRhMzRiNTg2N2U=
Binary file
data.tar.gz.sig CHANGED
Binary file
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.8.3
1
+ 1.8.4.rc0
@@ -2,7 +2,18 @@ module Mongo
2
2
  ASCENDING = 1
3
3
  DESCENDING = -1
4
4
  GEO2D = '2d'
5
+ GEO2DSPHERE = '2dsphere'
5
6
  GEOHAYSTACK = 'geoHaystack'
7
+ TEXT = 'text'
8
+ HASHED = 'hashed'
9
+ INDEX_TYPES = [ ASCENDING,
10
+ DESCENDING,
11
+ GEO2D,
12
+ GEO2DSPHERE,
13
+ GEOHAYSTACK,
14
+ TEXT,
15
+ HASHED
16
+ ]
6
17
 
7
18
  DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024
8
19
  DEFAULT_MAX_MESSAGE_SIZE = DEFAULT_MAX_BSON_SIZE * 2
@@ -9,7 +9,8 @@ module Mongo
9
9
  :name,
10
10
  :pk_factory,
11
11
  :hint,
12
- :write_concern
12
+ :write_concern,
13
+ :capped
13
14
 
14
15
  # Read Preference
15
16
  attr_accessor :read,
@@ -20,20 +21,20 @@ module Mongo
20
21
  #
21
22
  # @param [String, Symbol] name the name of the collection.
22
23
  # @param [DB] db a MongoDB database instance.
23
- #
24
+ #
24
25
  # @option opts [String, Integer, Symbol] :w (1) Set default number of nodes to which a write
25
26
  # should be acknowledged
26
27
  # @option opts [Boolean] :j (false) Set journal acknowledgement
27
28
  # @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout
28
29
  # @option opts [Boolean] :fsync (false) Set fsync acknowledgement.
29
- #
30
+ #
30
31
  # Notes about write concern:
31
- # These write concern options will be used for insert, update, and remove methods called on this
32
- # Collection instance. If no value is provided, the default values set on this instance's DB will be used.
32
+ # These write concern options will be used for insert, update, and remove methods called on this
33
+ # Collection instance. If no value is provided, the default values set on this instance's DB will be used.
33
34
  # These option values can be overridden for any invocation of insert, update, or remove.
34
35
  #
35
36
  # @option opts [:create_pk] :pk (BSON::ObjectId) A primary key factory to use
36
- # other than the default BSON::ObjectId.
37
+ # other than the default BSON::ObjectId.
37
38
  # @option opts [:primary, :secondary] :read The default read preference for queries
38
39
  # initiates from this connection object. If +:secondary+ is chosen, reads will be sent
39
40
  # to one of the closest available secondary nodes. If a secondary node cannot be located, the
@@ -57,30 +58,26 @@ module Mongo
57
58
  db, name = name, db
58
59
  end
59
60
 
60
- case name
61
- when Symbol, String
62
- else
63
- raise TypeError, "new_name must be a string or symbol"
64
- end
65
-
61
+ raise TypeError,
62
+ "Collection name must be a String or Symbol." unless [String, Symbol].include?(name.class)
66
63
  name = name.to_s
67
64
 
68
- if name.empty? or name.include? ".."
69
- raise Mongo::InvalidNSName, "collection names cannot be empty"
70
- end
71
- if name.include? "$"
72
- raise Mongo::InvalidNSName, "collection names must not contain '$'" unless name =~ /((^\$cmd)|(oplog\.\$main))/
73
- end
74
- if name.match(/^\./) or name.match(/\.$/)
75
- raise Mongo::InvalidNSName, "collection names must not start or end with '.'"
65
+ raise Mongo::InvalidNSName,
66
+ "Collection names cannot be empty." if name.empty? || name.include?("..")
67
+
68
+ if name.include?("$")
69
+ raise Mongo::InvalidNSName,
70
+ "Collection names must not contain '$'" unless name =~ /((^\$cmd)|(oplog\.\$main))/
76
71
  end
77
72
 
73
+ raise Mongo::InvalidNSName,
74
+ "Collection names must not start or end with '.'" if name.match(/^\./) || name.match(/\.$/)
75
+
76
+ pk_factory = nil
78
77
  if opts.respond_to?(:create_pk) || !opts.is_a?(Hash)
79
78
  warn "The method for specifying a primary key factory on a Collection has changed.\n" +
80
- "Please specify it as an option (e.g., :pk => PkFactory)."
79
+ "Please specify it as an option (e.g., :pk => PkFactory)."
81
80
  pk_factory = opts
82
- else
83
- pk_factory = nil
84
81
  end
85
82
 
86
83
  @db, @name = db, name
@@ -92,6 +89,7 @@ module Mongo
92
89
  @write_concern = get_write_concern(opts, db)
93
90
  @read = opts[:read] || @db.read
94
91
  Mongo::ReadPreference::validate(@read)
92
+ @capped = opts[:capped]
95
93
  @tag_sets = opts.fetch(:tag_sets, @db.tag_sets)
96
94
  @acceptable_latency = opts.fetch(:acceptable_latency, @db.acceptable_latency)
97
95
  end
@@ -106,7 +104,7 @@ module Mongo
106
104
  #
107
105
  # @return [Boolean]
108
106
  def capped?
109
- [1, true].include? @db.command({:collstats => @name})['capped']
107
+ @capped ||= [1, true].include?(@db.command({:collstats => @name})['capped'])
110
108
  end
111
109
 
112
110
  # Return a sub-collection of this collection by name. If 'users' is a collection, then
@@ -315,10 +313,10 @@ module Mongo
315
313
  # @return [ObjectId] the _id of the saved document.
316
314
  #
317
315
  # @option opts [Hash] :w, :j, :wtimeout, :fsync Set the write concern for this operation.
318
- # :w > 0 will run a +getlasterror+ command on the database to report any assertion.
316
+ # :w > 0 will run a +getlasterror+ command on the database to report any assertion.
319
317
  # :j will confirm a write has been committed to the journal,
320
318
  # :wtimeout specifies how long to wait for write confirmation,
321
- # :fsync will confirm that a write has been fsynced.
319
+ # :fsync will confirm that a write has been fsynced.
322
320
  # Options provided here will override any write concern options set on this collection,
323
321
  # its database object, or the current connection. See the options
324
322
  # for DB#get_last_error.
@@ -351,23 +349,23 @@ module Mongo
351
349
  # @option opts [Boolean] :j (false) Set journal acknowledgement
352
350
  # @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout
353
351
  # @option opts [Boolean] :fsync (false) Set fsync acknowledgement.
354
- #
352
+ #
355
353
  # Notes on write concern:
356
354
  # Options provided here will override any write concern options set on this collection,
357
- # its database object, or the current connection. See the options for +DB#get_last_error+.
355
+ # its database object, or the current connection. See the options for +DB#get_last_error+.
358
356
  #
359
357
  # @option opts [Boolean] :continue_on_error (+false+) If true, then
360
358
  # continue a bulk insert even if one of the documents inserted
361
359
  # triggers a database assertion (as in a duplicate insert, for instance).
362
360
  # If not acknowledging writes, the list of ids returned will
363
361
  # include the object ids of all documents attempted on insert, even
364
- # if some are rejected on error. When acknowledging writes, any error will raise an
362
+ # if some are rejected on error. When acknowledging writes, any error will raise an
365
363
  # OperationFailure exception.
366
364
  # MongoDB v2.0+.
367
365
  # @option opts [Boolean] :collect_on_error (+false+) if true, then
368
366
  # collects invalid documents as an array. Note that this option changes the result format.
369
367
  #
370
- # @raise [Mongo::OperationFailure] will be raised iff :w > 0 and the operation fails.
368
+ # @raise [Mongo::OperationFailure] will be raised iff :w > 0 and the operation fails.
371
369
  #
372
370
  # @core insert insert-instance_method
373
371
  def insert(doc_or_docs, opts={})
@@ -392,7 +390,7 @@ module Mongo
392
390
  #
393
391
  # Notes on write concern:
394
392
  # Options provided here will override any write concern options set on this collection,
395
- # its database object, or the current connection. See the options for +DB#get_last_error+.
393
+ # its database object, or the current connection. See the options for +DB#get_last_error+.
396
394
  #
397
395
  # @example remove all documents from the 'users' collection:
398
396
  # users.remove
@@ -446,7 +444,7 @@ module Mongo
446
444
  #
447
445
  # Notes on write concern:
448
446
  # Options provided here will override any write concern options set on this collection,
449
- # its database object, or the current connection. See the options for DB#get_last_error.
447
+ # its database object, or the current connection. See the options for DB#get_last_error.
450
448
  #
451
449
  # @return [Hash, true] Returns a Hash containing the last error object if acknowledging writes.
452
450
  # Otherwise, returns true.
@@ -483,8 +481,9 @@ module Mongo
483
481
  #
484
482
  # @param [String, Array] spec
485
483
  # should be either a single field name or an array of
486
- # [field name, direction] pairs. Directions should be specified
487
- # as Mongo::ASCENDING, Mongo::DESCENDING, or Mongo::GEO2D.
484
+ # [field name, type] pairs. Index types should be specified
485
+ # as Mongo::ASCENDING, Mongo::DESCENDING, Mongo::GEO2D, Mongo::GEO2DSPHERE, Mongo::GEOHAYSTACK,
486
+ # Mongo::TEXT or Mongo::HASHED.
488
487
  #
489
488
  # Note that geospatial indexing only works with versions of MongoDB >= 1.3.3+. Keep in mind, too,
490
489
  # that in order to geo-index a given field, that field must reference either an array or a sub-object
@@ -501,6 +500,8 @@ module Mongo
501
500
  # feature is only available in MongoDB >= 1.3.2.
502
501
  # @option opts [Boolean] :drop_dups (nil) If creating a unique index on a collection with pre-existing records,
503
502
  # this option will keep the first document the database indexes and drop all subsequent with duplicate values.
503
+ # @option opts [Integer] :bucket_size (nil) For use with geoHaystack indexes. Number of documents to group
504
+ # together within a certain proximity to a given longitude and latitude.
504
505
  # @option opts [Integer] :min (nil) specify the minimum longitude and latitude for a geo index.
505
506
  # @option opts [Integer] :max (nil) specify the maximum longitude and latitude for a geo index.
506
507
  #
@@ -525,11 +526,12 @@ module Mongo
525
526
  #
526
527
  # @core indexes create_index-instance_method
527
528
  def create_index(spec, opts={})
528
- opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
529
- field_spec = parse_index_spec(spec)
530
- opts = opts.dup
531
- name = opts.delete(:name) || generate_index_name(field_spec)
532
- name = name.to_s if name
529
+ opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
530
+ opts[:bucketSize] = opts[:bucket_size] if opts[:bucket_size]
531
+ field_spec = parse_index_spec(spec)
532
+ opts = opts.dup
533
+ name = opts.delete(:name) || generate_index_name(field_spec)
534
+ name = name.to_s if name
533
535
  generate_indexes(field_spec, name, opts)
534
536
  name
535
537
  end
@@ -551,11 +553,12 @@ module Mongo
551
553
  #
552
554
  # @return [String] the name of the index.
553
555
  def ensure_index(spec, opts={})
554
- now = Time.now.utc.to_i
555
- opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
556
- field_spec = parse_index_spec(spec)
557
- name = opts[:name] || generate_index_name(field_spec)
558
- name = name.to_s if name
556
+ now = Time.now.utc.to_i
557
+ opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
558
+ opts[:bucketSize] = opts[:bucket_size] if opts[:bucket_size]
559
+ field_spec = parse_index_spec(spec)
560
+ name = opts[:name] || generate_index_name(field_spec)
561
+ name = name.to_s if name
559
562
 
560
563
  if !@cache[name] || @cache[name] <= now
561
564
  generate_indexes(field_spec, name, opts)
@@ -626,7 +629,7 @@ module Mongo
626
629
  #
627
630
  # @param [Array] pipeline Should be a single array of pipeline operator hashes.
628
631
  #
629
- # '$project' Reshapes a document stream by including fields, excluding fields, inserting computed fields,
632
+ # '$project' Reshapes a document stream by including fields, excluding fields, inserting computed fields,
630
633
  # renaming fields,or creating/populating fields that hold sub-documents.
631
634
  #
632
635
  # '$match' Query-like interface for filtering documents out of the aggregation pipeline.
@@ -1017,11 +1020,13 @@ module Mongo
1017
1020
  end
1018
1021
  elsif spec.is_a?(Array) && spec.all? {|field| field.is_a?(Array) }
1019
1022
  spec.each do |f|
1020
- if [Mongo::ASCENDING, Mongo::DESCENDING, Mongo::GEO2D, Mongo::GEOHAYSTACK].include?(f[1])
1023
+ if Mongo::INDEX_TYPES.include?(f[1])
1021
1024
  field_spec[f[0].to_s] = f[1]
1022
1025
  else
1023
1026
  raise MongoArgumentError, "Invalid index field #{f[1].inspect}; " +
1024
- "should be one of Mongo::ASCENDING (1), Mongo::DESCENDING (-1) or Mongo::GEO2D ('2d')."
1027
+ "should be one of Mongo::ASCENDING (#{Mongo::ASCENDING}), Mongo::DESCENDING (#{Mongo::DESCENDING}), " +
1028
+ "Mongo::GEOHAYSTACK ('#{Mongo::GEOHAYSTACK}'), Mongo::GEO2DSPHERE ('#{Mongo::GEO2DSPHERE}'), " +
1029
+ "Mongo::TEXT ('#{Mongo::TEXT}'), or Mongo::HASHED ('#{Mongo::HASHED}')"
1025
1030
  end
1026
1031
  end
1027
1032
  else
@@ -1109,8 +1114,8 @@ module Mongo
1109
1114
 
1110
1115
  def generate_index_name(spec)
1111
1116
  indexes = []
1112
- spec.each_pair do |field, direction|
1113
- indexes.push("#{field}_#{direction}")
1117
+ spec.each_pair do |field, type|
1118
+ indexes.push("#{field}_#{type}")
1114
1119
  end
1115
1120
  indexes.join("_")
1116
1121
  end
@@ -6,12 +6,13 @@ module Mongo
6
6
  include Mongo::Constants
7
7
  include Mongo::Conversions
8
8
  include Mongo::Logging
9
+ include Mongo::ReadPreference
9
10
 
10
11
  attr_reader :collection, :selector, :fields,
11
12
  :order, :hint, :snapshot, :timeout,
12
13
  :full_collection_name, :transformer,
13
14
  :options, :cursor_id, :show_disk_loc,
14
- :comment, :read, :tag_sets
15
+ :comment, :read, :tag_sets, :acceptable_latency
15
16
 
16
17
  # Create a new cursor.
17
18
  #
@@ -471,6 +472,7 @@ module Mongo
471
472
  nil, @options & OP_QUERY_EXHAUST != 0)
472
473
  rescue ConnectionFailure => ex
473
474
  socket.close if socket
475
+ @connection.unpin_pool
474
476
  @connection.refresh
475
477
  if tries < 3 && !@socket && (!@command || Mongo::Support::secondary_ok?(@selector))
476
478
  tries += 1
@@ -483,6 +485,9 @@ module Mongo
483
485
  ensure
484
486
  socket.checkin unless @socket || socket.nil?
485
487
  end
488
+ if !@socket && !@command
489
+ @connection.pin_pool(socket.pool, read_preference)
490
+ end
486
491
  @returned += @n_received
487
492
  @cache += results
488
493
  @query_run = true
@@ -530,16 +535,15 @@ module Mongo
530
535
  if @pool
531
536
  socket = @pool.checkout
532
537
  elsif @command && !Mongo::Support::secondary_ok?(@selector)
533
- socket = @connection.checkout_reader(:primary)
538
+ socket = @connection.checkout_reader({:mode => :primary})
534
539
  else
535
- socket = @connection.checkout_reader(@read, @tag_sets, @acceptable_latency)
540
+ socket = @connection.checkout_reader(read_preference)
536
541
  end
537
542
  rescue SystemStackError, NoMemoryError, SystemCallError => ex
538
543
  @connection.close
539
544
  raise ex
540
545
  end
541
546
  @pool = socket.pool
542
- #puts "checkout_socket_from_connection caller:#{caller[0][/:in `([^']+)'/,1]} self:#{self.object_id} @pool.port:#{@pool.port}"
543
547
  socket
544
548
  end
545
549
 
@@ -14,6 +14,12 @@ module Mongo
14
14
  SYSTEM_JS_COLLECTION = 'system.js'
15
15
  SYSTEM_COMMAND_COLLECTION = '$cmd'
16
16
 
17
+ PROFILE_LEVEL = {
18
+ :off => 0,
19
+ :slow_only => 1,
20
+ :all => 2
21
+ }
22
+
17
23
  # Counter for generating unique request ids.
18
24
  @@current_request_id = 0
19
25
 
@@ -22,10 +28,24 @@ module Mongo
22
28
  # collection that already exists, raises an error.
23
29
  #
24
30
  # Strict mode is disabled by default, but enabled (+true+) at any time.
25
- attr_writer :strict
31
+ #
32
+ # @deprecated Support for strict mode has been deprecated and will be
33
+ # removed in version 2.0 of the driver.
34
+ def strict=(value)
35
+ unless ENV['TEST_MODE']
36
+ warn "Support for strict mode has been deprecated and will be " +
37
+ "removed in version 2.0 of the driver."
38
+ end
39
+ @strict = value
40
+ end
26
41
 
27
42
  # Returns the value of the +strict+ flag.
28
- def strict?; @strict; end
43
+ #
44
+ # @deprecated Support for strict mode has been deprecated and will be
45
+ # removed in version 2.0 of the driver.
46
+ def strict?
47
+ @strict
48
+ end
29
49
 
30
50
  # The name of the database and the local write concern options.
31
51
  attr_reader :name, :write_concern
@@ -45,8 +65,9 @@ module Mongo
45
65
  # @param [Mongo::MongoClient] client a connection object pointing to MongoDB. Note
46
66
  # that databases are usually instantiated via the MongoClient class. See the examples below.
47
67
  #
48
- # @option opts [Boolean] :strict (False) If true, collections must exist to be accessed and must
49
- # not exist to be created. See DB#collection and DB#create_collection.
68
+ # @option opts [Boolean] :strict (False) [DEPRECATED] If true, collections existence checks are
69
+ # performed during a number of relevant operations. See DB#collection, DB#create_collection and
70
+ # DB#drop_collection.
50
71
  #
51
72
  # @option opts [Object, #create_pk(doc)] :pk (BSON::ObjectId) A primary key factory object,
52
73
  # which should take a hash and return a hash which merges the original hash with any primary key
@@ -99,10 +120,8 @@ module Mongo
99
120
  #
100
121
  # @core authenticate authenticate-instance_method
101
122
  def authenticate(username, password, save_auth=true)
102
- if @connection.pool_size > 1
103
- if !save_auth
104
- raise MongoArgumentError, "If using connection pooling, :save_auth must be set to true."
105
- end
123
+ if @connection.pool_size > 1 && !save_auth
124
+ raise MongoArgumentError, "If using connection pooling, :save_auth must be set to true."
106
125
  end
107
126
 
108
127
  begin
@@ -126,17 +145,15 @@ module Mongo
126
145
  auth['nonce'] = nonce
127
146
  auth['key'] = Mongo::Support.auth_key(username, password, nonce)
128
147
  if ok?(doc = self.command(auth, :check_response => false, :socket => opts[:socket]))
129
- if save_auth
130
- @connection.add_auth(@name, username, password)
131
- end
132
- true
148
+ @connection.add_auth(@name, username, password) if save_auth
133
149
  else
134
150
  message = "Failed to authenticate user '#{username}' on db '#{self.name}'"
135
151
  raise Mongo::AuthenticationError.new(message, doc['code'], doc)
136
152
  end
153
+ true
137
154
  end
138
155
 
139
- # Adds a stored Javascript function to the database which can executed
156
+ # Adds a stored Javascript function to the database which can executed
140
157
  # server-side in map_reduce, db.eval and $where clauses.
141
158
  #
142
159
  # @param [String] function_name
@@ -146,7 +163,7 @@ module Mongo
146
163
  def add_stored_function(function_name, code)
147
164
  self[SYSTEM_JS_COLLECTION].save(
148
165
  {
149
- "_id" => function_name,
166
+ "_id" => function_name,
150
167
  :value => BSON::Code.new(code)
151
168
  }
152
169
  )
@@ -159,11 +176,8 @@ module Mongo
159
176
  #
160
177
  # @return [Boolean]
161
178
  def remove_stored_function(function_name)
162
- if self[SYSTEM_JS_COLLECTION].find_one({"_id" => function_name})
163
- self[SYSTEM_JS_COLLECTION].remove({"_id" => function_name}, :w => 1)
164
- else
165
- return false
166
- end
179
+ return false unless self[SYSTEM_JS_COLLECTION].find_one({"_id" => function_name})
180
+ self[SYSTEM_JS_COLLECTION].remove({"_id" => function_name}, :w => 1)
167
181
  end
168
182
 
169
183
  # Adds a user to this database for use with authentication. If the user already
@@ -181,7 +195,7 @@ module Mongo
181
195
  user['pwd'] = Mongo::Support.hash_password(username, password)
182
196
  user['readOnly'] = true if read_only;
183
197
  users.save(user)
184
- return user
198
+ user
185
199
  end
186
200
 
187
201
  # Remove the given user from this database. Returns false if the user
@@ -194,7 +208,7 @@ module Mongo
194
208
  if self[SYSTEM_USER_COLLECTION].find_one({:user => username})
195
209
  self[SYSTEM_USER_COLLECTION].remove({:user => username}, :w => 1)
196
210
  else
197
- return false
211
+ false
198
212
  end
199
213
  end
200
214
 
@@ -206,21 +220,17 @@ module Mongo
206
220
  #
207
221
  # @return [Boolean]
208
222
  def logout(opts={})
209
- if @connection.pool_size > 1
210
- @connection.logout_pools(@name)
211
- end
212
-
223
+ @connection.logout_pools(@name) if @connection.pool_size > 1
213
224
  issue_logout(opts)
214
225
  end
215
226
 
216
227
  def issue_logout(opts={})
217
- doc = command({:logout => 1}, :socket => opts[:socket])
218
- if ok?(doc)
228
+ if ok?(doc = command({:logout => 1}, :socket => opts[:socket]))
219
229
  @connection.remove_auth(@name)
220
- true
221
230
  else
222
- raise MongoDBError, "error logging out: #{doc.inspect}"
231
+ raise MongoDBError, "Error logging out: #{doc.inspect}"
223
232
  end
233
+ true
224
234
  end
225
235
 
226
236
  # Get an array of collection names in this database.
@@ -278,20 +288,19 @@ module Mongo
278
288
  # @return [Mongo::Collection]
279
289
  def create_collection(name, opts={})
280
290
  name = name.to_s
281
- if collection_names.include?(name)
282
- if strict?
283
- raise MongoDBError, "Collection #{name} already exists. " +
284
- "Currently in strict mode."
285
- else
286
- return Collection.new(name, self, opts)
287
- end
291
+ if strict? && collection_names.include?(name)
292
+ raise MongoDBError, "Collection '#{name}' already exists. (strict=true)"
288
293
  end
289
294
 
290
- # Create a new collection.
291
- oh = BSON::OrderedHash.new
292
- oh[:create] = name
293
- doc = command(oh.merge(opts || {}))
294
- return Collection.new(name, self, :pk => @pk_factory) if ok?(doc)
295
+ begin
296
+ cmd = BSON::OrderedHash.new
297
+ cmd[:create] = name
298
+ doc = command(cmd.merge(opts || {}))
299
+ return Collection.new(name, self, :pk => @pk_factory) if ok?(doc)
300
+ rescue OperationFailure => e
301
+ return Collection.new(name, self, :pk => @pk_factory) if e.message =~ /exists/
302
+ raise e
303
+ end
295
304
  raise MongoDBError, "Error creating collection: #{doc.inspect}"
296
305
  end
297
306
 
@@ -306,8 +315,7 @@ module Mongo
306
315
  # @return [Mongo::Collection]
307
316
  def collection(name, opts={})
308
317
  if strict? && !collection_names.include?(name.to_s)
309
- raise Mongo::MongoDBError, "Collection #{name} doesn't exist. " +
310
- "Currently in strict mode."
318
+ raise MongoDBError, "Collection '#{name}' doesn't exist. (strict=true)"
311
319
  else
312
320
  opts = opts.dup
313
321
  opts.merge!(:pk => @pk_factory) unless opts[:pk]
@@ -322,9 +330,12 @@ module Mongo
322
330
  #
323
331
  # @return [Boolean] +true+ on success or +false+ if the collection name doesn't exist.
324
332
  def drop_collection(name)
325
- return true unless collection_names.include?(name.to_s)
326
-
327
- ok?(command(:drop => name))
333
+ return false if strict? && !collection_names.include?(name.to_s)
334
+ begin
335
+ ok?(command(:drop => name))
336
+ rescue OperationFailure => e
337
+ false
338
+ end
328
339
  end
329
340
 
330
341
  # Run the getlasterror command with the specified replication options.
@@ -342,7 +353,7 @@ module Mongo
342
353
  cmd[:getlasterror] = 1
343
354
  cmd.merge!(opts)
344
355
  doc = command(cmd, :check_response => false)
345
- raise MongoDBError, "error retrieving last error: #{doc.inspect}" unless ok?(doc)
356
+ raise MongoDBError, "Error retrieving last error: #{doc.inspect}" unless ok?(doc)
346
357
  doc
347
358
  end
348
359
 
@@ -362,11 +373,7 @@ module Mongo
362
373
  # @return [String, Nil] the text of the error or +nil+ if no error has occurred.
363
374
  def previous_error
364
375
  error = command(:getpreverror => 1)
365
- if error["err"]
366
- error
367
- else
368
- nil
369
- end
376
+ error["err"] ? error : nil
370
377
  end
371
378
 
372
379
  # Reset the error history of this database
@@ -393,19 +400,19 @@ module Mongo
393
400
  # Evaluate a JavaScript expression in MongoDB.
394
401
  #
395
402
  # @param [String, Code] code a JavaScript expression to evaluate server-side.
396
- # @param [Integer, Hash] args any additional argument to be passed to the +code+ expression when
403
+ # @param [Integer, Hash] args any additional argument to be passed to the +code+ expression when
397
404
  # it's run on the server.
398
405
  #
399
406
  # @return [String] the return value of the function.
400
407
  def eval(code, *args)
401
- if not code.is_a? BSON::Code
408
+ unless code.is_a?(BSON::Code)
402
409
  code = BSON::Code.new(code)
403
410
  end
404
411
 
405
- oh = BSON::OrderedHash.new
406
- oh[:$eval] = code
407
- oh[:args] = args
408
- doc = command(oh)
412
+ cmd = BSON::OrderedHash.new
413
+ cmd[:$eval] = code
414
+ cmd[:args] = args
415
+ doc = command(cmd)
409
416
  doc['retval']
410
417
  end
411
418
 
@@ -418,10 +425,10 @@ module Mongo
418
425
  #
419
426
  # @raise MongoDBError if there's an error renaming the collection.
420
427
  def rename_collection(from, to)
421
- oh = BSON::OrderedHash.new
422
- oh[:renameCollection] = "#{@name}.#{from}"
423
- oh[:to] = "#{@name}.#{to}"
424
- doc = DB.new('admin', @connection).command(oh, :check_response => false)
428
+ cmd = BSON::OrderedHash.new
429
+ cmd[:renameCollection] = "#{@name}.#{from}"
430
+ cmd[:to] = "#{@name}.#{to}"
431
+ doc = DB.new('admin', @connection).command(cmd, :check_response => false)
425
432
  ok?(doc) || raise(MongoDBError, "Error renaming collection: #{doc.inspect}")
426
433
  end
427
434
 
@@ -435,10 +442,10 @@ module Mongo
435
442
  #
436
443
  # @raise MongoDBError if there's an error dropping the index.
437
444
  def drop_index(collection_name, index_name)
438
- oh = BSON::OrderedHash.new
439
- oh[:deleteIndexes] = collection_name
440
- oh[:index] = index_name.to_s
441
- doc = command(oh, :check_response => false)
445
+ cmd = BSON::OrderedHash.new
446
+ cmd[:deleteIndexes] = collection_name
447
+ cmd[:index] = index_name.to_s
448
+ doc = command(cmd, :check_response => false)
442
449
  ok?(doc) || raise(MongoDBError, "Error with drop_index command: #{doc.inspect}")
443
450
  end
444
451
 
@@ -447,7 +454,7 @@ module Mongo
447
454
  #
448
455
  # @param [String] collection_name
449
456
  #
450
- # @return [Hash] keys are index names and the values are lists of [key, direction] pairs
457
+ # @return [Hash] keys are index names and the values are lists of [key, type] pairs
451
458
  # defining the index.
452
459
  def index_information(collection_name)
453
460
  sel = {:ns => full_collection_name(collection_name)}
@@ -499,8 +506,9 @@ module Mongo
499
506
  # @core commands command_instance-method
500
507
  def command(selector, opts={})
501
508
  check_response = opts.fetch(:check_response, true)
502
- socket = opts[:socket]
503
- raise MongoArgumentError, "command must be given a selector" unless selector.is_a?(Hash) && !selector.empty?
509
+ socket = opts[:socket]
510
+ raise MongoArgumentError, "Command must be given a selector" unless selector.is_a?(Hash) && !selector.empty?
511
+
504
512
  if selector.keys.length > 1 && RUBY_VERSION < '1.9' && selector.class != BSON::OrderedHash
505
513
  raise MongoArgumentError, "DB#command requires an OrderedHash when hash contains multiple keys"
506
514
  end
@@ -513,19 +521,21 @@ module Mongo
513
521
  end
514
522
 
515
523
  begin
516
- result = Cursor.new(system_command_collection,
517
- :limit => -1,
518
- :selector => selector,
519
- :socket => socket,
520
- :read => read_pref,
521
- :comment => opts[:comment]).next_document
524
+ result = Cursor.new(
525
+ system_command_collection,
526
+ :limit => -1,
527
+ :selector => selector,
528
+ :socket => socket,
529
+ :read => read_pref,
530
+ :comment => opts[:comment]).next_document
522
531
  rescue OperationFailure => ex
523
532
  raise OperationFailure, "Database command '#{selector.keys.first}' failed: #{ex.message}"
524
533
  end
525
534
 
526
- if result.nil?
527
- raise OperationFailure, "Database command '#{selector.keys.first}' failed: returned null."
528
- elsif (check_response && !ok?(result))
535
+ raise OperationFailure,
536
+ "Database command '#{selector.keys.first}' failed: returned null." unless result
537
+
538
+ if check_response && !ok?(result)
529
539
  message = "Database command '#{selector.keys.first}' failed: ("
530
540
  message << result.map do |key, value|
531
541
  "#{key}: '#{value}'"
@@ -533,9 +543,9 @@ module Mongo
533
543
  message << ').'
534
544
  code = result['code'] || result['assertionCode']
535
545
  raise OperationFailure.new(message, code, result)
536
- else
537
- result
538
546
  end
547
+
548
+ result
539
549
  end
540
550
 
541
551
  # A shortcut returning db plus dot plus collection name.
@@ -558,9 +568,8 @@ module Mongo
558
568
  #
559
569
  # @raise [MongoArgumentError] if the primary key factory has already been set.
560
570
  def pk_factory=(pk_factory)
561
- if @pk_factory
562
- raise MongoArgumentError, "Cannot change primary key factory once it's been set"
563
- end
571
+ raise MongoArgumentError,
572
+ "Cannot change primary key factory once it's been set" if @pk_factory
564
573
 
565
574
  @pk_factory = pk_factory
566
575
  end
@@ -572,20 +581,15 @@ module Mongo
572
581
  #
573
582
  # @core profiling profiling_level-instance_method
574
583
  def profiling_level
575
- oh = BSON::OrderedHash.new
576
- oh[:profile] = -1
577
- doc = command(oh, :check_response => false)
578
- raise "Error with profile command: #{doc.inspect}" unless ok?(doc) && doc['was'].kind_of?(Numeric)
579
- case doc['was'].to_i
580
- when 0
581
- :off
582
- when 1
583
- :slow_only
584
- when 2
585
- :all
586
- else
587
- raise "Error: illegal profiling level value #{doc['was']}"
588
- end
584
+ cmd = BSON::OrderedHash.new
585
+ cmd[:profile] = -1
586
+ doc = command(cmd, :check_response => false)
587
+
588
+ raise "Error with profile command: #{doc.inspect}" unless ok?(doc)
589
+
590
+ level_sym = PROFILE_LEVEL.invert[doc['was'].to_i]
591
+ raise "Error: illegal profiling level value #{doc['was']}" unless level_sym
592
+ level_sym
589
593
  end
590
594
 
591
595
  # Set this database's profiling level. If profiling is enabled, you can
@@ -593,18 +597,9 @@ module Mongo
593
597
  #
594
598
  # @param [Symbol] level acceptable options are +:off+, +:slow_only+, or +:all+.
595
599
  def profiling_level=(level)
596
- oh = BSON::OrderedHash.new
597
- oh[:profile] = case level
598
- when :off
599
- 0
600
- when :slow_only
601
- 1
602
- when :all
603
- 2
604
- else
605
- raise "Error: illegal profiling level value #{level}"
606
- end
607
- doc = command(oh, :check_response => false)
600
+ cmd = BSON::OrderedHash.new
601
+ cmd[:profile] = PROFILE_LEVEL[level]
602
+ doc = command(cmd, :check_response => false)
608
603
  ok?(doc) || raise(MongoDBError, "Error with profile command: #{doc.inspect}")
609
604
  end
610
605
 
@@ -628,9 +623,9 @@ module Mongo
628
623
  cmd[:validate] = name
629
624
  cmd[:full] = true
630
625
  doc = command(cmd, :check_response => false)
631
- if !ok?(doc)
632
- raise MongoDBError, "Error with validate command: #{doc.inspect}"
633
- end
626
+
627
+ raise MongoDBError, "Error with validate command: #{doc.inspect}" unless ok?(doc)
628
+
634
629
  if (doc.has_key?('valid') && !doc['valid']) || (doc['result'] =~ /\b(exception|corrupt)\b/i)
635
630
  raise MongoDBError, "Error: invalid collection #{name}: #{doc.inspect}"
636
631
  end