mongo 2.11.1 → 2.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -1
  3. data.tar.gz.sig +2 -1
  4. data/Rakefile +24 -0
  5. data/lib/mongo/address.rb +53 -37
  6. data/lib/mongo/auth.rb +30 -10
  7. data/lib/mongo/auth/cr.rb +1 -0
  8. data/lib/mongo/auth/cr/conversation.rb +13 -13
  9. data/lib/mongo/auth/ldap.rb +2 -1
  10. data/lib/mongo/auth/ldap/conversation.rb +9 -12
  11. data/lib/mongo/auth/scram.rb +1 -0
  12. data/lib/mongo/auth/scram/conversation.rb +36 -27
  13. data/lib/mongo/auth/user.rb +7 -1
  14. data/lib/mongo/auth/x509.rb +2 -1
  15. data/lib/mongo/auth/x509/conversation.rb +9 -9
  16. data/lib/mongo/bulk_write/transformable.rb +3 -3
  17. data/lib/mongo/client.rb +17 -6
  18. data/lib/mongo/cluster.rb +67 -49
  19. data/lib/mongo/cluster/sdam_flow.rb +87 -3
  20. data/lib/mongo/collection/view/readable.rb +3 -1
  21. data/lib/mongo/collection/view/writable.rb +3 -3
  22. data/lib/mongo/cursor/builder/kill_cursors_command.rb +8 -1
  23. data/lib/mongo/cursor/builder/op_kill_cursors.rb +8 -1
  24. data/lib/mongo/database.rb +1 -1
  25. data/lib/mongo/grid/file.rb +5 -0
  26. data/lib/mongo/grid/file/chunk.rb +2 -0
  27. data/lib/mongo/grid/fs_bucket.rb +15 -13
  28. data/lib/mongo/grid/stream/write.rb +9 -3
  29. data/lib/mongo/protocol/serializers.rb +12 -2
  30. data/lib/mongo/server.rb +13 -6
  31. data/lib/mongo/server/connection.rb +15 -8
  32. data/lib/mongo/server/connection_base.rb +7 -4
  33. data/lib/mongo/server/description.rb +34 -21
  34. data/lib/mongo/server/monitor.rb +1 -1
  35. data/lib/mongo/server/monitor/connection.rb +2 -3
  36. data/lib/mongo/session.rb +10 -10
  37. data/lib/mongo/socket.rb +10 -1
  38. data/lib/mongo/uri.rb +1 -1
  39. data/lib/mongo/version.rb +1 -1
  40. data/mongo.gemspec +1 -1
  41. data/spec/README.md +13 -0
  42. data/spec/integration/auth_spec.rb +27 -8
  43. data/spec/integration/bson_symbol_spec.rb +34 -0
  44. data/spec/integration/client_construction_spec.rb +14 -0
  45. data/spec/integration/client_options_spec.rb +5 -5
  46. data/spec/integration/connection_spec.rb +57 -9
  47. data/spec/integration/crud_spec.rb +45 -0
  48. data/spec/integration/cursor_reaping_spec.rb +2 -1
  49. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  50. data/spec/integration/retryable_errors_spec.rb +2 -2
  51. data/spec/integration/zlib_compression_spec.rb +25 -0
  52. data/spec/lite_spec_helper.rb +1 -0
  53. data/spec/mongo/address_spec.rb +19 -13
  54. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  55. data/spec/mongo/auth/scram/conversation_spec.rb +25 -14
  56. data/spec/mongo/auth/user/view_spec.rb +39 -7
  57. data/spec/mongo/auth/user_spec.rb +12 -0
  58. data/spec/mongo/auth/x509/conversation_spec.rb +1 -1
  59. data/spec/mongo/bulk_write_spec.rb +2 -2
  60. data/spec/mongo/client_construction_spec.rb +3 -22
  61. data/spec/mongo/cluster_spec.rb +57 -0
  62. data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
  63. data/spec/mongo/collection_spec.rb +26 -2
  64. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +56 -0
  65. data/spec/mongo/server/connection_spec.rb +76 -8
  66. data/spec/mongo/server/monitor/connection_spec.rb +14 -7
  67. data/spec/mongo/socket/ssl_spec.rb +132 -98
  68. data/spec/mongo/socket/tcp_spec.rb +1 -9
  69. data/spec/mongo/uri_spec.rb +1 -1
  70. data/spec/runners/sdam/verifier.rb +6 -3
  71. data/spec/spec_tests/data/sdam/rs/primary_address_change.yml +29 -0
  72. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me.yml +27 -23
  73. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +56 -79
  74. data/spec/spec_tests/data/sdam/sharded/primary_address_change.yml +21 -0
  75. data/spec/spec_tests/data/sdam/sharded/primary_mismatched_me.yml +22 -0
  76. data/spec/spec_tests/data/sdam/single/primary_address_change.yml +24 -0
  77. data/spec/spec_tests/data/sdam/single/primary_mismatched_me.yml +25 -0
  78. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +159 -0
  79. data/spec/spec_tests/data/sdam_monitoring/{replica_set_other_seed.yml → replica_set_with_primary_change.yml} +97 -101
  80. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_primary_removal.yml +22 -18
  81. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +90 -0
  82. data/spec/support/cluster_config.rb +36 -0
  83. data/spec/support/cluster_tools.rb +5 -3
  84. data/spec/support/command_monitoring.rb +1 -1
  85. data/spec/support/constraints.rb +18 -18
  86. data/spec/support/lite_constraints.rb +8 -0
  87. data/spec/support/server_discovery_and_monitoring.rb +2 -0
  88. data/spec/support/spec_config.rb +3 -3
  89. data/spec/support/utils.rb +11 -1
  90. metadata +661 -637
  91. metadata.gz.sig +0 -0
