mongo 1.10.2 → 1.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +43 -9
  5. data/VERSION +1 -1
  6. data/lib/mongo.rb +1 -0
  7. data/lib/mongo/collection.rb +36 -21
  8. data/lib/mongo/connection/pool.rb +14 -22
  9. data/lib/mongo/cursor.rb +13 -0
  10. data/lib/mongo/db.rb +18 -13
  11. data/lib/mongo/functional.rb +0 -2
  12. data/lib/mongo/functional/authentication.rb +35 -25
  13. data/lib/mongo/legacy.rb +4 -4
  14. data/mongo.gemspec +0 -5
  15. data/test/functional/authentication_test.rb +3 -2
  16. data/test/functional/bulk_write_collection_view_test.rb +9 -14
  17. data/test/functional/client_test.rb +42 -43
  18. data/test/functional/collection_test.rb +1073 -995
  19. data/test/functional/collection_writer_test.rb +1 -1
  20. data/test/functional/cursor_fail_test.rb +3 -9
  21. data/test/functional/cursor_message_test.rb +14 -15
  22. data/test/functional/cursor_test.rb +224 -166
  23. data/test/functional/db_api_test.rb +262 -261
  24. data/test/functional/db_connection_test.rb +1 -3
  25. data/test/functional/db_test.rb +116 -115
  26. data/test/functional/grid_file_system_test.rb +108 -108
  27. data/test/functional/pool_test.rb +73 -0
  28. data/test/functional/timeout_test.rb +2 -0
  29. data/test/helpers/test_unit.rb +146 -11
  30. data/test/replica_set/authentication_test.rb +4 -2
  31. data/test/replica_set/basic_test.rb +5 -13
  32. data/test/replica_set/client_test.rb +8 -6
  33. data/test/replica_set/complex_connect_test.rb +3 -0
  34. data/test/replica_set/count_test.rb +2 -0
  35. data/test/replica_set/cursor_test.rb +5 -0
  36. data/test/replica_set/insert_test.rb +1 -1
  37. data/test/replica_set/max_values_test.rb +1 -1
  38. data/test/replica_set/pinning_test.rb +1 -1
  39. data/test/replica_set/query_test.rb +1 -1
  40. data/test/replica_set/read_preference_test.rb +7 -1
  41. data/test/replica_set/refresh_test.rb +11 -8
  42. data/test/replica_set/replication_ack_test.rb +2 -1
  43. data/test/sharded_cluster/basic_test.rb +17 -11
  44. data/test/shared/authentication/basic_auth_shared.rb +59 -98
  45. data/test/shared/authentication/bulk_api_auth_shared.rb +11 -21
  46. data/test/shared/authentication/gssapi_shared.rb +28 -21
  47. data/test/test_helper.rb +5 -0
  48. data/test/tools/mongo_config.rb +96 -11
  49. metadata +4 -5
  50. metadata.gz.sig +0 -0
  51. data/lib/mongo/functional/sasl_java.rb +0 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1a1eba07acbd5cbdc1ea149bee675c8cb19414fc
4
- data.tar.gz: 94ede5709c9ed0d5aef5e05e19f6a4c90f5cc1d1
3
+ metadata.gz: 047647bfd88def86157a8e4e25df514da21a1364
4
+ data.tar.gz: 7fd48a7694323f7e4759b94f12058b5e34a6bba4
5
5
  SHA512:
6
- metadata.gz: 007196c1e574ed834d0cdf44cde761220a531367d303aa1f074955ac112af6cf16a43943f466a00f1b7e955902e702d0ca99c67a33571d9341095b7258d4ef57
7
- data.tar.gz: b8fcc33bf2f9119ada0e8b5c3010ad9246dd7cc32daa6240980955dd680ddd4b8474e92f3ea0fcbe9178042e6536e324d42d6a476c9ef042563f2509d35068c2
6
+ metadata.gz: 3b360776478001d2b41342764c13dd209954c0bbcf73c5b87dc4f2169d3e42bd27c6650514ca281a1146c33d1d2624edf653cf8ddd51e3ff8f9e37c9bf4505d3
7
+ data.tar.gz: e4a9d033eb058e0424ecae35599a27be0a7c68e56b2a0557dcbc42a331e940a0c42c73f0b1c1eeb3b76d977fe63a84df5b7310bc001feeb2f8441518e163b2eb
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -37,6 +37,17 @@ bundle install
37
37
  rake install
