mongo 1.8.0 → 1.8.2

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 (80) hide show
  1. data/README.md +14 -29
  2. data/VERSION +1 -1
  3. data/lib/mongo.rb +3 -0
  4. data/lib/mongo/collection.rb +99 -49
  5. data/lib/mongo/cursor.rb +17 -17
  6. data/lib/mongo/db.rb +30 -14
  7. data/lib/mongo/gridfs/grid.rb +5 -3
  8. data/lib/mongo/gridfs/grid_file_system.rb +5 -3
  9. data/lib/mongo/gridfs/grid_io.rb +5 -3
  10. data/lib/mongo/legacy.rb +9 -2
  11. data/lib/mongo/mongo_client.rb +100 -72
  12. data/lib/mongo/mongo_replica_set_client.rb +46 -60
  13. data/lib/mongo/mongo_sharded_client.rb +5 -66
  14. data/lib/mongo/networking.rb +2 -1
  15. data/lib/mongo/util/node.rb +41 -42
  16. data/lib/mongo/util/pool.rb +15 -43
  17. data/lib/mongo/util/pool_manager.rb +16 -65
  18. data/lib/mongo/util/read_preference.rb +82 -0
  19. data/lib/mongo/util/sharding_pool_manager.rb +0 -86
  20. data/lib/mongo/util/ssl_socket.rb +2 -1
  21. data/lib/mongo/util/support.rb +8 -18
  22. data/lib/mongo/util/tcp_socket.rb +5 -4
  23. data/lib/mongo/util/thread_local_variable_manager.rb +29 -0
  24. data/lib/mongo/util/unix_socket.rb +23 -0
  25. data/lib/mongo/util/uri_parser.rb +31 -18
  26. data/lib/mongo/util/write_concern.rb +7 -2
  27. data/mongo.gemspec +1 -1
  28. data/test/auxillary/repl_set_auth_test.rb +2 -2
  29. data/test/bson/bson_test.rb +1 -1
  30. data/test/bson/byte_buffer_test.rb +24 -26
  31. data/test/bson/hash_with_indifferent_access_test.rb +11 -1
  32. data/test/functional/collection_test.rb +16 -16
  33. data/test/functional/connection_test.rb +1 -4
  34. data/test/functional/db_api_test.rb +14 -10
  35. data/test/functional/pool_test.rb +23 -31
  36. data/test/functional/timeout_test.rb +3 -5
  37. data/test/functional/uri_test.rb +10 -5
  38. data/test/replica_set/basic_test.rb +3 -8
  39. data/test/replica_set/client_test.rb +47 -31
  40. data/test/replica_set/complex_connect_test.rb +12 -10
  41. data/test/replica_set/connection_test.rb +8 -151
  42. data/test/replica_set/count_test.rb +9 -5
  43. data/test/replica_set/cursor_test.rb +17 -27
  44. data/test/replica_set/insert_test.rb +5 -10
  45. data/test/replica_set/query_test.rb +4 -9
  46. data/test/replica_set/read_preference_test.rb +200 -0
  47. data/test/replica_set/refresh_test.rb +54 -65
  48. data/test/replica_set/replication_ack_test.rb +16 -14
  49. data/test/sharded_cluster/basic_test.rb +30 -0
  50. data/test/test_helper.rb +33 -15
  51. data/test/threading/basic_test.rb +79 -0
  52. data/test/tools/mongo_config.rb +62 -22
  53. data/test/unit/client_test.rb +36 -14
  54. data/test/unit/collection_test.rb +23 -0
  55. data/test/unit/connection_test.rb +30 -14
  56. data/test/unit/cursor_test.rb +137 -7
  57. data/test/unit/db_test.rb +17 -4
  58. data/test/unit/grid_test.rb +2 -2
  59. data/test/unit/node_test.rb +2 -1
  60. data/test/unit/pool_manager_test.rb +29 -1
  61. data/test/unit/read_test.rb +15 -15
  62. data/test/unit/safe_test.rb +4 -4
  63. data/test/unit/write_concern_test.rb +4 -4
  64. metadata +134 -143
  65. data/examples/admin.rb +0 -43
  66. data/examples/capped.rb +0 -22
  67. data/examples/cursor.rb +0 -48
  68. data/examples/gridfs.rb +0 -44
  69. data/examples/index_test.rb +0 -126
  70. data/examples/info.rb +0 -31
  71. data/examples/queries.rb +0 -74
  72. data/examples/replica_set.rb +0 -26
  73. data/examples/simple.rb +0 -25
  74. data/examples/strict.rb +0 -35
  75. data/examples/types.rb +0 -36
  76. data/examples/web/thin/load.rb +0 -23
  77. data/examples/web/unicorn/load.rb +0 -25
  78. data/test/support/hash_with_indifferent_access.rb +0 -186
  79. data/test/support/keys.rb +0 -45
  80. data/test/threading/threading_with_large_pool_test.rb +0 -90