@@ -185,7 +185,9 @@ module Mongo
185
185
  pipeline << { :'$limit' => opts[:limit] } if opts[:limit]
186
186
  pipeline << { :'$group' => { _id: 1, n: { :'$sum' => 1 } } }
187
187
 
188
- opts.select! { |k, _| [:hint, :max_time_ms, :read, :collation, :session].include?(k) }
188
+ opts = opts.select { |k, _| [:hint, :max_time_ms, :read, :collation, :session].include?(k) }
189
+ opts[:collation] ||= collation
190
+
189
191
  first = aggregate(pipeline, opts).first
190
192
  return 0 unless first
191
193
  first['n'].to_i
@@ -234,7 +234,7 @@ module Mongo
234
234
  Operation::U => replacement,
235
235
  }
236
236
  if opts[:upsert]
237
- update_doc[:upsert] = true
237
+ update_doc['upsert'] = true
238
238
  end
239
239
  with_session(opts) do |session|
240
240
  write_concern = write_concern_with_session(session)
@@ -281,7 +281,7 @@ module Mongo
281
281
  Operation::MULTI => true,
282
282
  }
283
283
  if opts[:upsert]
284
- update_doc[:upsert] = true
284
+ update_doc['upsert'] = true
285
285
  end
286
286
  with_session(opts) do |session|
287
287
  write_concern = write_concern_with_session(session)
@@ -325,7 +325,7 @@ module Mongo
325
325
  Operation::U => spec,
326
326
  }
327
327
  if opts[:upsert]
328
- update_doc[:upsert] = true
328
+ update_doc['upsert'] = true
329
329
  end
330
330
  with_session(opts) do |session|
331
331
  write_concern = write_concern_with_session(session)
@@ -92,7 +92,14 @@ module Mongo
92
92
  #
93
93
  # @since 2.3.0
94
94
  def get_cursors_list(spec)
95
- spec[:selector][:cursors].map(&:value)
95
+ spec[:selector][:cursors].map do |value|
96
+ if value.respond_to?(:value)
97
+ # bson-ruby >= 4.6.0
98
+ value = value.value
99
+ else
100
+ value = value.instance_variable_get('@integer')
101
+ end
102
+ end
96
103
  end
