mongo 1.7.1 → 1.8.0

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 (138) hide show
  1. data/{LICENSE.txt → LICENSE} +0 -0
  2. data/README.md +124 -111
  3. data/Rakefile +9 -325
  4. data/VERSION +1 -0
  5. data/bin/mongo_console +4 -4
  6. data/examples/admin.rb +43 -0
  7. data/examples/capped.rb +22 -0
  8. data/examples/cursor.rb +48 -0
  9. data/examples/gridfs.rb +44 -0
  10. data/examples/index_test.rb +126 -0
  11. data/examples/info.rb +31 -0
  12. data/examples/queries.rb +74 -0
  13. data/examples/replica_set.rb +26 -0
  14. data/examples/simple.rb +25 -0
  15. data/examples/strict.rb +35 -0
  16. data/examples/types.rb +36 -0
  17. data/{test/load → examples/web}/thin/load.rb +3 -1
  18. data/{test/load → examples/web}/unicorn/load.rb +5 -3
  19. data/lib/mongo.rb +8 -10
  20. data/lib/mongo/collection.rb +134 -114
  21. data/lib/mongo/cursor.rb +21 -14
  22. data/lib/mongo/db.rb +30 -28
  23. data/lib/mongo/exceptions.rb +1 -1
  24. data/lib/mongo/gridfs/grid.rb +8 -7
  25. data/lib/mongo/gridfs/grid_ext.rb +1 -1
  26. data/lib/mongo/gridfs/grid_file_system.rb +6 -5
  27. data/lib/mongo/gridfs/grid_io.rb +22 -19
  28. data/lib/mongo/legacy.rb +82 -0
  29. data/lib/mongo/{connection.rb → mongo_client.rb} +82 -61
  30. data/lib/mongo/{repl_set_connection.rb → mongo_replica_set_client.rb} +54 -39
  31. data/lib/mongo/{sharded_connection.rb → mongo_sharded_client.rb} +9 -9
  32. data/lib/mongo/networking.rb +25 -20
  33. data/lib/mongo/util/conversions.rb +1 -1
  34. data/lib/mongo/util/core_ext.rb +1 -1
  35. data/lib/mongo/util/logging.rb +20 -4
  36. data/lib/mongo/util/node.rb +16 -16
  37. data/lib/mongo/util/pool.rb +56 -27
  38. data/lib/mongo/util/pool_manager.rb +28 -27
  39. data/lib/mongo/util/server_version.rb +1 -1
  40. data/lib/mongo/util/sharding_pool_manager.rb +8 -8
  41. data/lib/mongo/util/ssl_socket.rb +1 -5
  42. data/lib/mongo/util/support.rb +24 -8
  43. data/lib/mongo/util/tcp_socket.rb +0 -4
  44. data/lib/mongo/util/uri_parser.rb +54 -38
  45. data/lib/mongo/util/write_concern.rb +67 -0
  46. data/mongo.gemspec +21 -32
  47. data/test/auxillary/{1.4_features.rb → 1.4_feature_test.rb} +4 -5
  48. data/test/auxillary/authentication_test.rb +18 -20
  49. data/test/auxillary/autoreconnect_test.rb +3 -5
  50. data/test/auxillary/fork_test.rb +5 -7
  51. data/test/auxillary/repl_set_auth_test.rb +13 -15
  52. data/test/auxillary/slave_connection_test.rb +8 -7
  53. data/test/auxillary/threaded_authentication_test.rb +15 -17
  54. data/test/bson/binary_test.rb +1 -1
  55. data/test/bson/bson_test.rb +60 -36
  56. data/test/bson/byte_buffer_test.rb +1 -1
  57. data/test/bson/hash_with_indifferent_access_test.rb +2 -2
  58. data/test/bson/json_test.rb +1 -2
  59. data/test/bson/object_id_test.rb +1 -2
  60. data/test/bson/ordered_hash_test.rb +1 -1
  61. data/test/bson/timestamp_test.rb +1 -1
  62. data/test/{collection_test.rb → functional/collection_test.rb} +57 -57
  63. data/test/{connection_test.rb → functional/connection_test.rb} +75 -89
  64. data/test/{conversions_test.rb → functional/conversions_test.rb} +1 -1
  65. data/test/{cursor_fail_test.rb → functional/cursor_fail_test.rb} +3 -29
  66. data/test/{cursor_message_test.rb → functional/cursor_message_test.rb} +1 -1
  67. data/test/{cursor_test.rb → functional/cursor_test.rb} +5 -1
  68. data/test/{db_api_test.rb → functional/db_api_test.rb} +8 -9
  69. data/test/{db_connection_test.rb → functional/db_connection_test.rb} +3 -5
  70. data/test/{db_test.rb → functional/db_test.rb} +13 -13
  71. data/test/{grid_file_system_test.rb → functional/grid_file_system_test.rb} +2 -2
  72. data/test/{grid_io_test.rb → functional/grid_io_test.rb} +6 -6
  73. data/test/{grid_test.rb → functional/grid_test.rb} +4 -10
  74. data/test/{pool_test.rb → functional/pool_test.rb} +1 -1
  75. data/test/functional/safe_test.rb +84 -0
  76. data/test/{support_test.rb → functional/support_test.rb} +1 -1
  77. data/test/{threading_test.rb → functional/threading_test.rb} +9 -9
  78. data/test/{timeout_test.rb → functional/timeout_test.rb} +1 -1
  79. data/test/{uri_test.rb → functional/uri_test.rb} +1 -1
  80. data/test/functional/write_concern_test.rb +104 -0
  81. data/test/replica_set/basic_test.rb +139 -0
  82. data/test/replica_set/client_test.rb +255 -0
  83. data/test/replica_set/complex_connect_test.rb +62 -0
  84. data/test/replica_set/connection_test.rb +255 -0
  85. data/test/{replica_sets → replica_set}/count_test.rb +17 -14
  86. data/test/replica_set/cursor_test.rb +75 -0
  87. data/test/{replica_sets → replica_set}/insert_test.rb +19 -16
  88. data/test/replica_set/query_test.rb +64 -0
  89. data/test/replica_set/refresh_test.rb +153 -0
  90. data/test/{replica_sets → replica_set}/replication_ack_test.rb +21 -17
  91. data/test/sharded_cluster/basic_test.rb +31 -50
  92. data/test/support/hash_with_indifferent_access.rb +1 -1
  93. data/test/test_helper.rb +56 -9
  94. data/test/threading/threading_with_large_pool_test.rb +8 -8
  95. data/test/tools/mongo_config.rb +270 -58
  96. data/test/tools/mongo_config_test.rb +146 -0
  97. data/test/unit/client_test.rb +230 -0
  98. data/test/unit/collection_test.rb +45 -32
  99. data/test/unit/connection_test.rb +82 -74
  100. data/test/unit/cursor_test.rb +14 -6
  101. data/test/unit/db_test.rb +8 -8
  102. data/test/unit/grid_test.rb +11 -11
  103. data/test/unit/node_test.rb +24 -24
  104. data/test/unit/pool_manager_test.rb +13 -13
  105. data/test/unit/pool_test.rb +1 -1
  106. data/test/unit/read_test.rb +21 -26
  107. data/test/unit/safe_test.rb +52 -33
  108. data/test/unit/util_test.rb +55 -0
  109. data/test/unit/write_concern_test.rb +161 -0
  110. metadata +158 -171
  111. data/docs/CREDITS.md +0 -123
  112. data/docs/FAQ.md +0 -116
  113. data/docs/GRID_FS.md +0 -158
  114. data/docs/HISTORY.md +0 -392
  115. data/docs/READ_PREFERENCE.md +0 -99
  116. data/docs/RELEASES.md +0 -54
  117. data/docs/REPLICA_SETS.md +0 -113
  118. data/docs/TAILABLE_CURSORS.md +0 -51
  119. data/docs/TUTORIAL.md +0 -356
  120. data/docs/WRITE_CONCERN.md +0 -31
  121. data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
  122. data/lib/mongo/version.rb +0 -3
  123. data/test/bson/test_helper.rb +0 -30
  124. data/test/replica_sets/basic_test.rb +0 -119
  125. data/test/replica_sets/complex_connect_test.rb +0 -57
  126. data/test/replica_sets/complex_read_preference_test.rb +0 -237
  127. data/test/replica_sets/connect_test.rb +0 -156
  128. data/test/replica_sets/cursor_test.rb +0 -70
  129. data/test/replica_sets/pooled_insert_test.rb +0 -57
  130. data/test/replica_sets/query_test.rb +0 -50
  131. data/test/replica_sets/read_preference_test.rb +0 -234
  132. data/test/replica_sets/refresh_test.rb +0 -156
  133. data/test/replica_sets/refresh_with_threads_test.rb +0 -60
  134. data/test/replica_sets/rs_test_helper.rb +0 -39
  135. data/test/safe_test.rb +0 -68
  136. data/test/sharded_cluster/mongo_config_test.rb +0 -126
  137. data/test/sharded_cluster/sc_test_helper.rb +0 -39
  138. data/test/tools/repl_set_manager.rb +0 -418
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  # --
4
- # Copyright (C) 2008-2011 10gen Inc.
4
+ # Copyright (C) 2008-2012 10gen Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
19
19
  module Mongo
