mongo 1.10.0.rc0 → 1.10.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/VERSION +1 -1
  5. data/lib/mongo/bulk_write_collection_view.rb +31 -3
  6. data/lib/mongo/collection.rb +69 -25
  7. data/lib/mongo/collection_writer.rb +3 -2
  8. data/lib/mongo/connection/node.rb +5 -0
  9. data/lib/mongo/cursor.rb +4 -1
  10. data/lib/mongo/db.rb +23 -41
  11. data/lib/mongo/functional.rb +2 -0
  12. data/lib/mongo/functional/authentication.rb +18 -3
  13. data/lib/mongo/functional/sasl_java.rb +48 -0
  14. data/lib/mongo/functional/uri_parser.rb +62 -50
  15. data/lib/mongo/mongo_client.rb +24 -9
  16. data/lib/mongo/mongo_replica_set_client.rb +16 -5
  17. data/lib/mongo/networking.rb +3 -3
  18. data/lib/mongo/utils/conversions.rb +2 -1
  19. data/test/functional/authentication_test.rb +6 -1
  20. data/test/functional/bulk_api_stress_test.rb +133 -0
  21. data/test/functional/bulk_write_collection_view_test.rb +573 -226
  22. data/test/functional/client_test.rb +3 -1
  23. data/test/functional/collection_test.rb +336 -17
  24. data/test/functional/conversions_test.rb +32 -0
  25. data/test/functional/cursor_test.rb +3 -3
  26. data/test/functional/db_api_test.rb +2 -2
  27. data/test/functional/db_test.rb +24 -0
  28. data/test/functional/uri_test.rb +49 -32
  29. data/test/helpers/test_unit.rb +8 -0
  30. data/test/replica_set/authentication_test.rb +5 -1
  31. data/test/replica_set/client_test.rb +5 -4
  32. data/test/replica_set/max_values_test.rb +6 -0
  33. data/test/shared/authentication/basic_auth_shared.rb +101 -30
  34. data/test/shared/authentication/bulk_api_auth_shared.rb +259 -0
  35. data/test/shared/authentication/gssapi_shared.rb +164 -0
  36. data/test/shared/ssl_shared.rb +49 -27
  37. data/test/unit/client_test.rb +4 -2
  38. data/test/unit/connection_test.rb +4 -2
  39. data/test/unit/cursor_test.rb +12 -0
  40. data/test/unit/db_test.rb +6 -0
  41. metadata +27 -20
  42. metadata.gz.sig +0 -0
@@ -17,3 +17,5 @@ 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/
@@ -19,6 +19,7 @@ module Mongo
19
19
 
20
20
  DEFAULT_MECHANISM = 'MONGODB-CR'
21
21
  MECHANISMS = ['GSSAPI', 'MONGODB-CR', 'MONGODB-X509', 'PLAIN']
22
+ EXTRA = { 'GSSAPI' => [:gssapi_service_name, :canonicalize_host_name] }
22
23
 
23
24
  # authentication module methods
24
25
  class << self
@@ -59,6 +60,15 @@ module Mongo
59
60
  "When using the authentication mechanism #{auth[:mechanism]} " +
60
61
  "both username and password are required."
61
62
  end
63
+ # if extra opts exist, validate them
64
+ allowed_keys = EXTRA[auth[:mechanism]]
65
+ if auth[:extra] && !auth[:extra].empty?
66
+ invalid_opts = []
67
+ auth[:extra].keys.each { |k| invalid_opts << k unless allowed_keys.include?(k) }
68
+ raise MongoArgumentError,
69
+ "Invalid extra option(s): #{invalid_opts} found. Please check the extra options" +
70
+ " passed and try again." unless invalid_opts.empty?
71
+ end
62
72
  auth
63
73
  end
64
74
 
@@ -95,19 +105,22 @@ module Mongo
95
105
  # (if different than the current database).
96
106
  # @param mechanism [String] (nil) The authentication mechanism being used
97
107
  # (default: 'MONGODB-CR').
108
+ # @param extra [Hash] (nil) A optional hash of extra options to be stored with
109
+ # the credential set.
98
110
  #
99
111
  # @raise [MongoArgumentError] Raised if the database has already been used
100
112
  # for authentication. A log out is required before additional auths can
101
113
  # be issued against a given database.
102
114
  # @raise [AuthenticationError] Raised if authentication fails.
103
115
  # @return [Hash] a hash representing the authentication just added.