@@ -20,16 +20,14 @@ module Mongo
20
20
 
21
21
  # Instantiates and manages connections to a MongoDB replica set.
22
22
  class MongoReplicaSetClient < MongoClient
23
+ include ThreadLocalVariableManager
23
24
 
24
25
  REPL_SET_OPTS = [
25
- :read,
26
26
  :refresh_mode,
27
27
  :refresh_interval,
28
28
  :read_secondary,
29
29
  :rs_name,
30
- :name,
31
- :tag_sets,
32
- :secondary_acceptable_latency_ms
30
+ :name
33
31
  ]
34
32
 
35
33
  attr_reader :replica_set_name,
@@ -37,9 +35,7 @@ module Mongo
37
35
  :refresh_interval,
38
36
  :refresh_mode,
39
37
  :refresh_version,
40
- :manager,
41
- :tag_sets,
42
- :acceptable_latency
38
+ :manager
43
39
 
44
40
  # Create a connection to a MongoDB replica set.
45
41
  #
@@ -53,11 +49,17 @@ module Mongo
53
49
  # @overload initialize(seeds=ENV["MONGODB_URI"], opts={})
54
50
  # @param [Array<String>, Array<Array(String, Integer)>] seeds
55
51
  #
56
- # @option opts [Hash] :w (1), :j (false), :wtimeout (false), :fsync (false) Set the default write concern
57
- # propagated to DB objects instantiated off of this MongoReplicaSetClient. This
58
- # default can be overridden upon instantiation of any DB by explicitly setting write concern values
59
- # on initialization.
60
- # @option opts [:primary, :primary_preferred, :secondary, :secondary_preferred, :nearest] :read_preference (:primary)
52
+ # @option opts [String, Integer, Symbol] :w (1) Set default number of nodes to which a write
53
+ # should be acknowledged
54
+ # @option opts [Boolean] :j (false) Set journal acknowledgement
55
+ # @option opts [Integer] :wtimeout (nil) Set acknowledgement timeout
56
+ # @option opts [Boolean] :fsync (false) Set fsync acknowledgement.
57
+ #
58
+ # Notes about write concern options:
59
+ # Write concern options are propagated to objects instantiated from this MongoReplicaSetClient.
60
+ # These defaults can be overridden upon instantiation of any object by explicitly setting an options hash
61
+ # on initialization.
62
+ # @option opts [:primary, :primary_preferred, :secondary, :secondary_preferred, :nearest] :read (:primary)
61
63
  # A "read preference" determines the candidate replica set members to which a query or command can be sent.
62
64
  # [:primary]
63
65
  # * Read from primary only.
@@ -109,34 +111,38 @@ module Mongo
109
111
  # @raise [ConnectionFailure] This is raised for the various connection failures.
110
112
  def initialize(*args)
111
113
  opts = args.last.is_a?(Hash) ? args.pop : {}
112
- nodes = args
113
- nodes = nodes.flatten(1) if nodes.first.is_a?(Array) && nodes.first.first.is_a?(Array)
114
+ nodes = args.shift || []
115
+
116
+ raise MongoArgumentError, "Too many arguments" unless args.empty?
117
+
118
+ # This is temporary until support for the old format is dropped
119
+ @seeds = nodes.collect do |node|
120
+ if node.is_a?(Array)
121
+ warn "Initiating a MongoReplicaSetClient with seeds passed as individual [host, port] array arguments is deprecated."
122
+ warn "Please specify hosts as an array of 'host:port' strings; the old format will be removed in v2.0"
123
+ node
124
+ elsif node.is_a?(String)
125
+ host, port = node.split(":")
126
+ [ host, port.to_i ]
127
+ else
128
+ raise MongoArgumentError "Bad seed format!"
129
+ end
130
+ end
114
131
 