20
20
 
21
21
  # Instantiates and manages connections to a MongoDB sharded cluster for high availability.
22
- class ShardedConnection < ReplSetConnection
22
+ class MongoShardedClient < MongoReplicaSetClient
23
23
 
24
24
  SHARDED_CLUSTER_OPTS = [:refresh_mode, :refresh_interval]
25
25
 
@@ -34,9 +34,9 @@ module Mongo
34
34
  #
35
35
  # @option opts [String] :name (nil) The name of the sharded cluster to connect to. You
36
36
  # can use this option to verify that you're connecting to the right sharded cluster.
37
- # @option opts [Boolean, Hash] :safe (false) Set the default safe-mode options
38
- # propagated to DB objects instantiated off of this Connection. This
39
- # default can be overridden upon instantiation of any DB by explicitly setting a :safe value
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
40
  # on initialization.
41
41
  # @option opts [Logger] :logger (nil) Logger instance to receive driver operation log.
42
42
  # @option opts [Integer] :pool_size (1) The maximum number of socket connections allowed per
@@ -58,7 +58,7 @@ module Mongo
58
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
59
  #
60
60
  # @example Connect to a sharded cluster and provide two seed nodes.
61
- # Mongo::ShardedConnection.new(['localhost:30000', 'localhost:30001'])
61
+ # MongoShardedClient.new(['localhost:30000', 'localhost:30001'])
62
62
  #