104
- def add_auth(db_name, username, password=nil, source=nil, mechanism=nil)
116
+ def add_auth(db_name, username, password=nil, source=nil, mechanism=nil, extra=nil)
105
117
  auth = Authentication.validate_credentials({
106
118
  :db_name => db_name,
107
119
  :username => username,
108
120
  :password => password,
109
121
  :source => source,
110
- :mechanism => mechanism
122
+ :mechanism => mechanism,
123
+ :extra => extra
111
124
  })
112
125
 
113
126
  if @auths.any? {|a| a[:source] == auth[:source]}
@@ -276,7 +289,9 @@ module Mongo
276
289
  # @private
277
290
  def issue_gssapi(auth, opts={})
278
291
  raise NotImplementedError,
279
- "The #{auth[:mechanism]} authentication mechanism is not yet supported."
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] || {})
280
295
  end
281
296
 
282
297
  # Helper to fetch a nonce value from a given database instance.
@@ -0,0 +1,48 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'jruby'
16
+
17
+ include Java
18
+
19
+ jar_dir = File.join(File.dirname(__FILE__), '../../../ext/jsasl')
20
+ require File.join(jar_dir, 'target/jsasl.jar')
21
+
22
+ module Mongo
23
+ module Sasl
24
+
25
+ module GSSAPI
26
+
27
+ def self.authenticate(username, client, socket, opts={})
28
+ db = client.db('$external')
29
+ hostname = socket.pool.host
30
+ servicename = opts[:gssapi_service_name] || 'mongodb'
31
+ canonicalize = opts[:canonicalize_host_name] ? opts[:canonicalize_host_name] : false
32
+
33
+ authenticator = org.mongodb.sasl.GSSAPIAuthenticator.new(JRuby.runtime, username, hostname, servicename, canonicalize)
34
+ token = BSON::Binary.new(authenticator.initialize_challenge)
35
+ cmd = BSON::OrderedHash['saslStart', 1, 'mechanism', 'GSSAPI', 'payload', token, 'autoAuthorize', 1]
36
+ response = db.command(cmd, :check_response => false, :socket => socket)
37
+
38
+ until response['done'] do
39
+ token = BSON::Binary.new(authenticator.evaluate_challenge(response['payload'].to_s))
40
+ cmd = BSON::OrderedHash['saslContinue', 1, 'conversationId', response['conversationId'], 'payload', token]
41
+ response = db.command(cmd, :check_response => false, :socket => socket)
42
+ end
43
+ response
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -42,9 +42,11 @@ module Mongo
42
42
  OPT_ATTRS = [
43
43
  :authmechanism,
44
44
  :authsource,
45
+ :canonicalizehostname,
45
46
  :connect,
46
47
  :connecttimeoutms,
47
48
  :fsync,
49
+ :gssapiservicename,
48
50
  :journal,
49
51
  :pool_size,
50
52
  :readpreference,
@@ -59,71 +61,79 @@ module Mongo
59
61
  ]
60
62
 
61
63
  OPT_VALID = {
62
- :authmechanism => lambda { |arg| Mongo::Authentication.validate_mechanism(arg) },
63
- :authsource => lambda { |arg| arg.length > 0 },
64
- :connect => lambda { |arg| [ 'direct', 'replicaset', 'true', 'false', true, false ].include?(arg) },
65
- :connecttimeoutms => lambda { |arg| arg =~ /^\d+$/ },
66
- :fsync => lambda { |arg| ['true', 'false'].include?(arg) },
67
- :journal => lambda { |arg| ['true', 'false'].include?(arg) },
68
- :pool_size => lambda { |arg| arg.to_i > 0 },
69
- :readpreference => lambda { |arg| READ_PREFERENCES.keys.include?(arg) },
70
- :replicaset => lambda { |arg| arg.length > 0 },
71
- :safe => lambda { |arg| ['true', 'false'].include?(arg) },
72
- :slaveok => lambda { |arg| ['true', 'false'].include?(arg) },
73
- :sockettimeoutms => lambda { |arg| arg =~ /^\d+$/ },
74
- :ssl => lambda { |arg| ['true', 'false'].include?(arg) },
75
- :w => lambda { |arg| arg =~ /^\w+$/ },
76
- :wtimeout => lambda { |arg| arg =~ /^\d+$/ },
77
- :wtimeoutms => lambda { |arg| arg =~ /^\d+$/ }
64
+ :authmechanism => lambda { |arg| Mongo::Authentication.validate_mechanism(arg) },
65
+ :authsource => lambda { |arg| arg.length > 0 },
66
+ :canonicalizehostname => lambda { |arg| ['true', 'false'].include?(arg) },
67
+ :connect => lambda { |arg| [ 'direct', 'replicaset', 'true', 'false', true, false ].include?(arg) },
68
+ :connecttimeoutms => lambda { |arg| arg =~ /^\d+$/ },
69
+ :fsync => lambda { |arg| ['true', 'false'].include?(arg) },
70
+ :gssapiservicename => lambda { |arg| arg.length > 0 },
71
+ :journal => lambda { |arg| ['true', 'false'].include?(arg) },
72
+ :pool_size => lambda { |arg| arg.to_i > 0 },
73
+ :readpreference => lambda { |arg| READ_PREFERENCES.keys.include?(arg) },
74
+ :replicaset => lambda { |arg| arg.length > 0 },
75
+ :safe => lambda { |arg| ['true', 'false'].include?(arg) },
76
+ :slaveok => lambda { |arg| ['true', 'false'].include?(arg) },
77
+ :sockettimeoutms => lambda { |arg| arg =~ /^\d+$/ },
78
+ :ssl => lambda { |arg| ['true', 'false'].include?(arg) },
79
+ :w => lambda { |arg| arg =~ /^\w+$/ },
80
+ :wtimeout => lambda { |arg| arg =~ /^\d+$/ },
81
+ :wtimeoutms => lambda { |arg| arg =~ /^\d+$/ }
78
82
  }