115
- if nodes.empty? and ENV.has_key?('MONGODB_URI')
132
+ if @seeds.empty? && ENV.has_key?('MONGODB_URI')
116
133
  parser = URIParser.new ENV['MONGODB_URI']
117
134
  if parser.direct?
118
- raise MongoArgumentError, "Mongo::MongoReplicaSetClient.new called with no arguments, but ENV['MONGODB_URI'] implies a direct connection."
135
+ raise MongoArgumentError,
136
+ "ENV['MONGODB_URI'] implies a direct connection."
119
137
  end
120
138
  opts = parser.connection_options.merge! opts
121
- nodes = [parser.nodes]
139
+ @seeds = parser.nodes
122
140
  end
123
141
 
124
- unless nodes.length > 0
142
+ if @seeds.length.zero?
125
143
  raise MongoArgumentError, "A MongoReplicaSetClient requires at least one seed node."
126
144
  end
127
145
 
128
- # This is temporary until support for the old format is dropped
129
- if nodes.first.last.is_a?(Integer)
130
- warn "Initiating a MongoReplicaSetClient with seeds passed as individual [host, port] array arguments is deprecated."
131
- warn "Please specify hosts as an array of 'host:port' strings; the old format will be removed in v2.0"
132
- @seeds = nodes
133
- else
134
- @seeds = nodes.first.map do |host_port|
135
- host, port = host_port.split(":")
136
- [ host, port.to_i ]
137
- end
138
- end
139
-
140
146
  @seeds.freeze
141
147
 
142
148
  # Refresh
@@ -159,8 +165,10 @@ module Mongo
159
165
  @connect_mutex = Mutex.new
160
166
  @refresh_mutex = Mutex.new
161
167
 
168
+ @mongos = false
169
+
162
170
  check_opts(opts)
163
- setup(opts)
171
+ setup(opts.dup)
164
172
  end
165
173
 
166
174
  def valid_opts
@@ -181,8 +189,7 @@ module Mongo
181
189
  seeds = @manager.nil? ? @seeds : @manager.seeds
182
190
  @manager = PoolManager.new(self, seeds)
183
191
 
184
- Thread.current[:managers] ||= Hash.new
185
- Thread.current[:managers][self] = @manager
192
+ thread_local[:managers][self] = @manager
186
193
 
187
194
  @manager.connect
188
195
  @refresh_version += 1
@@ -232,7 +239,7 @@ module Mongo
232
239
  new_manager = PoolManager.new(self, discovered_seeds | @seeds)
233
240
  new_manager.connect
234
241
 
235
- Thread.current[:managers][self] = new_manager
242
+ thread_local[:managers][self] = new_manager
236
243
 
237
244
  # TODO: make sure that connect has succeeded
238
245
  @old_managers << @manager
@@ -279,11 +286,6 @@ module Mongo
279
286
  def read_primary?
280
287
  @manager.read_pool == @manager.primary_pool
281
288
  end
282
- alias :primary? :read_primary?
283
-
284
- def read_preference
285
- @read
286
- end
287
289
 
288
290
  # Close the connection to the database.
289
291
  def close(opts={})
@@ -294,9 +296,7 @@ module Mongo
294
296
  end
295
297
 
296
298
  # Clear the reference to this object.
297
- if Thread.current[:managers]
298
- Thread.current[:managers].delete(self)
299
- end
299
+ thread_local[:managers].delete(self)
300
300
 
301
301
  @connected = false
302
302
  end
@@ -374,19 +374,15 @@ module Mongo
374
374
  end
375
375
 
376
376
  def ensure_manager
377
- Thread.current[:managers] ||= Hash.new
378
-
379
- if Thread.current[:managers][self] != @manager
380
- Thread.current[:managers][self] = @manager
381
- end
377
+ thread_local[:managers][self] = @manager
382
378
  end
383
379
 
384
380
  def pin_pool(pool)
385
- @manager.pinned_pools[Thread.current] = pool if @manager
381
+ thread_local[:pinned_pools][@manager.object_id] = pool if @manager
386
382
  end
387
383
 
388
384
  def unpin_pool(pool)
389
- @manager.pinned_pools[Thread.current] = nil if @manager
385
+ thread_local[:pinned_pools].delete @manager.object_id if @manager
390
386
  end
391
387
 