63
63
  # @raise [MongoArgumentError] This is raised for usage errors.
64
64
  #
@@ -71,14 +71,14 @@ module Mongo
71
71
  if nodes.empty? and ENV.has_key?('MONGODB_URI')
72
72
  parser = URIParser.new ENV['MONGODB_URI']
73
73
  if parser.direct?
74
- raise MongoArgumentError, "Mongo::ShardedConnection.new called with no arguments, but ENV['MONGODB_URI'] implies a direct connection."
74
+ raise MongoArgumentError, "Mongo::MongoShardedClient.new called with no arguments, but ENV['MONGODB_URI'] implies a direct connection."
75
75
  end
76
76
  opts = parser.connection_options.merge! opts
77
77
  nodes = [parser.nodes]
78
78
  end
79
79
 
80
80
  unless nodes.length > 0
81
- raise MongoArgumentError, "A ShardedConnection requires at least one seed node."
81
+ raise MongoArgumentError, "A MongoShardedClient requires at least one seed node."
82
82
  end
83
83
 
84
84
  @seeds = nodes.map do |host_port|
@@ -118,7 +118,7 @@ module Mongo
118
118
  end
119
119
 
120
120
  def inspect
121
- "<Mongo::ShardedConnection:0x#{self.object_id.to_s(16)} @seeds=#{@seeds.inspect} " +
121
+ "<Mongo::MongoShardedClient:0x#{self.object_id.to_s(16)} @seeds=#{@seeds.inspect} " +
122
122
  "@connected=#{@connected}>"
123
123
  end
124
124
 
@@ -18,7 +18,7 @@ module Mongo
18
18
  # @return [Integer] number of bytes sent
19
19
  def send_message(operation, message, opts={})
20
20
  if opts.is_a?(String)
21
- warn "Connection#send_message no longer takes a string log message. " +
21
+ warn "MongoClient#send_message no longer takes a string log message. " +
22
22
  "Logging is now handled within the Collection and Cursor classes."
23
23
  opts = {}