79
83
 
80
84
  OPT_ERR = {
81
- :authmechanism => "must be one of #{Mongo::Authentication::MECHANISMS.join(', ')}",
82
- :authsource => "must be a string containing the name of the database being used for authentication",
83
- :connect => "must be 'direct', 'replicaset', 'true', or 'false'",
84
- :connecttimeoutms => "must be an integer specifying milliseconds",
85
- :fsync => "must be 'true' or 'false'",
86
- :journal => "must be 'true' or 'false'",
87
- :pool_size => "must be an integer greater than zero",
88
- :readpreference => "must be on of #{READ_PREFERENCES.keys.map(&:inspect).join(",")}",
89
- :replicaset => "must be a string containing the name of the replica set to connect to",
90
- :safe => "must be 'true' or 'false'",
91
- :slaveok => "must be 'true' or 'false'",
92
- :settimeoutms => "must be an integer specifying milliseconds",
93
- :ssl => "must be 'true' or 'false'",
94
- :w => "must be an integer indicating number of nodes to replicate to or a string " +
95
- "specifying that replication is required to the majority or nodes with a " +
96
- "particilar getLastErrorMode.",
97
- :wtimeout => "must be an integer specifying milliseconds",
98
- :wtimeoutms => "must be an integer specifying milliseconds"
85
+ :authmechanism => "must be one of #{Mongo::Authentication::MECHANISMS.join(', ')}",
86
+ :authsource => "must be a string containing the name of the database being used for authentication",
87
+ :canonicalizehostname => "must be 'true' or 'false'",
88
+ :connect => "must be 'direct', 'replicaset', 'true', or 'false'",
89
+ :connecttimeoutms => "must be an integer specifying milliseconds",
90
+ :fsync => "must be 'true' or 'false'",
91
+ :gssapiservicename => "must be a string containing the name of the GSSAPI service",
92
+ :journal => "must be 'true' or 'false'",
93
+ :pool_size => "must be an integer greater than zero",
94
+ :readpreference => "must be on of #{READ_PREFERENCES.keys.map(&:inspect).join(",")}",
95
+ :replicaset => "must be a string containing the name of the replica set to connect to",
96
+ :safe => "must be 'true' or 'false'",
97
+ :slaveok => "must be 'true' or 'false'",
98
+ :settimeoutms => "must be an integer specifying milliseconds",
99
+ :ssl => "must be 'true' or 'false'",
100
+ :w => "must be an integer indicating number of nodes to replicate to or a string " +
101
+ "specifying that replication is required to the majority or nodes with a " +
102
+ "particilar getLastErrorMode.",
103
+ :wtimeout => "must be an integer specifying milliseconds",
104
+ :wtimeoutms => "must be an integer specifying milliseconds"
99
105
  }
100
106
 
