mongo 1.3.0 → 1.12.5
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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +122 -271
- data/Rakefile +25 -209
- data/VERSION +1 -0
- data/bin/mongo_console +31 -9
- data/lib/mongo/bulk_write_collection_view.rb +387 -0
- data/lib/mongo/collection.rb +576 -269
- data/lib/mongo/collection_writer.rb +364 -0
- data/lib/mongo/connection/node.rb +249 -0
- data/lib/mongo/connection/pool.rb +340 -0
- data/lib/mongo/connection/pool_manager.rb +320 -0
- data/lib/mongo/connection/sharding_pool_manager.rb +67 -0
- data/lib/mongo/connection/socket/socket_util.rb +37 -0
- data/lib/mongo/connection/socket/ssl_socket.rb +95 -0
- data/lib/mongo/connection/socket/tcp_socket.rb +87 -0
- data/lib/mongo/connection/socket/unix_socket.rb +39 -0
- data/lib/mongo/connection/socket.rb +18 -0
- data/lib/mongo/connection.rb +7 -875
- data/lib/mongo/cursor.rb +403 -117
- data/lib/mongo/db.rb +444 -243
- data/lib/mongo/exception.rb +145 -0
- data/lib/mongo/functional/authentication.rb +455 -0
- data/lib/mongo/functional/logging.rb +85 -0
- data/lib/mongo/functional/read_preference.rb +183 -0
- data/lib/mongo/functional/scram.rb +556 -0
- data/lib/mongo/functional/uri_parser.rb +409 -0
- data/lib/mongo/functional/write_concern.rb +66 -0
- data/lib/mongo/functional.rb +20 -0
- data/lib/mongo/gridfs/grid.rb +30 -24
- data/lib/mongo/gridfs/grid_ext.rb +6 -10
- data/lib/mongo/gridfs/grid_file_system.rb +38 -20
- data/lib/mongo/gridfs/grid_io.rb +84 -75
- data/lib/mongo/gridfs.rb +18 -0
- data/lib/mongo/legacy.rb +140 -0
- data/lib/mongo/mongo_client.rb +697 -0
- data/lib/mongo/mongo_replica_set_client.rb +535 -0
- data/lib/mongo/mongo_sharded_client.rb +159 -0
- data/lib/mongo/networking.rb +372 -0
- data/lib/mongo/{util → utils}/conversions.rb +29 -8
- data/lib/mongo/{util → utils}/core_ext.rb +28 -18
- data/lib/mongo/{util → utils}/server_version.rb +4 -6
- data/lib/mongo/{util → utils}/support.rb +29 -31
- data/lib/mongo/utils/thread_local_variable_manager.rb +25 -0
- data/lib/mongo/utils.rb +19 -0
- data/lib/mongo.rb +51 -50
- data/mongo.gemspec +29 -32
- data/test/functional/authentication_test.rb +39 -0
- data/test/functional/bulk_api_stress_test.rb +133 -0
- data/test/functional/bulk_write_collection_view_test.rb +1198 -0
- data/test/functional/client_test.rb +627 -0
- data/test/functional/collection_test.rb +2175 -0
- data/test/functional/collection_writer_test.rb +83 -0
- data/test/{conversions_test.rb → functional/conversions_test.rb} +47 -3
- data/test/functional/cursor_fail_test.rb +57 -0
- data/test/functional/cursor_message_test.rb +56 -0
- data/test/functional/cursor_test.rb +683 -0
- data/test/functional/db_api_test.rb +835 -0
- data/test/functional/db_connection_test.rb +25 -0
- data/test/functional/db_test.rb +348 -0
- data/test/functional/grid_file_system_test.rb +285 -0
- data/test/{grid_io_test.rb → functional/grid_io_test.rb} +72 -11
- data/test/{grid_test.rb → functional/grid_test.rb} +88 -15
- data/test/functional/pool_test.rb +136 -0
- data/test/functional/safe_test.rb +98 -0
- data/test/functional/ssl_test.rb +29 -0
- data/test/functional/support_test.rb +62 -0
- data/test/functional/timeout_test.rb +60 -0
- data/test/functional/uri_test.rb +446 -0
- data/test/functional/write_concern_test.rb +118 -0
- data/test/helpers/general.rb +50 -0
- data/test/helpers/test_unit.rb +476 -0
- data/test/replica_set/authentication_test.rb +37 -0
- data/test/replica_set/basic_test.rb +189 -0
- data/test/replica_set/client_test.rb +393 -0
- data/test/replica_set/connection_test.rb +138 -0
- data/test/replica_set/count_test.rb +66 -0
- data/test/replica_set/cursor_test.rb +220 -0
- data/test/replica_set/insert_test.rb +157 -0
- data/test/replica_set/max_values_test.rb +151 -0
- data/test/replica_set/pinning_test.rb +105 -0
- data/test/replica_set/query_test.rb +73 -0
- data/test/replica_set/read_preference_test.rb +219 -0
- data/test/replica_set/refresh_test.rb +211 -0
- data/test/replica_set/replication_ack_test.rb +95 -0
- data/test/replica_set/ssl_test.rb +32 -0
- data/test/sharded_cluster/basic_test.rb +203 -0
- data/test/shared/authentication/basic_auth_shared.rb +260 -0
- data/test/shared/authentication/bulk_api_auth_shared.rb +249 -0
- data/test/shared/authentication/gssapi_shared.rb +176 -0
- data/test/shared/authentication/sasl_plain_shared.rb +96 -0
- data/test/shared/authentication/scram_shared.rb +92 -0
- data/test/shared/ssl_shared.rb +235 -0
- data/test/test_helper.rb +53 -94
- data/test/threading/basic_test.rb +120 -0
- data/test/tools/mongo_config.rb +708 -0
- data/test/tools/mongo_config_test.rb +160 -0
- data/test/unit/client_test.rb +381 -0
- data/test/unit/collection_test.rb +89 -53
- data/test/unit/connection_test.rb +282 -32
- data/test/unit/cursor_test.rb +206 -8
- data/test/unit/db_test.rb +55 -13
- data/test/unit/grid_test.rb +43 -16
- data/test/unit/mongo_sharded_client_test.rb +48 -0
- data/test/unit/node_test.rb +93 -0
- data/test/unit/pool_manager_test.rb +111 -0
- data/test/unit/read_pref_test.rb +406 -0
- data/test/unit/read_test.rb +159 -0
- data/test/unit/safe_test.rb +69 -36
- data/test/unit/sharding_pool_manager_test.rb +84 -0
- data/test/unit/write_concern_test.rb +175 -0
- data.tar.gz.sig +3 -0
- metadata +227 -216
- metadata.gz.sig +0 -0
- data/docs/CREDITS.md +0 -123
- data/docs/FAQ.md +0 -116
- data/docs/GridFS.md +0 -158
- data/docs/HISTORY.md +0 -244
- data/docs/RELEASES.md +0 -33
- data/docs/REPLICA_SETS.md +0 -72
- data/docs/TUTORIAL.md +0 -247
- data/docs/WRITE_CONCERN.md +0 -28
- data/lib/mongo/exceptions.rb +0 -71
- data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
- data/lib/mongo/repl_set_connection.rb +0 -342
- data/lib/mongo/test.rb +0 -20
- data/lib/mongo/util/pool.rb +0 -177
- data/lib/mongo/util/uri_parser.rb +0 -185
- data/test/async/collection_test.rb +0 -224
- data/test/async/connection_test.rb +0 -24
- data/test/async/cursor_test.rb +0 -162
- data/test/async/worker_pool_test.rb +0 -99
- data/test/auxillary/1.4_features.rb +0 -166
- data/test/auxillary/authentication_test.rb +0 -68
- data/test/auxillary/autoreconnect_test.rb +0 -41
- data/test/auxillary/fork_test.rb +0 -30
- data/test/auxillary/repl_set_auth_test.rb +0 -58
- data/test/auxillary/slave_connection_test.rb +0 -36
- data/test/auxillary/threaded_authentication_test.rb +0 -101
- data/test/bson/binary_test.rb +0 -15
- data/test/bson/bson_test.rb +0 -649
- data/test/bson/byte_buffer_test.rb +0 -208
- data/test/bson/hash_with_indifferent_access_test.rb +0 -38
- data/test/bson/json_test.rb +0 -17
- data/test/bson/object_id_test.rb +0 -154
- data/test/bson/ordered_hash_test.rb +0 -204
- data/test/bson/timestamp_test.rb +0 -24
- data/test/collection_test.rb +0 -910
- data/test/connection_test.rb +0 -309
- data/test/cursor_fail_test.rb +0 -75
- data/test/cursor_message_test.rb +0 -43
- data/test/cursor_test.rb +0 -483
- data/test/db_api_test.rb +0 -726
- data/test/db_connection_test.rb +0 -15
- data/test/db_test.rb +0 -287
- data/test/grid_file_system_test.rb +0 -243
- data/test/load/resque/load.rb +0 -21
- data/test/load/resque/processor.rb +0 -26
- data/test/load/thin/load.rb +0 -24
- data/test/load/unicorn/load.rb +0 -23
- data/test/load/unicorn/unicorn.rb +0 -29
- data/test/replica_sets/connect_test.rb +0 -94
- data/test/replica_sets/connection_string_test.rb +0 -32
- data/test/replica_sets/count_test.rb +0 -35
- data/test/replica_sets/insert_test.rb +0 -53
- data/test/replica_sets/pooled_insert_test.rb +0 -55
- data/test/replica_sets/query_secondaries.rb +0 -96
- data/test/replica_sets/query_test.rb +0 -51
- data/test/replica_sets/replication_ack_test.rb +0 -66
- data/test/replica_sets/rs_test_helper.rb +0 -27
- data/test/safe_test.rb +0 -68
- data/test/support/hash_with_indifferent_access.rb +0 -186
- data/test/support/keys.rb +0 -45
- data/test/support_test.rb +0 -18
- data/test/threading/threading_with_large_pool_test.rb +0 -90
- data/test/threading_test.rb +0 -87
- data/test/tools/auth_repl_set_manager.rb +0 -14
- data/test/tools/load.rb +0 -58
- data/test/tools/repl_set_manager.rb +0 -266
- data/test/tools/sharding_manager.rb +0 -202
- data/test/tools/test.rb +0 -4
- data/test/unit/pool_test.rb +0 -9
- data/test/unit/repl_set_connection_test.rb +0 -59
- data/test/uri_test.rb +0 -91
@@ -1,342 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# --
|
4
|
-
# Copyright (C) 2008-2011 10gen Inc.
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
# ++
|
18
|
-
|
19
|
-
module Mongo
|
20
|
-
|
21
|
-
# Instantiates and manages connections to a MongoDB replica set.
|
22
|
-
class ReplSetConnection < Connection
|
23
|
-
attr_reader :nodes, :secondaries, :arbiters, :read_pool, :secondary_pools
|
24
|
-
|
25
|
-
# Create a connection to a MongoDB replica set.
|
26
|
-
#
|
27
|
-
# Once connected to a replica set, you can find out which nodes are primary, secondary, and
|
28
|
-
# arbiters with the corresponding accessors: Connection#primary, Connection#secondaries, and
|
29
|
-
# Connection#arbiters. This is useful if your application needs to connect manually to nodes other
|
30
|
-
# than the primary.
|
31
|
-
#
|
32
|
-
# @param [Array] args A list of host-port pairs to be used as seed nodes followed by a
|
33
|
-
# hash containing any options. See the examples below for exactly how to use the constructor.
|
34
|
-
#
|
35
|
-
# @option options [String] :rs_name (nil) The name of the replica set to connect to. You
|
36
|
-
# can use this option to verify that you're connecting to the right replica set.
|
37
|
-
# @option options [Boolean, Hash] :safe (false) Set the default safe-mode options
|
38
|
-
# propogated to DB objects instantiated off of this Connection. This
|
39
|
-
# default can be overridden upon instantiation of any DB by explicity setting a :safe value
|
40
|
-
# on initialization.
|
41
|
-
# @option options [Boolean] :read_secondary(false) If true, a random secondary node will be chosen,
|
42
|
-
# and all reads will be directed to that node.
|
43
|
-
# @option options [Logger, #debug] :logger (nil) Logger instance to receive driver operation log.
|
44
|
-
# @option options [Integer] :pool_size (1) The maximum number of socket connections allowed per
|
45
|
-
# connection pool. Note: this setting is relevant only for multi-threaded applications.
|
46
|
-
# @option options [Float] :timeout (5.0) When all of the connections a pool are checked out,
|
47
|
-
# this is the number of seconds to wait for a new connection to be released before throwing an exception.
|
48
|
-
# Note: this setting is relevant only for multi-threaded applications.
|
49
|
-
#
|
50
|
-
# @example Connect to a replica set and provide two seed nodes. Note that the number of seed nodes does
|
51
|
-
# not have to be equal to the number of replica set members. The purpose of seed nodes is to permit
|
52
|
-
# the driver to find at least one replica set member even if a member is down.
|
53
|
-
# ReplSetConnection.new(['localhost', 30000], ['localhost', 30001])
|
54
|
-
#
|
55
|
-
# @example Connect to a replica set providing two seed nodes and ensuring a connection to the replica set named 'prod':
|
56
|
-
# ReplSetConnection.new(['localhost', 30000], ['localhost', 30001], :rs_name => 'prod')
|
57
|
-
#
|
58
|
-
# @example Connect to a replica set providing two seed nodes and allowing reads from a secondary node:
|
59
|
-
# ReplSetConnection.new(['localhost', 30000], ['localhost', 30001], :read_secondary => true)
|
60
|
-
#
|
61
|
-
# @see http://api.mongodb.org/ruby/current/file.REPLICA_SETS.html Replica sets in Ruby
|
62
|
-
#
|
63
|
-
# @raise [ReplicaSetConnectionError] This is raised if a replica set name is specified and the
|
64
|
-
# driver fails to connect to a replica set with that name.
|
65
|
-
def initialize(*args)
|
66
|
-
if args.last.is_a?(Hash)
|
67
|
-
opts = args.pop
|
68
|
-
else
|
69
|
-
opts = {}
|
70
|
-
end
|
71
|
-
|
72
|
-
unless args.length > 0
|
73
|
-
raise MongoArgumentError, "A ReplSetConnection requires at least one node."
|
74
|
-
end
|
75
|
-
|
76
|
-
# Get seed nodes
|
77
|
-
@nodes = args
|
78
|
-
|
79
|
-
# Replica set name
|
80
|
-
@replica_set = opts[:rs_name]
|
81
|
-
|
82
|
-
# Cache the various node types when connecting to a replica set.
|
83
|
-
@secondaries = []
|
84
|
-
@arbiters = []
|
85
|
-
|
86
|
-
# Connection pools for each secondary node
|
87
|
-
@secondary_pools = []
|
88
|
-
@read_pool = nil
|
89
|
-
|
90
|
-
# Are we allowing reads from secondaries?
|
91
|
-
@read_secondary = opts.fetch(:read_secondary, false)
|
92
|
-
|
93
|
-
setup(opts)
|
94
|
-
end
|
95
|
-
|
96
|
-
# Create a new socket and attempt to connect to master.
|
97
|
-
# If successful, sets host and port to master and returns the socket.
|
98
|
-
#
|
99
|
-
# If connecting to a replica set, this method will replace the
|
100
|
-
# initially-provided seed list with any nodes known to the set.
|
101
|
-
#
|
102
|
-
# @raise [ConnectionFailure] if unable to connect to any host or port.
|
103
|
-
def connect
|
104
|
-
close
|
105
|
-
@nodes_to_try = @nodes.clone
|
106
|
-
|
107
|
-
while connecting?
|
108
|
-
node = @nodes_to_try.shift
|
109
|
-
config = check_is_master(node)
|
110
|
-
|
111
|
-
if is_primary?(config)
|
112
|
-
set_primary(node)
|
113
|
-
else
|
114
|
-
set_auxillary(node, config)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
pick_secondary_for_read if @read_secondary
|
119
|
-
|
120
|
-
if connected?
|
121
|
-
BSON::BSON_CODER.update_max_bson_size(self)
|
122
|
-
else
|
123
|
-
if @secondary_pools.empty?
|
124
|
-
close # close any existing pools and sockets
|
125
|
-
raise ConnectionFailure, "Failed to connect any given host:port"
|
126
|
-
else
|
127
|
-
close # close any existing pools and sockets
|
128
|
-
raise ConnectionFailure, "Failed to connect to primary node."
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
alias :reconnect :connect
|
133
|
-
|
134
|
-
def connecting?
|
135
|
-
@nodes_to_try.length > 0
|
136
|
-
end
|
137
|
-
|
138
|
-
# The replica set primary's host name.
|
139
|
-
#
|
140
|
-
# @return [String]
|
141
|
-
def host
|
142
|
-
super
|
143
|
-
end
|
144
|
-
|
145
|
-
# The replica set primary's port.
|
146
|
-
#
|
147
|
-
# @return [Integer]
|
148
|
-
def port
|
149
|
-
super
|
150
|
-
end
|
151
|
-
|
152
|
-
# Determine whether we're reading from a primary node. If false,
|
153
|
-
# this connection connects to a secondary node and @read_secondaries is true.
|
154
|
-
#
|
155
|
-
# @return [Boolean]
|
156
|
-
def read_primary?
|
157
|
-
!@read_pool
|
158
|
-
end
|
159
|
-
alias :primary? :read_primary?
|
160
|
-
|
161
|
-
# Close the connection to the database.
|
162
|
-
def close
|
163
|
-
super
|
164
|
-
@read_pool = nil
|
165
|
-
@secondary_pools.each do |pool|
|
166
|
-
pool.close
|
167
|
-
end
|
168
|
-
@secondaries = []
|
169
|
-
@secondary_pools = []
|
170
|
-
@arbiters = []
|
171
|
-
@nodes_tried = []
|
172
|
-
@nodes_to_try = []
|
173
|
-
end
|
174
|
-
|
175
|
-
# If a ConnectionFailure is raised, this method will be called
|
176
|
-
# to close the connection and reset connection values.
|
177
|
-
# @deprecated
|
178
|
-
def reset_connection
|
179
|
-
close
|
180
|
-
warn "ReplSetConnection#reset_connection is now deprecated. " +
|
181
|
-
"Use ReplSetConnection#close instead."
|
182
|
-
end
|
183
|
-
|
184
|
-
# Is it okay to connect to a slave?
|
185
|
-
#
|
186
|
-
# @return [Boolean]
|
187
|
-
def slave_ok?
|
188
|
-
@read_secondary || @slave_ok
|
189
|
-
end
|
190
|
-
|
191
|
-
def authenticate_pools
|
192
|
-
super
|
193
|
-
@secondary_pools.each do |pool|
|
194
|
-
pool.authenticate_existing
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def logout_pools(db)
|
199
|
-
super
|
200
|
-
@secondary_pools.each do |pool|
|
201
|
-
pool.logout_existing(db)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
private
|
206
|
-
|
207
|
-
def check_is_master(node)
|
208
|
-
begin
|
209
|
-
host, port = *node
|
210
|
-
socket = TCPSocket.new(host, port)
|
211
|
-
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
212
|
-
|
213
|
-
config = self['admin'].command({:ismaster => 1}, :socket => socket)
|
214
|
-
|
215
|
-
check_set_name(config, socket)
|
216
|
-
rescue OperationFailure, SocketError, SystemCallError, IOError => ex
|
217
|
-
# It's necessary to rescue here. The #connect method will keep trying
|
218
|
-
# until it has no more nodes to try and raise a ConnectionFailure if
|
219
|
-
# it can't connect to a primary.
|
220
|
-
ensure
|
221
|
-
socket.close if socket
|
222
|
-
@nodes_tried << node
|
223
|
-
|
224
|
-
if config
|
225
|
-
nodes = []
|
226
|
-
nodes += config['hosts'] if config['hosts']
|
227
|
-
nodes += config['arbiters'] if config['arbiters']
|
228
|
-
nodes += config['passives'] if config['passives']
|
229
|
-
update_node_list(nodes)
|
230
|
-
|
231
|
-
if config['msg'] && @logger
|
232
|
-
@logger.warn("MONGODB #{config['msg']}")
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
config
|
238
|
-
end
|
239
|
-
|
240
|
-
# Primary, when connecting to a replica can, can only be a true primary node.
|
241
|
-
# (And not a slave, which is possible when connecting with the standard
|
242
|
-
# Connection class.
|
243
|
-
def is_primary?(config)
|
244
|
-
config && (config['ismaster'] == 1 || config['ismaster'] == true)
|
245
|
-
end
|
246
|
-
|
247
|
-
# Pick a node randomly from the set of possible secondaries.
|
248
|
-
def pick_secondary_for_read
|
249
|
-
if (size = @secondary_pools.size) > 0
|
250
|
-
@read_pool = @secondary_pools[rand(size)]
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
# Make sure that we're connected to the expected replica set.
|
255
|
-
def check_set_name(config, socket)
|
256
|
-
if @replica_set
|
257
|
-
config = self['admin'].command({:replSetGetStatus => 1},
|
258
|
-
:socket => socket, :check_response => false)
|
259
|
-
|
260
|
-
if !Mongo::Support.ok?(config)
|
261
|
-
raise ReplicaSetConnectionError, config['errmsg']
|
262
|
-
elsif config['set'] != @replica_set
|
263
|
-
raise ReplicaSetConnectionError,
|
264
|
-
"Attempting to connect to replica set '#{config['set']}' but expected '#{@replica_set}'"
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
# Determines what kind of node we have and caches its host
|
270
|
-
# and port so that users can easily connect manually.
|
271
|
-
def set_auxillary(node, config)
|
272
|
-
if config
|
273
|
-
if config['secondary']
|
274
|
-
host, port = *node
|
275
|
-
@secondaries << node unless @secondaries.include?(node)
|
276
|
-
@secondary_pools << Pool.new(self, host, port, :size => @pool_size, :timeout => @timeout)
|
277
|
-
elsif config['arbiterOnly']
|
278
|
-
@arbiters << node unless @arbiters.include?(node)
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
# Update the list of known nodes. Only applies to replica sets,
|
284
|
-
# where the response to the ismaster command will return a list
|
285
|
-
# of known hosts.
|
286
|
-
#
|
287
|
-
# @param hosts [Array] a list of hosts, specified as string-encoded
|
288
|
-
# host-port values. Example: ["myserver-1.org:27017", "myserver-1.org:27017"]
|
289
|
-
#
|
290
|
-
# @return [Array] the updated list of nodes
|
291
|
-
def update_node_list(hosts)
|
292
|
-
new_nodes = hosts.map do |host|
|
293
|
-
if !host.respond_to?(:split)
|
294
|
-
warn "Could not parse host #{host.inspect}."
|
295
|
-
next
|
296
|
-
end
|
297
|
-
|
298
|
-
host, port = host.split(':')
|
299
|
-
[host, port ? port.to_i : Connection::DEFAULT_PORT]
|
300
|
-
end
|
301
|
-
|
302
|
-
# Replace the list of seed nodes with the canonical list.
|
303
|
-
@nodes = new_nodes.clone
|
304
|
-
|
305
|
-
@nodes_to_try = new_nodes - @nodes_tried
|
306
|
-
end
|
307
|
-
|
308
|
-
# Checkout a socket for reading (i.e., a secondary node).
|
309
|
-
def checkout_reader
|
310
|
-
connect unless connected?
|
311
|
-
|
312
|
-
if @read_pool
|
313
|
-
@read_pool.checkout
|
314
|
-
else
|
315
|
-
checkout_writer
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
# Checkout a socket for writing (i.e., a primary node).
|
320
|
-
def checkout_writer
|
321
|
-
connect unless connected?
|
322
|
-
|
323
|
-
@primary_pool.checkout
|
324
|
-
end
|
325
|
-
|
326
|
-
# Checkin a socket used for reading.
|
327
|
-
def checkin_reader(socket)
|
328
|
-
if @read_pool
|
329
|
-
@read_pool.checkin(socket)
|
330
|
-
else
|
331
|
-
checkin_writer(socket)
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
# Checkin a socket used for writing.
|
336
|
-
def checkin_writer(socket)
|
337
|
-
if @primary_pool
|
338
|
-
@primary_pool.checkin(socket)
|
339
|
-
end
|
340
|
-
end
|
341
|
-
end
|
342
|
-
end
|
data/lib/mongo/test.rb
DELETED
data/lib/mongo/util/pool.rb
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# --
|
4
|
-
# Copyright (C) 2008-2011 10gen Inc.
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
|
18
|
-
module Mongo
|
19
|
-
class Pool
|
20
|
-
|
21
|
-
attr_accessor :host, :port, :size, :timeout, :safe, :checked_out
|
22
|
-
|
23
|
-
# Create a new pool of connections.
|
24
|
-
#
|
25
|
-
def initialize(connection, host, port, opts={})
|
26
|
-
@connection = connection
|
27
|
-
|
28
|
-
@host, @port = host, port
|
29
|
-
|
30
|
-
# Pool size and timeout.
|
31
|
-
@size = opts[:size] || 1
|
32
|
-
@timeout = opts[:timeout] || 5.0
|
33
|
-
|
34
|
-
# Mutex for synchronizing pool access
|
35
|
-
@connection_mutex = Mutex.new
|
36
|
-
|
37
|
-
# Condition variable for signal and wait
|
38
|
-
@queue = ConditionVariable.new
|
39
|
-
|
40
|
-
# Operations to perform on a socket
|
41
|
-
@socket_ops = Hash.new { |h, k| h[k] = [] }
|
42
|
-
|
43
|
-
@sockets = []
|
44
|
-
@pids = {}
|
45
|
-
@checked_out = []
|
46
|
-
end
|
47
|
-
|
48
|
-
def close
|
49
|
-
@sockets.each do |sock|
|
50
|
-
begin
|
51
|
-
sock.close
|
52
|
-
rescue IOError => ex
|
53
|
-
warn "IOError when attempting to close socket connected to #{@host}:#{@port}: #{ex.inspect}"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
@host = @port = nil
|
57
|
-
@sockets.clear
|
58
|
-
@pids.clear
|
59
|
-
@checked_out.clear
|
60
|
-
end
|
61
|
-
|
62
|
-
# Return a socket to the pool.
|
63
|
-
def checkin(socket)
|
64
|
-
@connection_mutex.synchronize do
|
65
|
-
@checked_out.delete(socket)
|
66
|
-
@queue.signal
|
67
|
-
end
|
68
|
-
true
|
69
|
-
end
|
70
|
-
|
71
|
-
# Adds a new socket to the pool and checks it out.
|
72
|
-
#
|
73
|
-
# This method is called exclusively from #checkout;
|
74
|
-
# therefore, it runs within a mutex.
|
75
|
-
def checkout_new_socket
|
76
|
-
begin
|
77
|
-
socket = TCPSocket.new(@host, @port)
|
78
|
-
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
79
|
-
rescue => ex
|
80
|
-
raise ConnectionFailure, "Failed to connect to host #{@host} and port #{@port}: #{ex}"
|
81
|
-
end
|
82
|
-
|
83
|
-
# If any saved authentications exist, we want to apply those
|
84
|
-
# when creating new sockets.
|
85
|
-
@connection.apply_saved_authentication(:socket => socket)
|
86
|
-
|
87
|
-
@sockets << socket
|
88
|
-
@pids[socket] = Process.pid
|
89
|
-
@checked_out << socket
|
90
|
-
socket
|
91
|
-
end
|
92
|
-
|
93
|
-
# If a user calls DB#authenticate, and several sockets exist,
|
94
|
-
# then we need a way to apply the authentication on each socket.
|
95
|
-
# So we store the apply_authentication method, and this will be
|
96
|
-
# applied right before the next use of each socket.
|
97
|
-
def authenticate_existing
|
98
|
-
@connection_mutex.synchronize do
|
99
|
-
@sockets.each do |socket|
|
100
|
-
@socket_ops[socket] << Proc.new do
|
101
|
-
@connection.apply_saved_authentication(:socket => socket)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# Store the logout op for each existing socket to be applied before
|
108
|
-
# the next use of each socket.
|
109
|
-
def logout_existing(db)
|
110
|
-
@connection_mutex.synchronize do
|
111
|
-
@sockets.each do |socket|
|
112
|
-
@socket_ops[socket] << Proc.new do
|
113
|
-
@connection.db(db).issue_logout(:socket => socket)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Checks out the first available socket from the pool.
|
120
|
-
#
|
121
|
-
# If the pid has changed, remove the socket and check out
|
122
|
-
# new one.
|
123
|
-
#
|
124
|
-
# This method is called exclusively from #checkout;
|
125
|
-
# therefore, it runs within a mutex.
|
126
|
-
def checkout_existing_socket
|
127
|
-
socket = (@sockets - @checked_out).first
|
128
|
-
if @pids[socket] != Process.pid
|
129
|
-
@pids[socket] = nil
|
130
|
-
@sockets.delete(socket)
|
131
|
-
socket.close
|
132
|
-
checkout_new_socket
|
133
|
-
else
|
134
|
-
@checked_out << socket
|
135
|
-
socket
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# Check out an existing socket or create a new socket if the maximum
|
140
|
-
# pool size has not been exceeded. Otherwise, wait for the next
|
141
|
-
# available socket.
|
142
|
-
def checkout
|
143
|
-
@connection.connect if !@connection.connected?
|
144
|
-
start_time = Time.now
|
145
|
-
loop do
|
146
|
-
if (Time.now - start_time) > @timeout
|
147
|
-
raise ConnectionTimeoutError, "could not obtain connection within " +
|
148
|
-
"#{@timeout} seconds. The max pool size is currently #{@size}; " +
|
149
|
-
"consider increasing the pool size or timeout."
|
150
|
-
end
|
151
|
-
|
152
|
-
@connection_mutex.synchronize do
|
153
|
-
socket = if @checked_out.size < @sockets.size
|
154
|
-
checkout_existing_socket
|
155
|
-
elsif @sockets.size < @size
|
156
|
-
checkout_new_socket
|
157
|
-
end
|
158
|
-
|
159
|
-
if socket
|
160
|
-
|
161
|
-
# This calls all procs, in order, scoped to existing sockets.
|
162
|
-
# At the moment, we use this to lazily authenticate and
|
163
|
-
# logout existing socket connections.
|
164
|
-
@socket_ops[socket].reject! do |op|
|
165
|
-
op.call
|
166
|
-
end
|
167
|
-
|
168
|
-
return socket
|
169
|
-
else
|
170
|
-
# Otherwise, wait
|
171
|
-
@queue.wait(@connection_mutex)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|