97
104
  end
98
105
  end
@@ -87,7 +87,14 @@ module Mongo
87
87
  #
88
88
  # @since 2.3.0
89
89
  def get_cursors_list(spec)
90
- spec[:cursor_ids].map(&:value)
90
+ spec[:cursor_ids].map do |value|
91
+ if value.respond_to?(:value)
92
+ # bson-ruby >= 4.6.0
93
+ value.value
94
+ else
95
+ value.instance_variable_get('@integer')
96
+ end
97
+ end
91
98
  end
92
99
  end
93
100
  end
@@ -157,7 +157,7 @@ module Mongo
157
157
  # @option opts :read [ Hash ] The read preference for this command.
158
158
  # @option opts :session [ Session ] The session to use for this command.
159
159
  #
160
- # @return [ Hash ] The result of the command execution.
160
+ # @return [ Mongo::Operation::Result ] The result of the command execution.
161
161
  def command(operation, opts = {})
162
162
  txn_read_pref = if opts[:session] && opts[:session].in_transaction?
163
163
  opts[:session].txn_read_preference
@@ -104,6 +104,11 @@ module Mongo
104
104
  # chunk objects and assemble the data. If we have an IO object, then
105
105
  # it's the original file data and we must split it into chunks and set
106
106
  # the original data itself.
107
+ #
108
+ # @param [ IO, String, Array<BSON::Document> ] value The file object,
109
+ # file contents or chunk documents.
110
+ #
111
+ # @return [ Array<Grid::File::Chunk> ] Array of chunks.
107
112
  def initialize_chunks!(value)
108
113
  if value.is_a?(Array)
109
114
  @chunks = value.map{ |doc| Chunk.new(doc) }
@@ -151,6 +151,7 @@ module Mongo
151
151
  # @return [ String ] The assembled data.
152
152
  #
153
153
  # @since 2.0.0
154
+ # @api private
154
155
  def assemble(chunks)
155
156
  chunks.reduce(''){ |data, chunk| data << chunk.data.data }
156
157
  end
@@ -167,6 +168,7 @@ module Mongo
167
168
  # @return [ Array<Chunk> ] The chunks of the data.
168
169
  #
169
170
  # @since 2.0.0
171
+ # @api private
170
172
  def split(io, file_info, offset = 0)
171
173
  io = StringIO.new(io) if io.is_a?(String)
172
174
  parts = Enumerator.new { |y| y << io.read(file_info.chunk_size) until io.eof? }
@@ -177,7 +177,7 @@ module Mongo
177
177
  #
178
178
  # @since 2.0.0
179
179
  def prefix
180
- @options[:fs_name] || @options[:bucket_name]|| DEFAULT_ROOT
180
+ @options[:fs_name] || @options[:bucket_name] || DEFAULT_ROOT
181
181
  end
182
182
 
183
183
  # Remove a single file from the GridFS.
@@ -230,7 +230,8 @@ module Mongo
230
230
  #
231
231
  # @since 2.1.0
232
232
  def open_download_stream(id, options = nil)
233
- read_stream(id, options).tap do |stream|
233
+ options = Hash[(options || {}).map { |k, v| [k.to_sym, v] }]
234
+ read_stream(id, **options).tap do |stream|
234
235
  if block_given?
235
236
  begin
236
237
  yield stream
@@ -348,15 +349,15 @@ module Mongo
348
349
  download_to_stream(open_download_stream_by_name(filename, opts).file_id, io)
349
350
  end
350
351
 
351
- # Opens an upload stream to GridFS to which the contents of a user file came be written.
352
+ # Opens an upload stream to GridFS to which the contents of a file or
353
+ # blob can be written.
352
354
  #
353
- # @example Open a stream to which the contents of a file came be written.
354
- # fs.open_upload_stream('a-file.txt')
355
- #
356
- # @param [ String ] filename The filename of the file to upload.
355
+ # @param [ String ] filename The name of the file in GridFS.
357
356
  # @param [ Hash ] opts The options for the write stream.