101
107
  OPT_CONV = {
102
- :authmechanism => lambda { |arg| arg.upcase },
103
- :authsource => lambda { |arg| arg },
104
- :connect => lambda { |arg| arg == 'false' ? false : arg }, # convert 'false' to FalseClass
105
- :connecttimeoutms => lambda { |arg| arg.to_f / 1000 }, # stored as seconds
106
- :fsync => lambda { |arg| arg == 'true' ? true : false },
107
- :journal => lambda { |arg| arg == 'true' ? true : false },
108
- :pool_size => lambda { |arg| arg.to_i },
109
- :readpreference => lambda { |arg| READ_PREFERENCES[arg] },
110
- :replicaset => lambda { |arg| arg },
111
- :safe => lambda { |arg| arg == 'true' ? true : false },
112
- :slaveok => lambda { |arg| arg == 'true' ? true : false },
113
- :sockettimeoutms => lambda { |arg| arg.to_f / 1000 }, # stored as seconds
114
- :ssl => lambda { |arg| arg == 'true' ? true : false },
115
- :w => lambda { |arg| Mongo::Support.is_i?(arg) ? arg.to_i : arg.to_sym },
116
- :wtimeout => lambda { |arg| arg.to_i },
117
- :wtimeoutms => lambda { |arg| arg.to_i }
108
+ :authmechanism => lambda { |arg| arg.upcase },
109
+ :authsource => lambda { |arg| arg },
110
+ :canonicalizehostname => lambda { |arg| arg == 'true' ? true : false },
111
+ :connect => lambda { |arg| arg == 'false' ? false : arg }, # convert 'false' to FalseClass
112
+ :connecttimeoutms => lambda { |arg| arg.to_f / 1000 }, # stored as seconds
113
+ :fsync => lambda { |arg| arg == 'true' ? true : false },
114
+ :gssapiservicename => lambda { |arg| arg },
115
+ :journal => lambda { |arg| arg == 'true' ? true : false },
116
+ :pool_size => lambda { |arg| arg.to_i },
117
+ :readpreference => lambda { |arg| READ_PREFERENCES[arg] },
118
+ :replicaset => lambda { |arg| arg },
119
+ :safe => lambda { |arg| arg == 'true' ? true : false },
120
+ :slaveok => lambda { |arg| arg == 'true' ? true : false },
121
+ :sockettimeoutms => lambda { |arg| arg.to_f / 1000 }, # stored as seconds
122
+ :ssl => lambda { |arg| arg == 'true' ? true : false },
123
+ :w => lambda { |arg| Mongo::Support.is_i?(arg) ? arg.to_i : arg.to_sym },
124
+ :wtimeout => lambda { |arg| arg.to_i },
125
+ :wtimeoutms => lambda { |arg| arg.to_i }
118
126
  }
119
127
 
120
128
  attr_reader :auths,
121
129
  :authmechanism,
122
130
  :authsource,
131
+ :canonicalizehostname,
123
132
  :connect,
124
133
  :connecttimeoutms,
125
134
  :db_name,
126
135
  :fsync,
136
+ :gssapiservicename,
127
137
  :journal,
128
138
  :nodes,
129
139
  :pool_size,
@@ -318,6 +328,8 @@ module Mongo
318
328
  :source => @authsource,
319
329
  :mechanism => @authmechanism
320
330
  })
331
+ auth[:extra] = @canonicalizehostname ? { :canonicalize_host_name => @canonicalizehostname } : {}
332
+ auth[:extra].merge!(:gssapi_service_name => @gssapiservicename) if @gssapiservicename
321
333
  @auths << auth
322
334
  end
323
335
  end
@@ -33,6 +33,8 @@ module Mongo
33
33
  APPEND_HEADROOM = COMMAND_HEADROOM / 2
34
34
  SERIALIZE_HEADROOM = APPEND_HEADROOM / 2
35
35
 
36
+ DEFAULT_MAX_WRITE_BATCH_SIZE = 1000
37
+
36
38
  Mutex = ::Mutex
37
39
  ConditionVariable = ::ConditionVariable
38
40
 
@@ -66,7 +68,8 @@ module Mongo
66
68
  :acceptable_latency,
67
69
  :read,
68
70
  :max_wire_version,
69
- :min_wire_version
71
+ :min_wire_version,
72
+ :max_write_batch_size
70
73
 
71
74
  # Create a connection to single MongoDB instance.
72
75
  #
@@ -87,11 +90,17 @@ module Mongo
87
90
  # @param [Integer] port specify a port number here if only one host is being specified.
88
91
  # @param [Hash] opts hash of optional settings and configuration values.
89
92
  #
