mongo 1.8.0 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
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)