358
357
  #
359
- # @option opts [ Object ] :file_id An optional unique file id. An ObjectId is generated otherwise.
358
+ # @option opts [ Object ] :file_id An optional unique file id.
359
+ # A BSON::ObjectId is automatically generated if a file id is not
360
+ # provided.
360
361
  # @option opts [ Integer ] :chunk_size Override the default chunk size.
361
362
  # @option opts [ Hash ] :metadata User data for the 'metadata' field of the files
362
363
  # collection document.
@@ -375,7 +376,8 @@ module Mongo
375
376
  #
376
377
  # @since 2.1.0
377
378
  def open_upload_stream(filename, opts = {})
378
- write_stream(filename, opts).tap do |stream|
379
+ opts = Hash[opts.map { |k, v| [k.to_sym, v] }]
380
+ write_stream(filename, **opts).tap do |stream|
379
381
  if block_given?
380
382
  begin
381
383
  yield stream
@@ -462,12 +464,12 @@ module Mongo
462
464
  #
463
465
  # @option opts [ BSON::Document ] :file_info_doc For internal
464
466
  # driver use only. A BSON document to use as file information.
465
- def read_stream(id, opts = nil)
466
- Stream.get(self, Stream::READ_MODE, { file_id: id }.update(options).update(opts || {}))
467
+ def read_stream(id, **opts)
468
+ Stream.get(self, Stream::READ_MODE, { file_id: id }.update(options).update(opts))
467
469
  end
468
470
 
469
- def write_stream(filename, opts)
470
- Stream.get(self, Stream::WRITE_MODE, { filename: filename }.merge!(options).merge!(opts))
471
+ def write_stream(filename, **opts)
472
+ Stream.get(self, Stream::WRITE_MODE, { filename: filename }.update(options).update(opts))
471
473
  end
472
474
 
473
475
  def chunks_name
@@ -82,12 +82,12 @@ module Mongo
82
82
  @open = true
83
83
  end
84
84
 
85
- # Write to the GridFS bucket from the source stream.
85
+ # Write to the GridFS bucket from the source stream or a string.
86
86
  #
87
87
  # @example Write to GridFS.
88
88
  # stream.write(io)
89
89
  #
90
- # @param [ IO ] io The source io stream to upload from.
90
+ # @param [ String | IO ] io The string or IO object to upload from.
91
91
  #
92
92
  # @return [ Stream::Write ] self The write stream itself.
93
93
  #
@@ -95,7 +95,13 @@ module Mongo
95
95
  def write(io)
96
96
  ensure_open!
97
97
  @indexes ||= ensure_indexes!
98
- @length += io.size
98
+ @length += if io.respond_to?(:bytesize)
99
+ # String objects
100
+ io.bytesize
101
+ else
102
+ # IO objects
103
+ io.size
104
+ end
99
105
  chunks = File::Chunk.split(io, file_info, @n)
100
106
  @n += chunks.size
101
107
  chunks_collection.insert_many(chunks) unless chunks.empty?
@@ -110,7 +110,12 @@ module Mongo
110
110
  # @return [String] Buffer with serialized value.
111
111
  def self.serialize(buffer, value, validating_keys = BSON::Config.validating_keys?)
112
112
  if value.is_a?(BSON::Int32)
113
- value = value.value
113
+ if value.respond_to?(:value)
114
+ # bson-ruby >= 4.6.0
115
+ value = value.value
116
+ else
117
+ value = value.instance_variable_get('@integer')
118
+ end
114
119
  end
115
120
  buffer.put_int32(value)
116
121
  end
@@ -138,7 +143,12 @@ module Mongo
138
143
  # @return [ String ] Buffer with serialized value.
139
144
  def self.serialize(buffer, value, validating_keys = BSON::Config.validating_keys?)
140
145
  if value.is_a?(BSON::Int64)