24
24
  end
@@ -56,12 +56,11 @@ module Mongo
56
56
  # @see DB#get_last_error for valid last error params.
57
57
  #
58
58
  # @return [Hash] The document returned by the call to getlasterror.
59
- def send_message_with_safe_check(operation, message, db_name, log_message=nil, last_error_params=false)
59
+ def send_message_with_gle(operation, message, db_name, log_message=nil, write_concern=false)
60
60
  docs = num_received = cursor_id = ''
61
61
  add_message_headers(message, operation)
62
62
 
63
- last_error_message = BSON::ByteBuffer.new
64
- build_last_error_message(last_error_message, db_name, last_error_params)
63
+ last_error_message = build_get_last_error_message(db_name, write_concern)
65
64
  last_error_id = add_message_headers(last_error_message, Mongo::Constants::OP_QUERY)
66
65
 
67
66
  packed_message = message.append!(last_error_message).to_s
@@ -181,7 +180,7 @@ module Mongo
181
180
 
182
181
  # unpacks to flags, cursor_id_a, cursor_id_b, starting_from, number_remaining
183
182
  flags, cursor_id_a, cursor_id_b, _, number_remaining = header_buf.unpack('VVVVV')
184
-
183
+
185
184
  check_response_flags(flags)
186
185
  cursor_id = (cursor_id_b << 32) + cursor_id_a
187
186
  [number_remaining, cursor_id]
@@ -209,23 +208,28 @@ module Mongo
209
208
  [docs, number_received]
210
209
  end
211
210
 
212
- # Constructs a getlasterror message. This method is used exclusively by
213
- # Connection#send_message_with_safe_check.
214
- #
215
- # Because it modifies message by reference, we don't need to return it.
216
- def build_last_error_message(message, db_name, opts)
211
+ def build_command_message(db_name, query, projection=nil, skip=0, limit=-1)
212
+ message = BSON::ByteBuffer.new
217
213
  message.put_int(0)
218
214
  BSON::BSON_RUBY.serialize_cstr(message, "#{db_name}.$cmd")
219
- message.put_int(0)
220
- message.put_int(-1)
221
- cmd = BSON::OrderedHash.new
222
- cmd[:getlasterror] = 1
223
- if opts.is_a?(Hash)
224
- opts.assert_valid_keys(:w, :wtimeout, :fsync, :j)
225
- cmd.merge!(opts)
215
+ message.put_int(skip)
216
+ message.put_int(limit)
217
+ message.put_binary(BSON::BSON_CODER.serialize(query, false).to_s)
218
+ message.put_binary(BSON::BSON_CODER.serialize(projection, false).to_s) if projection
219
+ message
220
+ end
221
+
222
+ # Constructs a getlasterror message. This method is used exclusively by
223
+ # MongoClient#send_message_with_gle.
224
+ def build_get_last_error_message(db_name, write_concern)
225
+ gle = BSON::OrderedHash.new
226
+ gle[:getlasterror] = 1
227
+ if write_concern.is_a?(Hash)
228
+ write_concern.assert_valid_keys(:w, :wtimeout, :fsync, :j)
229
+ gle.merge!(write_concern)
230
+ gle.delete(:w) if gle[:w] == 1
226
231
  end
227
- message.put_binary(BSON::BSON_CODER.serialize(cmd, false).to_s)
228
- nil
232
+ build_command_message(db_name, gle)
229
233
  end
230
234
 
231
235
  # Prepares a message for transmission to MongoDB by
@@ -282,6 +286,7 @@ module Mongo
282
286
  end
283
287
  total_bytes_sent
284
288
  rescue => ex
289
+ socket.close
285
290
  raise ConnectionFailure, "Operation failed with the following exception: #{ex}:#{ex.message}"
286
291
  end
287
292
  end
@@ -306,7 +311,7 @@ module Mongo
306
311
  def receive_data(length, socket)
307
312
  message = new_binary_string
308
313
  socket.read(length, message)
309
-
314
+
310
315
  raise ConnectionFailure, "connection closed" unless message && message.length > 0
311
316
  if message.length < length