90
- # @option opts [String, Integer, Symbol] :w (1) Set default number of nodes to which a write
91
- # should be acknowledged
92
- # @option opts [Boolean] :j (false) Set journal acknowledgement
93
- # @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout
94
- # @option opts [Boolean] :fsync (false) Set fsync acknowledgement.
93
+ # @option opts [String, Integer, Symbol] :w (1) Set default number of nodes to which a write
94
+ # should be acknowledged.
95
+ # @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout.
96
+ # @option opts [Boolean] :j (false) If true, block until write operations have been committed
97
+ # to the journal. Cannot be used in combination with 'fsync'. Prior to MongoDB 2.6 this option was
98
+ # ignored if the server was running without journaling. Starting with MongoDB 2.6, write operations will
99
+ # fail with an exception if this option is used when the server is running without journaling.
100
+ # @option opts [Boolean] :fsync (false) If true, and the server is running without journaling, blocks until
101
+ # the server has synced all data files to disk. If the server is running with journaling, this acts the same as
102
+ # the 'j' option, blocking until write operations have been committed to the journal.
103
+ # Cannot be used in combination with 'j'.
95
104
  #
96
105
  # Notes about Write-Concern Options:
97
106
  # Write concern options are propagated to objects instantiated from this MongoClient.
@@ -101,7 +110,8 @@ module Mongo
101
110
  # @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
102
111
  # @option opts [String] :ssl_cert (nil) The certificate file used to identify the local connection against MongoDB.
103
112
  # @option opts [String] :ssl_key (nil) The private keyfile used to identify the local connection against MongoDB.
104
- # If included with the :ssl_cert then only :ssl_cert is needed.
113
+ # Note that even if the key is stored in the same file as the certificate, both need to be explicitly specified.
114
+ # Additionally, note that the driver does not currently support providing a passphrase for the private key.
105
115
  # @option opts [Boolean] :ssl_verify (nil) Specifies whether or not peer certification validation should occur.
106
116
  # @option opts [String] :ssl_ca_cert (nil) The ca_certs file contains a set of concatenated "certification authority"
107
117
  # certificates, which are used to validate certificates passed from the other end of the connection.
@@ -161,6 +171,7 @@ module Mongo
161
171
  @max_message_size = nil
162
172
  @max_wire_version = nil
163
173
  @min_wire_version = nil
174
+ @max_write_batch_size = nil
164
175
 
165
176
  check_opts(opts)
166
177
  setup(opts.dup)
@@ -231,8 +242,7 @@ module Mongo
231
242
  [@host, @port]
232
243
  end
233
244
 
234
- # Fsync, then lock the mongod process against writes. Use this to get
235
- # the datafiles in a state safe for snapshotting, backing up, etc.
245
+ # Flush all pending writes to datafiles.
236
246
  #
237
247
  # @return [BSON::OrderedHash] the command response
238
248
  def lock!
@@ -403,6 +413,7 @@ module Mongo
403
413
  @max_message_size = config['maxMessageSizeBytes']
404
414
  @max_wire_version = config['maxWireVersion']
405
415
  @min_wire_version = config['minWireVersion']
416
+ @max_write_batch_size = config['maxWriteBatchSize']
406
417
  check_wire_version_in_range
407
418
  set_primary(host_port)
408
419
  end
@@ -482,6 +493,10 @@ module Mongo
482
493
  @min_wire_version || 0
483
494
  end
484
495
 
496
+ def max_write_batch_size
497
+ @max_write_batch_size || DEFAULT_MAX_WRITE_BATCH_SIZE
498
+ end
499
+
485
500
  def wire_version_feature?(feature)
486
501
  min_wire_version <= feature && feature <= max_wire_version
487
502
  end
@@ -47,10 +47,16 @@ module Mongo
47
47
  # @param [Array<String>, Array<Array(String, Integer)>] seeds
48
48
  #
49
49
  # @option opts [String, Integer, Symbol] :w (1) Set default number of nodes to which a write
50
- # should be acknowledged
51
- # @option opts [Boolean] :j (false) Set journal acknowledgement
52
- # @option opts [Integer] :wtimeout (nil) Set acknowledgement timeout
53
- # @option opts [Boolean] :fsync (false) Set fsync acknowledgement.
50
+ # should be acknowledged.
51
+ # @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout.
52
+ # @option opts [Boolean] :j (false) If true, block until write operations have been committed
53
+ # to the journal. Cannot be used in combination with 'fsync'. Prior to MongoDB 2.6 this option was
54
+ # ignored if the server was running without journaling. Starting with MongoDB 2.6, write operations will
55
+ # fail with an exception if this option is used when the server is running without journaling.
56
+ # @option opts [Boolean] :fsync (false) If true, and the server is running without journaling, blocks until
57
+ # the server has synced all data files to disk. If the server is running with journaling, this acts the same as
58
+ # the 'j' option, blocking until write operations have been committed to the journal.
59
+ # Cannot be used in combination with 'j'.
54
60
  #