141
- value = value.value
146
+ if value.respond_to?(:value)
147
+ # bson-ruby >= 4.6.0
148
+ value = value.value
149
+ else
150
+ value = value.instance_variable_get('@integer')
151
+ end
142
152
  end
143
153
  buffer.put_int64(value)
144
154
  end
@@ -306,12 +306,11 @@ module Mongo
306
306
  "#<Mongo::Server:0x#{object_id} address=#{address.host}:#{address.port}>"
307
307
  end
308
308
 
309
- # @note This method is experimental and subject to change.
309
+ # @return [ String ] String representing server status (e.g. PRIMARY).
310
310
  #
311
- # @api experimental
312
- # @since 2.7.0
313
- def summary
314
- status = case
311
+ # @api private
312
+ def status
313
+ case
315
314
  when primary?
316
315
  'PRIMARY'
317
316
  when secondary?
@@ -331,8 +330,16 @@ module Mongo
331
330
  else
332
331
  # Since the summary method is often used for debugging, do not raise
333
332
  # an exception in case none of the expected types matched
334
- ''
333
+ nil
335
334
  end
335
+ end
336
+
337
+ # @note This method is experimental and subject to change.
338
+ #
339
+ # @api experimental
340
+ # @since 2.7.0
341
+ def summary
342
+ status = self.status || ''
336
343
  if replica_set_name
337
344
  status += " replica_set=#{replica_set_name}"
338
345
  end
@@ -103,6 +103,12 @@ module Mongo
103
103
  )
104
104
  end
105
105
 
106
+ # @return [ Server::Description ] The server description obtained from
107
+ # the handshake on this connection.
108
+ #
109
+ # @api private
110
+ attr_reader :description
111
+
106
112
  # @return [ Time ] The last time the connection was checked back into a pool.
107
113
  #
108
114
  # @since 2.5.0
@@ -181,13 +187,14 @@ module Mongo
181
187
 
182
188
  # Separate method to permit easier mocking in the test suite.
183
189
  def do_connect
184
- socket = address.socket(socket_timeout, ssl_options,
185
- connect_timeout: address.connect_timeout)
190
+ socket = address.socket(socket_timeout, ssl_options, address.options)
186
191
 
187
192
  begin
188
193
  handshake!(socket)
189
- pending_connection = PendingConnection.new(socket, @server, monitoring, options.merge(id: id))
190
- authenticate!(pending_connection)
194
+ unless description.arbiter?
195
+ pending_connection = PendingConnection.new(socket, @server, monitoring, options.merge(id: id))
196
+ authenticate!(pending_connection)
197
+ end
191
198
  rescue Exception
192
199
  socket.close
193
200
  raise
@@ -314,7 +321,7 @@ module Mongo
314
321
  raise exc
315
322
  end
316
323
  rescue => e
317
- log_warn("Failed to handshake with #{address}: #{e.class}: #{e}")
324
+ log_warn("Failed to handshake with #{address}: #{e.class}: #{e}:\n#{e.backtrace[0..5].join("\n")}")
318
325
  raise
319
326
  end
320
327
  end
@@ -356,8 +363,8 @@ module Mongo
356
363
  @auth_mechanism = nil
357
364
  end
358
365
 
359
- new_description = Description.new(address, response, average_rtt)
360
- @server.cluster.run_sdam_flow(@server.description, new_description)
366
+ @description = Description.new(address, response, average_rtt)
367
+ @server.cluster.run_sdam_flow(@server.description, @description)
361
368
  end
362
369
 
363
370
  def authenticate!(pending_connection)
@@ -371,7 +378,7 @@ module Mongo
371
378
  begin
372
379
  Auth.get(user).login(pending_connection)
373
380
  rescue => e
374
- log_warn("Failed to handshake with #{address}: #{e.class}: #{e}")
381
+ log_warn("Failed to handshake with #{address}: #{e.class}: #{e}:\n#{e.backtrace[0..5].join("\n")}")
375
382
  raise
376
383
  end
377
384
  end
@@ -29,12 +29,15 @@ module Mongo
29
29
  # @return [ Hash ] options The passed in options.