392
388
  def get_socket_from_pool(pool)
@@ -398,7 +394,7 @@ module Mongo
398
394
  end
399
395
 
400
396
  def local_manager
401
- Thread.current[:managers][self] if Thread.current[:managers]
397
+ thread_local[:managers][self]
402
398
  end
403
399
 
404
400
  def arbiters
@@ -466,20 +462,12 @@ module Mongo
466
462
  "Refresh mode must be either :sync or false."
467
463
  end
468
464
 
469
- # Determine read preference
470
465
  if opts[:read_secondary]
471
466
  warn ":read_secondary options has now been deprecated and will " +
472
467
  "be removed in driver v2.0. Use the :read option instead."
473
468
  @read_secondary = opts.delete(:read_secondary) || false
474
- @read = :secondary_preferred
475
- else
476
- @read = opts.delete(:read) || :primary
477
- Mongo::Support.validate_read_preference(@read)
478
469
  end
479
470
 
480
- @tag_sets = opts.delete(:tag_sets) || []
481
- @acceptable_latency = opts.delete(:secondary_acceptable_latency_ms) || 15
482
-
483
471
  # Replica set name
484
472
  if opts[:rs_name]
485
473
  warn ":rs_name option has been deprecated and will be removed in v2.0. " +
@@ -489,8 +477,6 @@ module Mongo
489
477
  @replica_set_name = opts.delete(:name)
490
478
  end
491
479
 
492
- opts[:connect_timeout] = opts.delete(:connect_timeout) || 30
493
-
494
480
  super opts
495
481
  end
496
482
 
@@ -20,49 +20,13 @@ module Mongo
20
20
 
21
21
  # Instantiates and manages connections to a MongoDB sharded cluster for high availability.
22
22
  class MongoShardedClient < MongoReplicaSetClient
23
+ include ThreadLocalVariableManager
23
24
 
24
- SHARDED_CLUSTER_OPTS = [:refresh_mode, :refresh_interval]
25
+ SHARDED_CLUSTER_OPTS = [:refresh_mode, :refresh_interval, :tag_sets, :read]
25
26
 
26
27
  attr_reader :seeds, :refresh_interval, :refresh_mode,
27
28
  :refresh_version, :manager
28
29
 
29
- # Create a connection to a MongoDB sharded cluster.
30
- #
31
- # If no args are provided, it will check <code>ENV["MONGODB_URI"]</code>.
32
- #
33
- # @param [Array] seeds "host:port" strings
34
- #
35
- # @option opts [String] :name (nil) The name of the sharded cluster to connect to. You
36
- # can use this option to verify that you're connecting to the right sharded cluster.
37
- # @option opts [Hash] ::w (1), :j (false), :wtimeout (false), :fsync (false) Set the default write concern
38
- # propagated to DB objects instantiated off of this MongoClient. This
39
- # default can be overridden upon instantiation of any DB by explicitly setting a write concern values
40
- # on initialization.
41
- # @option opts [Logger] :logger (nil) Logger instance to receive driver operation log.
42
- # @option opts [Integer] :pool_size (1) The maximum number of socket connections allowed per
43
- # connection pool. Note: this setting is relevant only for multi-threaded applications.
44
- # @option opts [Float] :pool_timeout (5.0) When all of the connections a pool are checked out,
45
- # this is the number of seconds to wait for a new connection to be released before throwing an exception.
46
- # Note: this setting is relevant only for multi-threaded applications.
47
- # @option opts [Float] :op_timeout (nil) The number of seconds to wait for a read operation to time out.
48
- # @option opts [Float] :connect_timeout (30) The number of seconds to wait before timing out a
49
- # connection attempt.
50
- # @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
51
- # @option opts [Boolean] :refresh_mode (false) Set this to :sync to periodically update the
52
- # state of the connection every :refresh_interval seconds. Sharded cluster connection failures
53
- # will always trigger a complete refresh. This option is useful when you want to add new nodes
54
- # or remove sharded cluster nodes not currently in use by the driver.
55
- # @option opts [Integer] :refresh_interval (90) If :refresh_mode is enabled, this is the number of seconds
56
- # between calls to check the sharded cluster's state.
57
- # Note: that the number of seed nodes does not have to be equal to the number of sharded cluster members.
58
- # The purpose of seed nodes is to permit the driver to find at least one sharded cluster member even if a member is down.
59
- #
60
- # @example Connect to a sharded cluster and provide two seed nodes.
61
- # MongoShardedClient.new(['localhost:30000', 'localhost:30001'])
62
- #
63
- # @raise [MongoArgumentError] This is raised for usage errors.
64
- #
65
- # @raise [ConnectionFailure] This is raised for the various connection failures.
66
30
  def initialize(*args)