38
38
  ```
39
39
 
40
+ To be able to use the driver with Kerberos authentication enabled, install the
41
+ `mongo_kerberos` gem and add it instead of mongo to your application:
42
+
43
+ ```bash
44
+ gem install mongo_kerberos
45
+ ```
46
+
47
+ ```ruby
48
+ require 'mongo_kerberos'
49
+ ```
50
+
40
51
  Usage
41
52
  -----
42
53
  Here is a quick example of basic usage for the Ruby driver:
@@ -84,10 +95,10 @@ MRI 1.8.7, 1.9.3, 2.0.0<br>JRuby 1.7.x | Windows<br>Linux<br>OS X | x86<br>x64<b
84
95
  Support & Feedback
85
96
  -----
86
97
 
87
- For issues, questions or feedback related to the Ruby driver, please look into
88
- our [support channels](http://www.mongodb.org/about/support). Please
89
- do not email any of the Ruby developers directly with issues or
90
- questions - you're more likely to get an answer quickly on the [mongodb-user list](http://groups.google.com/group/mongodb-user) on Google Groups.
98
+ **Support Channels**
99
+
100
+ For issues, questions or feedback related to the Ruby driver, please look into our [support channels](http://www.mongodb.org/about/support).
101
+ Please do not email any of the Ruby developers directly with issues or questions. You'll get a quicker answer on the [mongodb-user list](http://groups.google.com/group/mongodb-user) Google Group.
91
102
 
92
103
  Bugs & Feature Requests
93
104
  -----
@@ -100,18 +111,41 @@ Do you have a bug to report or a feature request to make?
100
111
 
101
112
  When reporting an issue, please keep in mind that all information in JIRA for all driver projects (ex. RUBY, CSHARP, JAVA) and the Core Server (ex. SERVER) project is **PUBLICLY** visible.
102
113
 
103
- **PLEASE DO**
114
+ **HOW TO ASK FOR HELP**
104
115
 
105
- * Provide as much information as possible about the issue.
106
- * Provide detailed steps for reproducing the issue.
107
- * Provide any applicable code snippets, stack traces and log data.
108
- * Specify version information for the driver and MongoDB.
116
+ Providing enough information so we can reproduce the issue immediately will reduce roundtrip communications and get you a useful response as quickly as possible.
117
+ That said, please provide the following information when logging an issue:
118
+
119
+ 1. Environment
120
+ 2. Ruby version, including patch-level
121
+ 3. MongoDB version
122
+ 4. A test case or code snippets
123
+ 5. Stack traces and log data, keeping in mind that this info is public
109
124
 
110
125
  **PLEASE DO NOT**
111
126
 
112
127
  * Provide any sensitive data or server logs.
113
128
  * Report potential security issues publicly (see 'Security Issues').
114
129
 
130
+ **EXAMPLE BUG REPORT**
131
+
132
+ Example taken from [RUBY-775](https://jira.mongodb.org/browse/RUBY-775)
133
+
134
+ ```
135
+ There appears to be a recursive locking condition in the replica set connection pooling.
136
+
137
+ Environment: AWS Linux 3.10.37-47.135.amzn1.x86_64 / jruby-1.7.12 / JDK java-1.7.0-openjdk-1.7.0.55-2.4.7.1.40.amzn1.x86_64
138
+
139
+ Component: Connection Pooling / Replica set
140
+
141
+ Here is a stack trace:
142
+ https://gist.githubusercontent.com/cheald/5ed01172c5b2c9943c87/raw/63075158dac4c78c1775cac8bf84ba3b6537bc1e/gistfile1.txt
143
+
144
+ The original lock occurs [here](https://github.com/mongodb/mongo-ruby-driver/blob/1.x-stable/lib/mongo/connection/pool_manager.rb#L60)
145
+
146
+ and then the process of reconnecting ends up attempting to resynchronize the same lock [here](https://github.com/mongodb/mongo-ruby-driver/blob/1.x-stable/lib/mongo/connection/pool_manager.rb#L150)
147
+ ```
148
+
115
149
  Security Issues
116
150
  -----
117
151
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.10.2
1
+ 1.11.1
@@ -64,6 +64,7 @@ module Mongo
64
64
  INVALID_BSON = 22
65
65
  WRITE_CONCERN_FAILED = 64
66
66
  MULTIPLE_ERRORS_OCCURRED = 65
67
+ UNAUTHORIZED = 13
67
68
 
68
69
  # mongod/s 2.6 and above return code 59 when a command doesn't exist.
69
70
  # mongod versions previous to 2.6 and mongos 2.4.x return no error code
@@ -518,8 +518,9 @@ module Mongo
518
518
  # @option opts [Boolean] :unique (false) if true, this index will enforce a uniqueness constraint.
519
519
  # @option opts [Boolean] :background (false) indicate that the index should be built in the background. This
520
520
  # feature is only available in MongoDB >= 1.3.2.
521
- # @option opts [Boolean] :drop_dups (nil) If creating a unique index on a collection with pre-existing records,
522
- # this option will keep the first document the database indexes and drop all subsequent with duplicate values.
521
+ # @option opts [Boolean] :drop_dups (nil) (DEPRECATED) If creating a unique index on a collection with
522
+ # pre-existing records, this option will keep the first document the database indexes and drop all subsequent
523
+ # with duplicate values.
523
524
  # @option opts [Integer] :bucket_size (nil) For use with geoHaystack indexes. Number of documents to group
524
525
  # together within a certain proximity to a given longitude and latitude.
525
526
  # @option opts [Integer] :min (nil) specify the minimum longitude and latitude for a geo index.
@@ -545,15 +546,19 @@ module Mongo
545
546
  # @example A geospatial index with alternate longitude and latitude:
546
547
  # @restaurants.create_index([['location', Mongo::GEO2D]], :min => 500, :max => 500)
547
548
  #
549
+ # @note The :drop_dups option is no longer supported by MongoDB starting with server version 2.7.5.
550
+ # The option is silently ignored by the server and unique index builds using the option will
551
+ # fail if a duplicate value is detected.
552
+ #
548
553
  # @return [String] the name of the index created.
549
554
  def create_index(spec, opts={})
550
- opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
551
- opts[:bucketSize] = opts[:bucket_size] if opts[:bucket_size]
552
- field_spec = parse_index_spec(spec)
553
- opts = opts.dup
554
- name = opts.delete(:name) || generate_index_name(field_spec)
555
- name = name.to_s if name
556
- generate_indexes(field_spec, name, opts)
555
+ options = opts.dup
556
+ options[:dropDups] = options.delete(:drop_dups) if options[:drop_dups]
557
+ options[:bucketSize] = options.delete(:bucket_size) if options[:bucket_size]
558
+ field_spec = parse_index_spec(spec)
559
+ name = options.delete(:name) || generate_index_name(field_spec)
560
+ name = name.to_s if name
561
+ generate_indexes(field_spec, name, options)
557
562
  name
558
563
  end
559
564
 
@@ -572,17 +577,22 @@ module Mongo
572
577
  # Time t+10min : @posts.ensure_index(:subject => Mongo::ASCENDING) -- calls create_index and
573
578
  # resets the 5 minute counter
574
579
  #
580
+ # @note The :drop_dups option is no longer supported by MongoDB starting with server version 2.7.5.
581
+ # The option is silently ignored by the server and unique index builds using the option will
582
+ # fail if a duplicate value is detected.
583
+ #
575
584
  # @return [String] the name of the index.
576
585
  def ensure_index(spec, opts={})
577
- now = Time.now.utc.to_i
578
- opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
579
- opts[:bucketSize] = opts[:bucket_size] if opts[:bucket_size]
580
- field_spec = parse_index_spec(spec)
581
- name = opts[:name] || generate_index_name(field_spec)
582
- name = name.to_s if name
586
+ now = Time.now.utc.to_i
587
+ options = opts.dup
588
+ options[:dropDups] = options.delete(:drop_dups) if options[:drop_dups]
589
+ options[:bucketSize] = options.delete(:bucket_size) if options[:bucket_size]
590
+ field_spec = parse_index_spec(spec)
591
+ name = options.delete(:name) || generate_index_name(field_spec)
592
+ name = name.to_s if name
583
593
 
584
594
  if !@cache[name] || @cache[name] <= now
585
- generate_indexes(field_spec, name, opts)
595
+ generate_indexes(field_spec, name, options)
586
596
  end
587
597
 
588
598
  # Reset the cache here in case there are any errors inserting. Best to be safe.
@@ -1029,6 +1039,10 @@ module Mongo
1029
1039
  # @option opts [Hash] :query ({}) A query selector for filtering the documents counted.
1030
1040
  # @option opts [Integer] :skip (nil) The number of documents to skip.
1031
1041
  # @option opts [Integer] :limit (nil) The number of documents to limit.
1042
+ # @option opts [String, Array, OrderedHash] :hint hint for query optimizer, usually not necessary if
1043
+ # using MongoDB > 1.1. This option is only supported with #count in server version > 2.6.
1044
+ # @option opts [String] :named_hint for specifying a named index as a hint, will be overridden by :hint
1045
+ # if :hint is also provided. This option is only supported with #count in server version > 2.6.
1032
1046
  # @option opts [:primary, :secondary] :read Read preference for this command. See Collection#find for
1033
1047
  # more details.
1034
1048
  # @option opts [String] :comment (nil) a comment to include in profiling logs
@@ -1036,12 +1050,13 @@ module Mongo
1036
1050
  # @return [Integer]
1037
1051
  def count(opts={})
1038
1052
  find(opts[:query],
1039
- :skip => opts[:skip],
1040
- :limit => opts[:limit],
1041
- :read => opts[:read],
1042
- :comment => opts[:comment]).count(true)
1053
+ :skip => opts[:skip],
1054
+ :limit => opts[:limit],
1055
+ :named_hint => opts[:named_hint] || @hint,
1056
+ :hint => opts[:hint] || @hint,
1057
+ :read => opts[:read],
1058
+ :comment => opts[:comment]).count(true)
1043
1059
  end
1044
-
1045
1060
  alias :size :count
1046
1061
 
1047
1062
  protected
@@ -182,10 +182,6 @@ module Mongo
182
182
  raise ConnectionFailure, "Failed to connect to host #{@host} and port #{@port}: #{ex}"
183
183
  end
184
184
 
185
- # If any saved authentications exist, we want to apply those
186
- # when creating new sockets and process logouts.
187
- check_auths(socket)
188
-
189
185
  @sockets << socket
190
186
  @checked_out << socket
191
187
  @thread_ids_to_sockets[Thread.current.object_id] = socket
@@ -199,12 +195,8 @@ module Mongo
199
195
  #
200
196
  # @deprecated This method has been replaced by Pool#check_auths (private)
201
197
  # and it isn't necessary to ever invoke this method directly.
198
+ # Authentication of sockets is handled upon checkout and checkin.
202
199
  def authenticate_existing
203
- @connection_mutex.synchronize do
204
- @sockets.each do |socket|
205
- check_auths(socket)
206
- end
207
- end
208
200
  end
209
201
 
210
202
  # Store the logout op for each existing socket to be applied before
@@ -212,12 +204,8 @@ module Mongo
212
204
  #
213
205
  # @deprecated This method has been replaced by Pool#check_auths (private)
214
206
  # and it isn't necessary to ever invoke this method directly.
207
+ # Authentication of sockets is handled upon checkout and checkin.
215
208
  def logout_existing(database)
216
- @connection_mutex.synchronize do
217
- @sockets.each do |socket|
218
- check_auths(socket)
219
- end
220
- end
221
209
  end
222
210
 
223
211
  # Checks out the first available socket from the pool.
@@ -291,16 +279,20 @@ module Mongo
291
279
  end
292
280
 
293
281
  if socket
294
- check_auths(socket)
295
-
296
- if socket.closed?
297
- @checked_out.delete(socket)
298
- @sockets.delete(socket)
299
- @thread_ids_to_sockets.delete(Thread.current.object_id)
300
- socket = checkout_new_socket
282
+ if !socket.closed?
283
+ begin
284
+ check_auths(socket)
285
+ return socket
286
+ rescue ConnectionFailure
287
+ # Socket failed authentication and will be cleaned up below
288
+ end
301
289
  end
302
290
 
303
- return socket
291
+ # Socket was closed from earlier network error, or just now from
292
+ # a network error when authenticating.
293
+ @checked_out.delete(socket)
294
+ @sockets.delete(socket)
295
+ @thread_ids_to_sockets.delete(Thread.current.object_id)
304
296
  else
305
297
  # Otherwise, wait
306
298
  @queue.wait(@connection_mutex)
@@ -203,7 +203,12 @@ module Mongo
203
203
  command.merge!(BSON::OrderedHash["skip", @skip]) if @skip != 0
204
204
  end
205
205
 
206
+ if @hint
207
+ hint = @hint.is_a?(String) ? @hint : generate_index_name(@hint)
208
+ end
209
+
206
210
  command.merge!(BSON::OrderedHash["fields", @fields])
211
+ command.merge!(BSON::OrderedHash["hint", hint]) if hint
207
212
 
208
213
  response = @db.command(command, :read => @read, :comment => @comment)
209
214
  return response['n'].to_i if Mongo::Support.ok?(response)
@@ -715,5 +720,13 @@ module Mongo
715
720
  def compile_regex?
716
721
  @compile_regex
717
722
  end
723
+
724
+ def generate_index_name(spec)
725
+ indexes = []
726
+ spec.each_pair do |field, type|
727
+ indexes.push("#{field}_#{type}")
728
+ end
729
+ indexes.join("_")
730
+ end
718
731
  end
719
732
  end
@@ -156,7 +156,6 @@ module Mongo
156
156
  warn "[DEPRECATED] Disabling the 'save_auth' option no longer has " +
157
157
  "any effect. Please see the API documentation for more details " +
158
158
  "on this change." unless save_auth.nil?
159
-
160
159
  @client.add_auth(self.name, username, password, source, mechanism, extra)
161
160
  true
162
161
  end
@@ -220,19 +219,25 @@ module Mongo
220
219
  def add_user(username, password=nil, read_only=false, opts={})
221
220
  begin
222
221
  user_info = command(:usersInfo => username)
223
- # MongoDB >= 2.5.3 requires the use of commands to manage users.
224
- # "Command not found" error didn't return an error code (59) before
225
- # MongoDB 2.4.7 so we assume that a nil error code means the usersInfo
226
- # command doesn't exist and we should fall back to the legacy add user code.
222
+ if user_info.key?('users') && !user_info['users'].empty?
223
+ create_or_update_user(:updateUser, username, password, read_only, opts)
224
+ else
225
+ create_or_update_user(:createUser, username, password, read_only, opts)
226
+ end
227
+ # MongoDB >= 2.5.3 requires the use of commands to manage users.
228
+ # "Command not found" error didn't return an error code (59) before
229
+ # MongoDB 2.4.7 so we assume that a nil error code means the usersInfo
230
+ # command doesn't exist and we should fall back to the legacy add user code.
227
231
  rescue OperationFailure => ex
228
- raise ex unless Mongo::ErrorCode::COMMAND_NOT_FOUND_CODES.include?(ex.error_code)
229
- return legacy_add_user(username, password, read_only, opts)
230
- end
231
-
232
- if user_info.key?('users') && !user_info['users'].empty?
233
- create_or_update_user(:updateUser, username, password, read_only, opts)
234
- else
235
- create_or_update_user(:createUser, username, password, read_only, opts)
232
+ if Mongo::ErrorCode::COMMAND_NOT_FOUND_CODES.include?(ex.error_code)
233
+ legacy_add_user(username, password, read_only, opts)
234
+ elsif ex.error_code == Mongo::ErrorCode::UNAUTHORIZED
235
+ # In MongoDB > 2.7 the localhost exception was narrowed, and the usersInfo
236
+ # command is no longer allowed. In this case, add the first user.
237
+ create_or_update_user(:createUser, username, password, read_only, opts)
238
+ else
239
+ raise ex
240
+ end
236
241
  end
237
242
  end
238
243
 
@@ -17,5 +17,3 @@ require 'mongo/functional/logging'
17
17
  require 'mongo/functional/read_preference'
18
18
  require 'mongo/functional/write_concern'
19
19
  require 'mongo/functional/uri_parser'
20
-
21
- require 'mongo/functional/sasl_java' if RUBY_PLATFORM =~ /java/
@@ -166,12 +166,12 @@ module Mongo
166
166
  # @param db_name [String] The database name.
167
167
  # @param opts [Hash] Hash of optional settings and configuration values.
168
168
  #
169
- # @option opts [Socket] socket (nil) Optional socket instance to use.
169
+ # @option opts [Socket] socket Socket instance to use.
170
170
  #
171
171
  # @raise [MongoDBError] Raised if the logout operation fails.
172
172
  # @return [Boolean] The result of the logout operation.
173
173
  def issue_logout(db_name, opts={})
174
- doc = db(db_name).command({:logout => 1}, :socket => opts[:socket])
174
+ doc = auth_command({:logout => 1}, opts[:socket], db_name).first
175
175
  unless Support.ok?(doc)
176
176
  raise MongoDBError, "Error logging out on DB #{db_name}."
177
177
  end
@@ -185,7 +185,7 @@ module Mongo
185
185
  # @param auth [Hash] The authentication credentials to be used.
186
186
  # @param opts [Hash] Hash of optional settings and configuration values.
187
187
  #
188
- # @option opts [Socket] socket (nil) Optional socket instance to use.
188
+ # @option opts [Socket] socket Socket instance to use.
189
189
  #
190
190
  # @raise [AuthenticationError] Raised if the authentication fails.
191
191
  # @return [Boolean] Result of the authentication operation.
@@ -217,14 +217,14 @@ module Mongo
217
217
  # @param auth [Hash] The authentication credentials to be used.
218
218
  # @param opts [Hash] Hash of optional settings and configuration values.
219
219
  #
220
- # @option opts [Socket] socket (nil) Optional socket instance to use.
220
+ # @option opts [Socket] socket Socket instance to use.
221
221
  #
222
222
  # @return [Boolean] Result of the authentication operation.
223
223
  #
224
224
  # @private
225
225
  def issue_cr(auth, opts={})
226
- database = db(auth[:source])
227
- nonce = get_nonce(database, opts)
226
+ db_name = auth[:source]
227
+ nonce = get_nonce(auth[:source], opts)
228
228
 
229
229
  # build auth command document
230
230
  cmd = BSON::OrderedHash.new
@@ -234,9 +234,7 @@ module Mongo
234
234
  cmd['key'] = Authentication.auth_key(auth[:username],
235
235
  auth[:password],
236
236
  nonce)
237
-
238
- database.command(cmd, :check_response => false,
239
- :socket => opts[:socket])
237
+ auth_command(cmd, opts[:socket], db_name).first
240
238
  end
241
239
 
242
240
  # Handles issuing authentication commands for the MONGODB-X509 auth mechanism.
@@ -246,15 +244,14 @@ module Mongo
246
244
  #
247
245
  # @private
248
246
  def issue_x509(auth, opts={})
249
- database = db('$external')
247
+ db_name = '$external'
250
248
 
251
249
  cmd = BSON::OrderedHash.new
252
250
  cmd[:authenticate] = 1
253
251
  cmd[:mechanism] = auth[:mechanism]
254
252
  cmd[:user] = auth[:username]
255
253
 
256
- database.command(cmd, :check_response => false,
257
- :socket => opts[:socket])
254
+ auth_command(cmd, opts[:socket], db_name).first
258
255
  end
259
256
 
260
257
  # Handles issuing authentication commands for the PLAIN auth mechanism.
@@ -262,14 +259,14 @@ module Mongo
262
259
  # @param auth [Hash] The authentication credentials to be used.
263
260
  # @param opts [Hash] Hash of optional settings and configuration values.
264
261
  #
265
- # @option opts [Socket] socket (nil) Optional socket instance to use.
262
+ # @option opts [Socket] socket Socket instance to use.
266
263
  #
267
264
  # @return [Boolean] Result of the authentication operation.
268
265
  #
269
266
  # @private
270
267
  def issue_plain(auth, opts={})
271
- database = db(auth[:source])
272
- payload = "\x00#{auth[:username]}\x00#{auth[:password]}"
268
+ db_name = auth[:source]
269
+ payload = "\x00#{auth[:username]}\x00#{auth[:password]}"
273
270
 
274
271
  cmd = BSON::OrderedHash.new
275
272
  cmd[:saslStart] = 1
@@ -277,8 +274,7 @@ module Mongo
277
274
  cmd[:payload] = BSON::Binary.new(payload)
278
275
  cmd[:autoAuthorize] = 1
279
276
 
280
- database.command(cmd, :check_response => false,
281
- :socket => opts[:socket])
277
+ auth_command(cmd, opts[:socket], db_name).first
282
278
  end
283
279
 
284
280
  # Handles issuing authentication commands for the GSSAPI auth mechanism.
@@ -288,10 +284,7 @@ module Mongo
288
284
  #
289
285
  # @private
290
286
  def issue_gssapi(auth, opts={})
291
- raise NotImplementedError,
292
- "The #{auth[:mechanism]} authentication mechanism is only supported " +
293
- "for JRuby." unless RUBY_PLATFORM =~ /java/
294
- Mongo::Sasl::GSSAPI.authenticate(auth[:username], self, opts[:socket], auth[:extra] || {})
287
+ raise "In order to use Kerberos, please add the mongo-kerberos gem to your dependencies"
295
288
  end
296
289
 
297
290
  # Helper to fetch a nonce value from a given database instance.
@@ -299,20 +292,37 @@ module Mongo
299
292
  # @param database [Mongo::DB] The DB instance to use for issue the nonce command.
300
293
  # @param opts [Hash] Hash of optional settings and configuration values.
301
294
  #
302
- # @option opts [Socket] socket (nil) Optional socket instance to use.
295
+ # @option opts [Socket] socket Socket instance to use.
303
296
  #
304
297
  # @raise [MongoDBError] Raised if there is an error executing the command.
305
298
  # @return [String] Returns the nonce value.
306
299
  #
307
300
  # @private
308
- def get_nonce(database, opts={})
309
- doc = database.command({:getnonce => 1}, :check_response => false,
310
- :socket => opts[:socket])
301
+ def get_nonce(db_name, opts={})
302
+ cmd = BSON::OrderedHash.new
303
+ cmd[:getnonce] = 1
304
+ doc = auth_command(cmd, opts[:socket], db_name).first
305
+
311
306
  unless Support.ok?(doc)
312
307
  raise MongoDBError, "Error retrieving nonce: #{doc}"
313
308
  end
314
309
  doc['nonce']
315
310
  end
316
311
 
312
+ def auth_command(selector, socket, db_name)
313
+ begin
314
+ message = build_command_message(db_name, selector)
315
+ request_id = add_message_headers(message, Mongo::Constants::OP_QUERY)
316
+ packed_message = message.to_s
317
+
318
+ send_message_on_socket(packed_message, socket)
319
+ receive(socket, request_id).shift
320
+ rescue OperationFailure => ex
321
+ return ex.result
322
+ rescue ConnectionFailure, OperationTimeout => ex
323
+ socket.close
324
+ raise ex
325
+ end
326
+ end
317
327
  end
318
328
  end