30
30
  attr_reader :options
31
31
 
32
+ # @return [ Server ] The server that this connection is for.
33
+ #
34
+ # @api private
35
+ attr_reader :server
36
+
32
37
  # @return [ Mongo::Address ] address The address to connect to.
33
- def address
34
- @server.address
35
- end
38
+ def_delegators :server, :address
36
39
 
37
- def_delegators :@server,
40
+ def_delegators :server,
38
41
  :features,
39
42
  :max_bson_object_size,
40
43
  :max_message_size,
@@ -33,6 +33,7 @@ module Mongo
33
33
  # Constant for reading arbiter info from config.
34
34
  #
35
35
  # @since 2.0.0
36
+ # @deprecated
36
37
  ARBITER = 'arbiterOnly'.freeze
37
38
 
38
39
  # Constant for reading arbiters info from config.
@@ -53,16 +54,19 @@ module Mongo
53
54
  # Constant for the key for the message value.
54
55
  #
55
56
  # @since 2.0.0
57
+ # @deprecated
56
58
  MESSAGE = 'msg'.freeze
57
59
 
58
60
  # Constant for the message that indicates a sharded cluster.
59
61
  #
60
62
  # @since 2.0.0
63
+ # @deprecated
61
64
  MONGOS_MESSAGE = 'isdbgrid'.freeze
62
65
 
63
66
  # Constant for determining ghost servers.
64
67
  #
65
68
  # @since 2.0.0
69
+ # @deprecated
66
70
  REPLICA_SET = 'isreplicaset'.freeze
67
71
 
68
72
  # Constant for reading max bson size info from config.
@@ -129,6 +133,7 @@ module Mongo
129
133
  # Constant for reading primary info from config.
130
134
  #
131
135
  # @since 2.0.0
136
+ # @deprecated
132
137
  PRIMARY = 'ismaster'.freeze
133
138
 
134
139
  # Constant for reading primary host field from config.
@@ -139,6 +144,7 @@ module Mongo
139
144
  # Constant for reading secondary info from config.
140
145
  #
141
146
  # @since 2.0.0
147
+ # @deprecated
142
148
  SECONDARY = 'secondary'.freeze
143
149
 
144
150
  # Constant for reading replica set name info from config.
@@ -227,7 +233,7 @@ module Mongo
227
233
  # @return [ Float ] The moving average time the ismaster call took to complete.
228
234
  attr_reader :average_round_trip_time
229
235
 
230
- # Will return true if the server is an arbiter.
236
+ # Returns whether this server is an arbiter, per the SDAM spec.
231
237
  #
232
238
  # @example Is the server an arbiter?
233
239
  # description.arbiter?
@@ -236,7 +242,9 @@ module Mongo
236
242
  #
237
243
  # @since 2.0.0
238
244
  def arbiter?
239
- ok? && !!config[ARBITER] && !replica_set_name.nil?
245
+ ok? &&
246
+ config['arbiterOnly'] == true &&
247
+ !!config['setName']
240
248
  end
241
249
 
242
250
  # Get a list of all arbiters in the replica set.
@@ -251,7 +259,7 @@ module Mongo
251
259
  @arbiters ||= (config[ARBITERS] || []).map { |s| s.downcase }
252
260
  end
253
261
 
254
- # Is the server a ghost in a replica set?
262
+ # Whether this server is a ghost, per the SDAM spec.
255
263
  #
256
264
  # @example Is the server a ghost?
257
265
  # description.ghost?
@@ -260,7 +268,8 @@ module Mongo
260
268
  #
261
269
  # @since 2.0.0
262
270
  def ghost?
263
- ok? && !!config[REPLICA_SET]
271
+ ok? &&
272
+ config['isreplicaset'] == true
264
273
  end
265
274
 
266
275
  # Will return true if the server is hidden.
@@ -431,7 +440,7 @@ module Mongo
431
440
  config[LOGICAL_SESSION_TIMEOUT_MINUTES] if config[LOGICAL_SESSION_TIMEOUT_MINUTES]