312
317
  chunk = new_binary_string
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  # --
4
- # Copyright (C) 2008-2011 10gen Inc.
4
+ # Copyright (C) 2008-2012 10gen Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  # --
4
- # Copyright (C) 2008-2011 10gen Inc.
4
+ # Copyright (C) 2008-2012 10gen Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -29,17 +29,28 @@ module Mongo
29
29
  # Execute the block and log the operation described by name and payload.
30
30
  def instrument(name, payload = {})
31
31
  start_time = Time.now
32
- res = yield
33
- log_operation(name, payload, start_time)
32
+ res = Logging.instrumenter.instrument(name, payload) do
33
+ yield
34
+ end
35
+ duration = Time.now - start_time
36
+ log_operation(name, payload, duration)
34
37
  res
35
38
  end
36
39
 
40
+ def self.instrumenter
41
+ @instrumenter || Instrumenter
42
+ end
43
+
44
+ def self.instrumenter=(instrumenter)
45
+ @instrumenter = instrumenter
46
+ end
47
+
37
48
  protected
38
49
 
39
- def log_operation(name, payload, start_time)
50
+ def log_operation(name, payload, duration)
40
51
  @logger && @logger.debug do
41
52
  msg = "MONGODB "
42
- msg << "(#{((Time.now - start_time) * 1000).to_i}ms) "
53
+ msg << "(%.1fms) " % (duration * 1000)
43
54
  msg << "#{payload[:database]}['#{payload[:collection]}'].#{name}("
44
55
  msg << payload.values_at(:selector, :document, :documents, :fields ).compact.map(&:inspect).join(', ') + ")"
45
56
  msg << ".skip(#{payload[:skip]})" if payload[:skip]
@@ -49,5 +60,10 @@ module Mongo
49
60
  end
50
61
  end
51
62
 
63
+ module Instrumenter
64
+ def self.instrument(name, payload = {})
65
+ yield
66
+ end
67
+ end
52
68
  end
53
69
  end
@@ -1,10 +1,10 @@
1
1
  module Mongo
2
2
  class Node
3
3
 
4
- attr_accessor :host, :port, :address, :config, :connection, :socket, :last_state
4
+ attr_accessor :host, :port, :address, :config, :client, :socket, :last_state
5
5
 
6
- def initialize(connection, host_port)
7
- @connection = connection
6
+ def initialize(client, host_port)
7
+ @client = client
8
8
  @host, @port = split_node(host_port)
9
9
  @address = "#{@host}:#{@port}"
10
10
  @config = nil
@@ -29,11 +29,11 @@ module Mongo
29
29
  # return nil.
30
30
  def connect
31
31
  begin