67
31
  opts = args.last.is_a?(Hash) ? args.pop : {}
68
32
 
@@ -109,6 +73,8 @@ module Mongo
109
73
  @connect_mutex = Mutex.new
110
74
  @refresh_mutex = Mutex.new
111
75
 
76
+ @mongos = true
77
+
112
78
  check_opts(opts)
113
79
  setup(opts)
114
80
  end
@@ -131,8 +97,7 @@ module Mongo
131
97
  @old_managers << @manager if @manager
132
98
  @manager = ShardingPoolManager.new(self, discovered_seeds | @seeds)
133
99
 
134
- Thread.current[:managers] ||= Hash.new
135
- Thread.current[:managers][self] = @manager
100
+ thread_local[:managers][self] = @manager
136
101
 
137
102
  @manager.connect
138
103
  @refresh_version += 1
@@ -191,31 +156,5 @@ module Mongo
191
156
  end
192
157
  end
193
158
  end
194
-
195
- private
196
-
197
- # Parse option hash
198
- def setup(opts)
199
- # Refresh
200
- @refresh_mode = opts.fetch(:refresh_mode, false)
201
- @refresh_interval = opts.fetch(:refresh_interval, 90)
202
-
203
- if @refresh_mode && @refresh_interval < 60
204
- @refresh_interval = 60 unless ENV['TEST_MODE'] = 'TRUE'
205
- end
206
-
207
- if @refresh_mode == :async
208
- warn ":async refresh mode has been deprecated. Refresh
209
- mode will be disabled."
210
- elsif ![:sync, false].include?(@refresh_mode)
211
- raise MongoArgumentError,
212
- "Refresh mode must be either :sync or false."
213
- end
214
-
215
- opts[:connect_timeout] = opts[:connect_timeout] || 30
216
-
217
- super opts
218
- end
219
-
220
159
  end
221
160
  end
@@ -28,7 +28,7 @@ module Mongo
28
28
 
29
29
  sock = opts.fetch(:socket, nil)
30
30
  begin
31
- if operation == Mongo::Constants::OP_KILL_CURSORS && read_preference != :primary
31
+ if operation == Mongo::Constants::OP_KILL_CURSORS && @read != :primary
32
32
  sock ||= checkout_reader
33
33
  else
34
34
  sock ||= checkout_writer
@@ -229,6 +229,7 @@ module Mongo
229
229
  gle.merge!(write_concern)
230
230
  gle.delete(:w) if gle[:w] == 1
231
231
  end
232
+ gle[:w] = gle[:w].to_s if gle[:w].is_a?(Symbol)
232
233
  build_command_message(db_name, gle)
233
234
  end
234
235
 
@@ -1,7 +1,7 @@
1
1
  module Mongo
2
2
  class Node
3
3
 
4
- attr_accessor :host, :port, :address, :config, :client, :socket, :last_state
4
+ attr_accessor :host, :port, :address, :client, :socket, :last_state
5
5
 
6
6
  def initialize(client, host_port)
7
7
  @client = client
@@ -9,6 +9,7 @@ module Mongo
9
9
  @address = "#{@host}:#{@port}"
10
10
  @config = nil
11
11
  @socket = nil
12
+ @node_mutex = Mutex.new
12
13
  end
13
14
 
14
15
  def eql?(other)
@@ -20,6 +21,12 @@ module Mongo
20
21
  address
21
22
  end
22
23
 
24
+ def config
25
+ connect unless connected?
26
+ set_config unless @config
27
+ @config
28
+ end
29
+
23
30
  def inspect
24
31
  "<Mongo::Node:0x#{self.object_id.to_s(16)} @host=#{@host} @port=#{@port}>"
25
32
  end
@@ -28,18 +35,19 @@ module Mongo
28
35
  # and, if successful, return the socket. Otherwise,
29
36
  # return nil.
30
37
  def connect