432
441
  end
433
442
 
434
- # Is the server a mongos?
443
+ # Returns whether this server is a mongos, per the SDAM spec.
435
444
  #
436
445
  # @example Is the server a mongos?
437
446
  # description.mongos?
@@ -440,10 +449,10 @@ module Mongo
440
449
  #
441
450
  # @since 2.0.0
442
451
  def mongos?
443
- ok? && config[MESSAGE] == MONGOS_MESSAGE
452
+ ok? && config['msg'] == 'isdbgrid'
444
453
  end
445
454
 
446
- # Is the description of type other.
455
+ # Returns whether the server is an other, per the SDAM spec.
447
456
  #
448
457
  # @example Is the description of type other.
449
458
  # description.other?
@@ -455,11 +464,11 @@ module Mongo
455
464
  # The SDAM spec is slightly confusing on what "other" means,
456
465
  # but it's referred to it as "RSOther" which means a non-RS member
457
466
  # cannot be "other".
458
- if unknown? || replica_set_name.nil?
459
- return false
460
- end
461
- (!primary? && !secondary? && !passive? && !arbiter?) ||
462
- (hidden? && !replica_set_name.nil?)
467
+ ok? &&
468
+ !!config['setName'] && (
469
+ config['hidden'] == true ||
470
+ !primary? && !secondary? && !arbiter?
471
+ )
463
472
  end
464
473
 
465
474
  # Will return true if the server is passive.
@@ -498,7 +507,7 @@ module Mongo
498
507
  config[PRIMARY_HOST] && config[PRIMARY_HOST].downcase
499
508
  end
500
509
 
501
- # Will return true if the server is a primary.
510
+ # Returns whether this server is a primary, per the SDAM spec.
502
511
  #
503
512
  # @example Is the server a primary?
504
513
  # description.primary?
@@ -508,9 +517,8 @@ module Mongo
508
517
  # @since 2.0.0
509
518
  def primary?
510
519
  ok? &&
511
- !!config[PRIMARY] &&
512
- (primary_host.nil? || primary_host == address.to_s) &&
513
- !replica_set_name.nil?
520
+ config['ismaster'] == true &&
521
+ !!config['setName']
514
522
  end
515
523
 
516
524
  # Get the name of the replica set the server belongs to, returns nil if
@@ -538,7 +546,7 @@ module Mongo
538
546
  hosts + arbiters + passives
539
547
  end
540
548
 
541
- # Will return true if the server is a secondary.
549
+ # Returns whether this server is a secondary, per the SDAM spec.
542
550
  #
543
551
  # @example Is the server a secondary?
544
552
  # description.secondary?
@@ -547,7 +555,9 @@ module Mongo
547
555
  #
548
556
  # @since 2.0.0
549
557
  def secondary?
550
- ok? && !!config[SECONDARY] && !replica_set_name.nil?
558
+ ok? &&
559
+ config['secondary'] == true &&
560
+ !!config['setName']
551
561
  end
552
562
 
553
563
  # Returns the server type as a symbol.
@@ -569,7 +579,7 @@ module Mongo
569
579
  :unknown
570
580
  end
571
581
 
572
- # Is this server a standalone server?
582
+ # Returns whether this server is a standalone, per the SDAM spec.
573
583
  #
574
584
  # @example Is the server standalone?
575
585
  # description.standalone?
@@ -578,10 +588,13 @@ module Mongo
578
588
  #
579
589
  # @since 2.0.0
580
590
  def standalone?
581
- replica_set_name.nil? && !mongos? && !ghost? && !unknown?
591
+ ok? &&
592
+ config['msg'] != 'isdbgrid' &&
593
+ config['setName'].nil? &&
594
+ config['isreplicaset'] != true
582
595
  end
583
596
 
584
- # Is the server description currently unknown?
597
+ # Returns whether this server is an unknown, per the SDAM spec.
585
598
  #
586
599
  # @example Is the server description unknown?
587
600
  # description.unknown?