32
- socket = @connection.socket_class.new(@host, @port,
33
- @connection.op_timeout, @connection.connect_timeout
32
+ socket = @client.socket_class.new(@host, @port,
33
+ @client.op_timeout, @client.connect_timeout
34
34
  )
35
35
  rescue OperationTimeout, ConnectionFailure, OperationFailure, SocketError, SystemCallError, IOError => ex
36
- @connection.log(:debug, "Failed connection to #{host_string} with #{ex.class}, #{ex.message}.")
36
+ @client.log(:debug, "Failed connection to #{host_string} with #{ex.class}, #{ex.message}.")
37
37
  socket.close if socket
38
38
  end
39
39
 
@@ -54,7 +54,7 @@ module Mongo
54
54
 
55
55
  def active?
56
56
  begin
57
- result = @connection['admin'].command({:ping => 1}, :socket => @socket)
57
+ result = @client['admin'].command({:ping => 1}, :socket => @socket)
58
58
  rescue OperationFailure, SocketError, SystemCallError, IOError
59
59
  return nil
60
60
  end
@@ -66,16 +66,16 @@ module Mongo
66
66
  # matches with the name provided.
67
67
  def set_config
68
68
  begin
69
- @config = @connection['admin'].command({:ismaster => 1}, :socket => @socket)
69
+ @config = @client['admin'].command({:ismaster => 1}, :socket => @socket)
70
70
 
71
71
  if @config['msg']
72
- @connection.log(:warn, "#{config['msg']}")
72
+ @client.log(:warn, "#{config['msg']}")
73
73
  end
74
74
 
75
75
  check_set_membership(config)
76
76
  check_set_name(config)
77
77
  rescue ConnectionFailure, OperationFailure, OperationTimeout, SocketError, SystemCallError, IOError => ex
78
- @connection.log(:warn, "Attempted connection to node #{host_string} raised " +
78
+ @client.log(:warn, "Attempted connection to node #{host_string} raised " +
79
79
  "#{ex.class}: #{ex.message}")
80
80
 
81
81
  # Socket may already be nil from issuing command
@@ -145,12 +145,12 @@ module Mongo
145
145
  end
146
146
 
147
147
  host = host_port[0]
148
- port = host_port[1].nil? ? Connection::DEFAULT_PORT : host_port[1].to_i
148
+ port = host_port[1].nil? ? MongoClient::DEFAULT_PORT : host_port[1].to_i
149
149
 
150
150
  [host, port]
151
151
  end
152
152
 
153
- # Ensure that this node is a healty member of a replica set.
153
+ # Ensure that this node is a healthy member of a replica set.
154
154
  def check_set_membership(config)
155
155
  if !config.has_key?('hosts')
156
156
  message = "Will not connect to #{host_string} because it's not a member " +
@@ -165,13 +165,13 @@ module Mongo
165
165
 
166
166
  # Ensure that this node is part of a replica set of the expected name.
167
167
  def check_set_name(config)
168
- if @connection.replica_set_name
168
+ if @client.replica_set_name
169
169
  if !config['setName']
170
- @connection.log(:warn, "Could not verify replica set name for member #{host_string} " +
170
+ @client.log(:warn, "Could not verify replica set name for member #{host_string} " +
171
171
  "because ismaster does not return name in this version of MongoDB")
172
- elsif @connection.replica_set_name != config['setName']
172
+ elsif @client.replica_set_name != config['setName']
173
173
  message = "Attempting to connect to replica set '#{config['setName']}' on member #{host_string} " +
174
- "but expected '#{@connection.replica_set_name}'"
174
+ "but expected '#{@client.replica_set_name}'"
175
175
  raise ReplicaSetConnectionError, message
176
176
  end
177
177
  end
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  # --
4
- # Copyright (C) 2008-2011 10gen Inc.
4
+ # Copyright (C) 2008-2012 10gen Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -21,12 +21,17 @@ module Mongo
21
21
  MAX_PING_TIME = 1_000_000
22
22
  PRUNE_INTERVAL = 10_000
23
23
 
24
- attr_accessor :host, :port, :address,
25
- :size, :timeout, :safe, :checked_out, :connection
24
+ attr_accessor :host,
25
+ :port,
26
+ :address,
27
+ :size,
28
+ :timeout,
29
+ :checked_out,
30
+ :client
26
31
 
27
32
  # Create a new pool of connections.
28
- def initialize(connection, host, port, opts={})
29
- @connection = connection
33
+ def initialize(client, host, port, opts={})
34
+ @client = client
30
35
 
31
36
  @host, @port = host, port
32
37
 
@@ -43,25 +48,28 @@ module Mongo
43
48
  # Mutex for synchronizing pool access
44
49
  @connection_mutex = Mutex.new
45
50
 
51
+ # Mutex for synchronizing pings
52
+ @ping_mutex = Mutex.new
53
+
46
54
  # Condition variable for signal and wait
47
55
  @queue = ConditionVariable.new
48
56
 
49
57
  # Operations to perform on a socket
50
58
  @socket_ops = Hash.new { |h, k| h[k] = [] }
51
59
 
52
- @sockets = []
53
- @pids = {}
54
- @checked_out = []
55
- @ping_time = nil
56
- @last_ping = nil
57
- @closed = false
60
+ @sockets = []
61
+ @pids = {}
62
+ @checked_out = []
63
+ @ping_time = nil
64
+ @last_ping = nil
65
+ @closed = false
58
66
  @threads_to_sockets = {}
59
67
  @checkout_counter = 0
60
68
  end
61
69
 
62
70
  # Close this pool.
63
71
  #
64
- # @option opts [Boolean] :soft (false) If true,
72
+ # @option opts [Boolean]:soft (false) If true,
65
73
  # close only those sockets that are not checked out.
66
74
  def close(opts={})
67
75
  @connection_mutex.synchronize do
@@ -85,6 +93,29 @@ module Mongo
85
93
  @closed
86
94
  end
87
95
 
96
+ def up?
97
+ !@closed
98
+ end
99
+
100
+ def matches_mode(mode)
101
+ if mode == :primary && @node.secondary? ||
102
+ mode == :secondary && @node.primary?
103
+ false
104
+ else
105
+ true
106
+ end
107
+ end
108
+
109
+ def matches_tag_set(tag_set)
110
+ tag_set.all? do |tag, value|
111
+ tags.has_key?(tag) && tags[tag] == value
112
+ end
113
+ end
114
+
115
+ def matches_tag_sets(tag_sets)
116
+ tag_sets.all? {|set| matches_tag_set(set)}
117
+ end
118
+
88
119
  def inspect
89
120
  "#<Mongo::Pool:0x#{self.object_id.to_s(16)} @host=#{@host} @port=#{port} " +
90
121
  "@ping_time=#{@ping_time} #{@checked_out.size}/#{@size} sockets available " +
@@ -102,15 +133,13 @@ module Mongo
102
133
  # Refresh ping time only if we haven't
103
134
  # checked within the last five minutes.
104
135
  def ping_time
105
- if !@last_ping
106
- @last_ping = Time.now
107
- @ping_time = refresh_ping_time
108
- elsif Time.now - @last_ping > 300
109
- @last_ping = Time.now
110
- @ping_time = refresh_ping_time
111
- else
112
- @ping_time
136
+ @ping_mutex.synchronize do
137
+ if !@last_ping || (Time.now - @last_ping) > 300
138
+ @ping_time = refresh_ping_time
139
+ @last_ping = Time.now
140
+ end
113
141
  end
142
+ @ping_time
114
143
  end
115
144
 
116
145
  # Return the time it takes on average
@@ -139,7 +168,7 @@ module Mongo
139
168
 
140
169
  def ping
141
170
  begin
142
- return self.connection['admin'].command({:ping => 1}, :socket => @node.socket, :timeout => 1)
171
+ return self.client['admin'].command({:ping => 1}, :socket => @node.socket, :timeout => MAX_PING_TIME)
143
172
  rescue ConnectionFailure, OperationFailure, SocketError, SystemCallError, IOError
144
173
  return false
145
174
  end
@@ -163,7 +192,7 @@ module Mongo
163
192
  # therefore, it runs within a mutex.
164
193
  def checkout_new_socket
165
194
  begin
166
- socket = @connection.socket_class.new(@host, @port, @connection.op_timeout)
195
+ socket = @client.socket_class.new(@host, @port, @client.op_timeout)
167
196
  socket.pool = self
168
197
  rescue => ex
169
198
  socket.close if socket
@@ -173,7 +202,7 @@ module Mongo
173
202
 
174
203
  # If any saved authentications exist, we want to apply those
175
204
  # when creating new sockets.
176
- @connection.apply_saved_authentication(:socket => socket)
205
+ @client.apply_saved_authentication(:socket => socket)
177
206
 
178
207
  @sockets << socket
179
208
  @pids[socket] = Process.pid
@@ -190,7 +219,7 @@ module Mongo
190
219
  @connection_mutex.synchronize do
191
220
  @sockets.each do |socket|
192
221
  @socket_ops[socket] << Proc.new do
193
- @connection.apply_saved_authentication(:socket => socket)
222
+ @client.apply_saved_authentication(:socket => socket)
194
223
  end
195
224
  end
196
225
  end
@@ -202,7 +231,7 @@ module Mongo
202
231
  @connection_mutex.synchronize do
203
232
  @sockets.each do |socket|
204
233
  @socket_ops[socket] << Proc.new do
205
- @connection.db(db).issue_logout(:socket => socket)
234
+ @client.db(db).issue_logout(:socket => socket)
206
235
  end
207
236
  end
208
237
  end
@@ -246,7 +275,7 @@ module Mongo
246
275
  # pool size has not been exceeded. Otherwise, wait for the next
247
276
  # available socket.
248
277
  def checkout
249
- @connection.connect if !@connection.connected?
278
+ @client.connect if !@client.connected?
250
279
  start_time = Time.now
251
280
  loop do
252
281
  if (Time.now - start_time) > @timeout
@@ -297,7 +326,7 @@ module Mongo
297
326
 
298
327
  socket = checkout_new_socket
299
328
  end
300
-
329
+
301
330
  return socket
302
331
  else
303
332
  # Otherwise, wait