31
- begin
32
- socket = @client.socket_class.new(@host, @port,
33
- @client.op_timeout, @client.connect_timeout
34
- )
35
- rescue OperationTimeout, ConnectionFailure, OperationFailure, SocketError, SystemCallError, IOError => ex
36
- @client.log(:debug, "Failed connection to #{host_string} with #{ex.class}, #{ex.message}.")
37
- socket.close if socket
38
+ @node_mutex.synchronize do
39
+ begin
40
+ @socket = @client.socket_class.new(@host, @port,
41
+ @client.op_timeout, @client.connect_timeout
42
+ )
43
+ rescue OperationTimeout, ConnectionFailure, OperationFailure, SocketError, SystemCallError, IOError => ex
44
+ @client.log(:debug, "Failed connection to #{host_string} with #{ex.class}, #{ex.message}.")
45
+ close
46
+ end
38
47
  end
39
-
40
- @socket = socket
41
48
  end
42
49
 
50
+ # This should only be called within a mutex
43
51
  def close
44
52
  if @socket && !@socket.closed?
45
53
  @socket.close
@@ -65,43 +73,38 @@ module Mongo
65
73
  # ismaster command. Additionally, check that the replica set name
66
74
  # matches with the name provided.
67
75
  def set_config
68
- begin
69
- @config = @client['admin'].command({:ismaster => 1}, :socket => @socket)
70
-
71
- if @config['msg']
72
- @client.log(:warn, "#{config['msg']}")
76
+ @node_mutex.synchronize do
77
+ begin
78
+ @config = @client['admin'].command({:ismaster => 1}, :socket => @socket)
79
+
80
+ if @config['msg']
81
+ @client.log(:warn, "#{config['msg']}")
82
+ end
83
+
84
+ unless @client.mongos?
85
+ check_set_membership(@config)
86
+ check_set_name(@config)
87
+ end
88
+ rescue ConnectionFailure, OperationFailure, OperationTimeout, SocketError, SystemCallError, IOError => ex
89
+ @client.log(:warn, "Attempted connection to node #{host_string} raised " +
90
+ "#{ex.class}: #{ex.message}")
91
+ # Socket may already be nil from issuing command
92
+ close
73
93
  end
74
-
75
- check_set_membership(config)
76
- check_set_name(config)
77
- rescue ConnectionFailure, OperationFailure, OperationTimeout, SocketError, SystemCallError, IOError => ex
78
- @client.log(:warn, "Attempted connection to node #{host_string} raised " +
79
- "#{ex.class}: #{ex.message}")
80
-
81
- # Socket may already be nil from issuing command
82
- close
83
94
  end
84
-
85
- @config
86
95
  end
87
96
 
88
97
  # Return a list of replica set nodes from the config.
89
98
  # Note: this excludes arbiters.
90
99
  def node_list
91
- connect unless connected?
92
- set_config unless @config
93
-
94
- return [] unless config
95
-
96
100
  nodes = []
97
101
  nodes += config['hosts'] if config['hosts']
98
102
  nodes += config['passives'] if config['passives']
103
+ nodes += ["#{@host}:#{@port}"] if @client.mongos?
99
104
  nodes
100
105
  end
101
106
 
102
107
  def arbiters
103
- connect unless connected?
104
- set_config unless @config
105
108
  return [] unless config['arbiters']
106
109
 
107
110
  config['arbiters'].map do |arbiter|
@@ -110,15 +113,15 @@ module Mongo
110
113
  end
111
114
 
112
115
  def primary?
113
- @config['ismaster'] == true || @config['ismaster'] == 1
116
+ config['ismaster'] == true || config['ismaster'] == 1
114
117
  end
115
118
 
116
119
  def secondary?
117
- @config['secondary'] == true || @config['secondary'] == 1
120
+ config['secondary'] == true || config['secondary'] == 1
118
121
  end
119
122
 
120
123
  def tags
121
- @config['tags'] || {}
124
+ config['tags'] || {}
122
125
  end
123
126
 
124
127
  def host_port
@@ -130,14 +133,10 @@ module Mongo
130
133
  end
131
134
 
132
135
  def healthy?
133
- if @config.has_key?('secondary')
134
- @config['ismaster'] || @config['secondary']
135
- else
136
- true
137
- end
136
+ connected? && config
138
137
  end
139
138
 
140
- private
139
+ protected
141
140
 
142
141
  def split_node(host_port)
143
142
  if host_port.is_a?(String)