55
61
  # Notes about write concern options:
56
62
  # Write concern options are propagated to objects instantiated from this MongoReplicaSetClient.
@@ -85,7 +91,8 @@ module Mongo
85
91
  # @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
86
92
  # @option opts [String] :ssl_cert (nil) The certificate file used to identify the local connection against MongoDB.
87
93
  # @option opts [String] :ssl_key (nil) The private keyfile used to identify the local connection against MongoDB.
88
- # If included with the :ssl_cert then only :ssl_cert is needed.
94
+ # Note that even if the key is stored in the same file as the certificate, both need to be explicitly specified.
95
+ # Additionally, note that the driver does not currently support providing a passphrase for the private key.
89
96
  # @option opts [Boolean] :ssl_verify (nil) Specifies whether or not peer certification validation should occur.
90
97
  # @option opts [String] :ssl_ca_cert (nil) The ca_certs file contains a set of concatenated "certification authority"
91
98
  # certificates, which are used to validate certificates passed from the other end of the connection.
@@ -463,6 +470,10 @@ module Mongo
463
470
  local_manager && local_manager.primary_pool && local_manager.primary_pool.node.wire_version_feature?(feature)
464
471
  end
465
472
 
473
+ def max_write_batch_size
474
+ local_manager && local_manager.primary_pool && local_manager.primary_pool.node.max_write_batch_size
475
+ end
476
+
466
477
  private
467
478
 
468
479
  # Parse option hash
@@ -104,9 +104,9 @@ module Mongo
104
104
  error = "wtimeout" if error == "timeout"
105
105
  raise OperationFailure.new(code.to_s + ': ' + error, code, docs[0])
106
106
  end
107
- elsif num_received == 1 && (jnote = docs[0]['jnote']) # assignment
108
- code = Mongo::ErrorCode::BAD_VALUE # as of server version 2.5.5
109
- raise OperationFailure.new(code.to_s + ': ' + jnote, code, docs[0])
107
+ elsif num_received == 1 && (note = docs[0]['jnote'] || docs[0]['wnote']) # assignment
108
+ code = docs[0]['code'] || Mongo::ErrorCode::BAD_VALUE # as of server version 2.5.5
109
+ raise OperationFailure.new(code.to_s + ': ' + note, code, docs[0])
110
110
  end
111
111
 
112
112
  docs[0]
@@ -37,7 +37,7 @@ module Mongo #:nodoc:
37
37
  )
38
38
  else
39
39
  order_by = value.inject({}) do |memo, (key, direction)|
40
- memo[key.to_s] = sort_value(direction.to_s.downcase)
40
+ memo[key.to_s] = sort_value(direction)
41
41
  memo
42
42
  end
43
43
  end
@@ -97,6 +97,7 @@ module Mongo #:nodoc:
97
97
  #
98
98
  # If the value is invalid then an error will be raised.
99
99
  def sort_value(value)
100
+ return value if value.is_a?(Hash)
100
101
  val = value.to_s.downcase
101
102
  return 1 if ASCENDING_CONVERSION.include?(val)
102
103
  return -1 if DESCENDING_CONVERSION.include?(val)
@@ -15,16 +15,21 @@
15
15
  require 'test_helper'
16
16
  require 'shared/authentication/basic_auth_shared'
17
17
  require 'shared/authentication/sasl_plain_shared'
18
+ require 'shared/authentication/bulk_api_auth_shared'
19
+ require 'shared/authentication/gssapi_shared'
20
+
18
21
 
19
22
  class AuthenticationTest < Test::Unit::TestCase
20
23
  include Mongo
21
24
  include BasicAuthTests
22
25
  include SASLPlainTests
26
+ include BulkAPIAuthTests
27
+ include GSSAPITests
23
28
 
24
29
  def setup
25
30
  @client = MongoClient.new(TEST_HOST, TEST_PORT)
31
+ @version = @client.server_version
26
32
  @db = @client[TEST_DB]
27
33
  @host_info = host_port
28
- init_auth
29
34
  end
30
35
  end