mongo 1.6.4 → 1.7.0.rc0
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.
- data/README.md +13 -13
- data/Rakefile +7 -10
- data/docs/{GridFS.md → GRID_FS.md} +0 -0
- data/docs/HISTORY.md +16 -0
- data/docs/READ_PREFERENCE.md +70 -10
- data/docs/TUTORIAL.md +2 -2
- data/lib/mongo.rb +2 -0
- data/lib/mongo/collection.rb +62 -11
- data/lib/mongo/connection.rb +31 -41
- data/lib/mongo/cursor.rb +42 -86
- data/lib/mongo/db.rb +10 -8
- data/lib/mongo/networking.rb +30 -65
- data/lib/mongo/repl_set_connection.rb +91 -170
- data/lib/mongo/sharded_connection.rb +221 -0
- data/lib/mongo/util/node.rb +29 -36
- data/lib/mongo/util/pool.rb +10 -3
- data/lib/mongo/util/pool_manager.rb +77 -90
- data/lib/mongo/util/sharding_pool_manager.rb +143 -0
- data/lib/mongo/util/support.rb +22 -2
- data/lib/mongo/util/tcp_socket.rb +10 -15
- data/lib/mongo/util/uri_parser.rb +17 -10
- data/lib/mongo/version.rb +1 -1
- data/test/collection_test.rb +133 -1
- data/test/connection_test.rb +50 -4
- data/test/db_api_test.rb +3 -3
- data/test/db_test.rb +6 -1
- data/test/replica_sets/basic_test.rb +3 -6
- data/test/replica_sets/complex_connect_test.rb +14 -2
- data/test/replica_sets/complex_read_preference_test.rb +237 -0
- data/test/replica_sets/connect_test.rb +47 -67
- data/test/replica_sets/count_test.rb +1 -1
- data/test/replica_sets/cursor_test.rb +70 -0
- data/test/replica_sets/read_preference_test.rb +171 -118
- data/test/replica_sets/refresh_test.rb +3 -3
- data/test/replica_sets/refresh_with_threads_test.rb +2 -2
- data/test/replica_sets/rs_test_helper.rb +2 -2
- data/test/sharded_cluster/basic_test.rb +112 -0
- data/test/sharded_cluster/mongo_config_test.rb +126 -0
- data/test/sharded_cluster/sc_test_helper.rb +39 -0
- data/test/test_helper.rb +3 -3
- data/test/threading/threading_with_large_pool_test.rb +1 -1
- data/test/tools/mongo_config.rb +307 -0
- data/test/tools/repl_set_manager.rb +12 -12
- data/test/unit/collection_test.rb +1 -1
- data/test/unit/cursor_test.rb +11 -6
- data/test/unit/db_test.rb +4 -0
- data/test/unit/grid_test.rb +2 -0
- data/test/unit/read_test.rb +39 -8
- data/test/uri_test.rb +4 -8
- metadata +144 -127
@@ -5,7 +5,7 @@ class ReplicaSetCountTest < Test::Unit::TestCase
|
|
5
5
|
|
6
6
|
def setup
|
7
7
|
ensure_rs
|
8
|
-
@conn = ReplSetConnection.new(build_seeds(3), :read => :
|
8
|
+
@conn = ReplSetConnection.new(build_seeds(3), :read => :primary_preferred)
|
9
9
|
assert @conn.primary_pool
|
10
10
|
@primary = Connection.new(@conn.primary_pool.host, @conn.primary_pool.port)
|
11
11
|
@db = @conn.db(MONGO_TEST_DB)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require './test/replica_sets/rs_test_helper'
|
3
|
+
|
4
|
+
class ReplicaSetCursorTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
ensure_rs
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_cursors_get_closed
|
10
|
+
setup_connection
|
11
|
+
assert_cursor_count
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_cursors_get_closed_secondary
|
15
|
+
setup_connection(:secondary)
|
16
|
+
assert_cursor_count
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def setup_connection(read=:primary)
|
22
|
+
# Setup ReplicaSet Connection
|
23
|
+
@replconn = Mongo::ReplSetConnection.new(
|
24
|
+
build_seeds(3),
|
25
|
+
:read => read
|
26
|
+
)
|
27
|
+
|
28
|
+
@db = @replconn.db(MONGO_TEST_DB)
|
29
|
+
@db.drop_collection("cursor_tests")
|
30
|
+
@coll = @db.collection("cursor_tests")
|
31
|
+
|
32
|
+
@coll.insert({:a => 1}, :safe => true, :w => 3)
|
33
|
+
@coll.insert({:b => 2}, :safe => true, :w => 3)
|
34
|
+
@coll.insert({:c => 3}, :safe => true, :w => 3)
|
35
|
+
|
36
|
+
# Pin reader
|
37
|
+
@coll.find_one
|
38
|
+
|
39
|
+
# Setup Direct Connections
|
40
|
+
@primary = Mongo::Connection.new(*@replconn.manager.primary)
|
41
|
+
@read = Mongo::Connection.new(*@replconn.manager.read)
|
42
|
+
end
|
43
|
+
|
44
|
+
def cursor_count(connection)
|
45
|
+
connection['cursor_tests'].command({:cursorInfo => 1})['totalOpen']
|
46
|
+
end
|
47
|
+
|
48
|
+
def query_count(connection)
|
49
|
+
connection['admin'].command({:serverStatus => 1})['opcounters']['query']
|
50
|
+
end
|
51
|
+
|
52
|
+
def assert_cursor_count
|
53
|
+
before_primary = cursor_count(@primary)
|
54
|
+
before_read = cursor_count(@read)
|
55
|
+
before_query = query_count(@read)
|
56
|
+
|
57
|
+
@coll.find.limit(2).to_a
|
58
|
+
sleep(1)
|
59
|
+
|
60
|
+
after_primary = cursor_count(@primary)
|
61
|
+
after_read = cursor_count(@read)
|
62
|
+
after_query = query_count(@read)
|
63
|
+
|
64
|
+
assert_equal before_primary, after_primary
|
65
|
+
assert_equal before_read, after_read
|
66
|
+
assert_equal 1, after_query - before_query
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
@@ -5,80 +5,169 @@ require 'logger'
|
|
5
5
|
class ReadPreferenceTest < Test::Unit::TestCase
|
6
6
|
|
7
7
|
def setup
|
8
|
-
ensure_rs
|
9
|
-
log = Logger.new("test.log")
|
10
|
-
seeds = build_seeds(2)
|
11
|
-
args = {
|
12
|
-
:read => :secondary,
|
13
|
-
:pool_size => 50,
|
14
|
-
:refresh_mode => false,
|
15
|
-
:refresh_interval => 5,
|
16
|
-
:logger => log
|
17
|
-
}
|
18
|
-
@conn = ReplSetConnection.new(seeds, args)
|
19
|
-
@db = @conn.db(MONGO_TEST_DB)
|
20
|
-
@db.drop_collection("test-sets")
|
21
|
-
end
|
8
|
+
ensure_rs(:secondary_count => 1, :arbiter_count => 1)
|
22
9
|
|
23
|
-
|
24
|
-
@rs.
|
10
|
+
# Insert data
|
11
|
+
conn = Connection.new(@rs.host, @rs.primary[1])
|
12
|
+
db = conn.db(MONGO_TEST_DB)
|
13
|
+
coll = db.collection("test-sets")
|
14
|
+
coll.save({:a => 20}, :safe => {:w => 2})
|
25
15
|
end
|
26
16
|
|
27
17
|
def test_read_primary
|
18
|
+
conn = make_connection
|
19
|
+
rescue_connection_failure do
|
20
|
+
assert conn.read_primary?
|
21
|
+
assert conn.primary?
|
22
|
+
end
|
23
|
+
|
24
|
+
conn = make_connection(:primary_preferred)
|
28
25
|
rescue_connection_failure do
|
29
|
-
assert
|
30
|
-
assert
|
26
|
+
assert conn.read_primary?
|
27
|
+
assert conn.primary?
|
28
|
+
end
|
29
|
+
|
30
|
+
conn = make_connection(:secondary)
|
31
|
+
rescue_connection_failure do
|
32
|
+
assert !conn.read_primary?
|
33
|
+
assert !conn.primary?
|
34
|
+
end
|
35
|
+
|
36
|
+
conn = make_connection(:secondary_preferred)
|
37
|
+
rescue_connection_failure do
|
38
|
+
assert !conn.read_primary?
|
39
|
+
assert !conn.primary?
|
31
40
|
end
|
32
41
|
end
|
33
42
|
|
34
|
-
def
|
35
|
-
|
36
|
-
assert
|
37
|
-
assert
|
38
|
-
|
43
|
+
def test_connection_pools
|
44
|
+
conn = make_connection
|
45
|
+
assert conn.primary_pool, "No primary pool!"
|
46
|
+
assert conn.read_pool, "No read pool!"
|
47
|
+
assert conn.primary_pool.port == conn.read_pool.port,
|
48
|
+
"Primary port and read port are not the same!"
|
49
|
+
|
50
|
+
conn = make_connection(:primary_preferred)
|
51
|
+
assert conn.primary_pool, "No primary pool!"
|
52
|
+
assert conn.read_pool, "No read pool!"
|
53
|
+
assert conn.primary_pool.port == conn.read_pool.port,
|
54
|
+
"Primary port and read port are not the same!"
|
55
|
+
|
56
|
+
conn = make_connection(:secondary)
|
57
|
+
assert conn.primary_pool, "No primary pool!"
|
58
|
+
assert conn.read_pool, "No read pool!"
|
59
|
+
assert conn.primary_pool.port != conn.read_pool.port,
|
60
|
+
"Primary port and read port are the same!"
|
61
|
+
|
62
|
+
conn = make_connection(:secondary_preferred)
|
63
|
+
assert conn.primary_pool, "No primary pool!"
|
64
|
+
assert conn.read_pool, "No read pool!"
|
65
|
+
assert conn.primary_pool.port != conn.read_pool.port,
|
66
|
+
"Primary port and read port are the same!"
|
39
67
|
end
|
40
68
|
|
41
|
-
def
|
42
|
-
|
43
|
-
@rs.remove_secondary_node
|
44
|
-
|
45
|
-
@conn = ReplSetConnection.new(build_seeds(3), :read => :secondary_only)
|
69
|
+
def test_read_routing
|
70
|
+
prepare_routing_test
|
46
71
|
|
47
|
-
|
48
|
-
@
|
49
|
-
|
50
|
-
@
|
72
|
+
# Test that reads are going to the right members
|
73
|
+
assert_query_route(@primary, @primary_direct)
|
74
|
+
assert_query_route(@primary_preferred, @primary_direct)
|
75
|
+
assert_query_route(@secondary, @secondary_direct)
|
76
|
+
assert_query_route(@secondary_preferred, @secondary_direct)
|
77
|
+
end
|
51
78
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
79
|
+
def test_read_routing_with_primary_down
|
80
|
+
prepare_routing_test
|
81
|
+
|
82
|
+
# Test that reads are going to the right members
|
83
|
+
assert_query_route(@primary, @primary_direct)
|
84
|
+
assert_query_route(@primary_preferred, @primary_direct)
|
85
|
+
assert_query_route(@secondary, @secondary_direct)
|
86
|
+
assert_query_route(@secondary_preferred, @secondary_direct)
|
87
|
+
|
88
|
+
# Kill the primary so only a single secondary exists
|
89
|
+
@rs.kill_primary
|
58
90
|
|
91
|
+
# Test that reads are going to the right members
|
92
|
+
assert_raise_error ConnectionFailure do
|
93
|
+
@primary[MONGO_TEST_DB]['test-sets'].find_one
|
94
|
+
end
|
95
|
+
assert_query_route(@primary_preferred, @secondary_direct)
|
96
|
+
assert_query_route(@secondary, @secondary_direct)
|
97
|
+
assert_query_route(@secondary_preferred, @secondary_direct)
|
98
|
+
|
99
|
+
# Restore set
|
100
|
+
@rs.restart_killed_nodes
|
101
|
+
sleep(1)
|
102
|
+
@repl_cons.each { |con| con.refresh }
|
103
|
+
sleep(1)
|
104
|
+
@primary_direct = Connection.new(
|
105
|
+
@rs.host,
|
106
|
+
@primary.read_pool.port
|
107
|
+
)
|
108
|
+
|
109
|
+
# Test that reads are going to the right members
|
110
|
+
assert_query_route(@primary, @primary_direct)
|
111
|
+
assert_query_route(@primary_preferred, @primary_direct)
|
112
|
+
assert_query_route(@secondary, @secondary_direct)
|
113
|
+
assert_query_route(@secondary_preferred, @secondary_direct)
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_read_routing_with_secondary_down
|
117
|
+
prepare_routing_test
|
118
|
+
|
119
|
+
# Test that reads are going to the right members
|
120
|
+
assert_query_route(@primary, @primary_direct)
|
121
|
+
assert_query_route(@primary_preferred, @primary_direct)
|
122
|
+
assert_query_route(@secondary, @secondary_direct)
|
123
|
+
assert_query_route(@secondary_preferred, @secondary_direct)
|
124
|
+
|
125
|
+
# Kill the secondary so that only primary exists
|
59
126
|
@rs.kill_secondary
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
127
|
+
|
128
|
+
# Test that reads are going to the right members
|
129
|
+
assert_query_route(@primary, @primary_direct)
|
130
|
+
assert_query_route(@primary_preferred, @primary_direct)
|
131
|
+
assert_raise_error ConnectionFailure do
|
132
|
+
@secondary[MONGO_TEST_DB]['test-sets'].find_one
|
65
133
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
134
|
+
assert_query_route(@secondary_preferred, @primary_direct)
|
135
|
+
|
136
|
+
# Restore set
|
137
|
+
@rs.restart_killed_nodes
|
138
|
+
sleep(1)
|
139
|
+
@repl_cons.each { |con| con.refresh }
|
140
|
+
sleep(1)
|
141
|
+
@secondary_direct = Connection.new(
|
142
|
+
@rs.host,
|
143
|
+
@secondary.read_pool.port,
|
144
|
+
:slave_ok => true
|
145
|
+
)
|
146
|
+
|
147
|
+
# Test that reads are going to the right members
|
148
|
+
assert_query_route(@primary, @primary_direct)
|
149
|
+
assert_query_route(@primary_preferred, @primary_direct)
|
150
|
+
assert_query_route(@secondary, @secondary_direct)
|
151
|
+
assert_query_route(@secondary_preferred, @secondary_direct)
|
69
152
|
end
|
70
153
|
|
71
|
-
def
|
72
|
-
@
|
73
|
-
@
|
154
|
+
def test_write_conecern
|
155
|
+
@conn = make_connection(:secondary_preferred)
|
156
|
+
@db = @conn[MONGO_TEST_DB]
|
157
|
+
@coll = @db.collection("test-sets", :safe => {
|
158
|
+
:w => 2, :wtimeout => 20000
|
159
|
+
})
|
74
160
|
@coll.save({:a => 20})
|
75
161
|
@coll.save({:a => 30})
|
76
162
|
@coll.save({:a => 40})
|
163
|
+
|
164
|
+
# pin the read pool
|
165
|
+
@coll.find_one
|
166
|
+
@secondary = Connection.new(@rs.host, @conn.read_pool.port, :slave_ok => true)
|
167
|
+
|
77
168
|
results = []
|
78
|
-
queries_before = @secondary['admin'].command({:serverStatus => 1})['opcounters']['query']
|
79
169
|
@coll.find.each {|r| results << r["a"]}
|
80
|
-
|
81
|
-
assert_equal 1, queries_after - queries_before
|
170
|
+
|
82
171
|
assert results.include?(20)
|
83
172
|
assert results.include?(30)
|
84
173
|
assert results.include?(40)
|
@@ -87,57 +176,17 @@ class ReadPreferenceTest < Test::Unit::TestCase
|
|
87
176
|
|
88
177
|
results = []
|
89
178
|
rescue_connection_failure do
|
90
|
-
#puts "@coll.find().each"
|
91
179
|
@coll.find.each {|r| results << r}
|
92
180
|
[20, 30, 40].each do |a|
|
93
181
|
assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
|
94
182
|
end
|
95
183
|
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_kill_primary
|
99
|
-
@coll = @db.collection("test-sets", :safe => {:w => 3, :wtimeout => 10000})
|
100
|
-
@coll.save({:a => 20})
|
101
|
-
@coll.save({:a => 30})
|
102
|
-
assert_equal 2, @coll.find.to_a.length
|
103
|
-
|
104
|
-
# Should still be able to read immediately after killing master node
|
105
|
-
@rs.kill_primary
|
106
|
-
assert_equal 2, @coll.find.to_a.length
|
107
|
-
rescue_connection_failure do
|
108
|
-
@coll.save({:a => 50}, :safe => {:w => 2, :wtimeout => 10000})
|
109
|
-
end
|
110
184
|
@rs.restart_killed_nodes
|
111
|
-
sleep(1)
|
112
|
-
@coll.save({:a => 50}, :safe => {:w => 2, :wtimeout => 10000})
|
113
|
-
assert_equal 4, @coll.find.to_a.length
|
114
|
-
end
|
115
|
-
|
116
|
-
def test_kill_secondary
|
117
|
-
@coll = @db.collection("test-sets", {:safe => {:w => 3, :wtimeout => 20000}})
|
118
|
-
@coll.save({:a => 20})
|
119
|
-
@coll.save({:a => 30})
|
120
|
-
assert_equal 2, @coll.find.to_a.length
|
121
|
-
|
122
|
-
read_node = @rs.get_node_from_port(@conn.read_pool.port)
|
123
|
-
@rs.kill(read_node)
|
124
|
-
|
125
|
-
# Should fail immediately on next read
|
126
|
-
old_read_pool_port = @conn.read_pool.port
|
127
|
-
assert_raise ConnectionFailure do
|
128
|
-
@coll.find.to_a.length
|
129
|
-
end
|
130
|
-
|
131
|
-
# Should eventually reconnect and be able to read
|
132
|
-
rescue_connection_failure do
|
133
|
-
length = @coll.find.to_a.length
|
134
|
-
assert_equal 2, length
|
135
|
-
end
|
136
|
-
new_read_pool_port = @conn.read_pool.port
|
137
|
-
assert old_read_pool_port != new_read_pool_port
|
138
185
|
end
|
139
186
|
|
140
187
|
def test_write_lots_of_data
|
188
|
+
@conn = make_connection(:secondary_preferred)
|
189
|
+
@db = @conn[MONGO_TEST_DB]
|
141
190
|
@coll = @db.collection("test-sets", {:safe => {:w => 2}})
|
142
191
|
|
143
192
|
6000.times do |n|
|
@@ -149,33 +198,37 @@ class ReadPreferenceTest < Test::Unit::TestCase
|
|
149
198
|
cursor.close
|
150
199
|
end
|
151
200
|
|
152
|
-
|
153
|
-
# def test_query_tagged
|
154
|
-
# col = @db['mongo-test']
|
201
|
+
private
|
155
202
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
203
|
+
def prepare_routing_test
|
204
|
+
# Setup replica set connections
|
205
|
+
@primary = make_connection(:primary)
|
206
|
+
@primary_preferred = make_connection(:primary_preferred)
|
207
|
+
@secondary = make_connection(:secondary)
|
208
|
+
@secondary_preferred = make_connection(:secondary_preferred)
|
209
|
+
@repl_cons = [@primary, @primary_preferred, @secondary, @secondary_preferred]
|
160
210
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
# threads = []
|
166
|
-
# 100.times do
|
167
|
-
# threads << Thread.new do
|
168
|
-
# col.find_one({}, :read => {:dc => "sf"})
|
169
|
-
# end
|
170
|
-
# end
|
171
|
-
|
172
|
-
# threads.each {|t| t.join }
|
211
|
+
# Setup direct connections
|
212
|
+
@primary_direct = Connection.new(@rs.host, @primary.read_pool.port)
|
213
|
+
@secondary_direct = Connection.new(@rs.host, @secondary.read_pool.port, :slave_ok => true)
|
214
|
+
end
|
173
215
|
|
174
|
-
|
175
|
-
|
216
|
+
def make_connection(mode = :primary, opts = {})
|
217
|
+
opts.merge!({:read => mode})
|
218
|
+
ReplSetConnection.new(build_seeds(3), opts)
|
219
|
+
end
|
176
220
|
|
177
|
-
|
178
|
-
|
179
|
-
|
221
|
+
def query_count(connection)
|
222
|
+
connection['admin'].command({:serverStatus => 1})['opcounters']['query']
|
223
|
+
end
|
180
224
|
|
225
|
+
def assert_query_route(test_connection, expected_target)
|
226
|
+
#puts "#{test_connection.read_pool.port} #{expected_target.read_pool.port}"
|
227
|
+
queries_before = query_count(expected_target)
|
228
|
+
assert_nothing_raised do
|
229
|
+
test_connection['MONGO_TEST_DB']['test-sets'].find_one
|
230
|
+
end
|
231
|
+
queries_after = query_count(expected_target)
|
232
|
+
assert_equal 1, queries_after - queries_before
|
233
|
+
end
|
181
234
|
end
|
@@ -69,12 +69,12 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
|
|
69
69
|
|
70
70
|
rescue_connection_failure do
|
71
71
|
@conn = ReplSetConnection.new(build_seeds(3),
|
72
|
-
:refresh_interval => 2, :refresh_mode => :sync)
|
72
|
+
:refresh_interval => 2, :refresh_mode => :sync, :read => :secondary_preferred)
|
73
73
|
end
|
74
74
|
|
75
75
|
assert_equal [], @conn.secondaries
|
76
76
|
assert @conn.connected?
|
77
|
-
assert_equal @conn.
|
77
|
+
assert_equal @conn.manager.read, @conn.manager.primary
|
78
78
|
old_refresh_version = @conn.refresh_version
|
79
79
|
|
80
80
|
@rs.restart_killed_nodes
|
@@ -86,7 +86,7 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
|
|
86
86
|
"Refresh version hasn't changed."
|
87
87
|
assert @conn.secondaries.length > 0,
|
88
88
|
"No secondaries have been added."
|
89
|
-
assert @conn.
|
89
|
+
assert @conn.manager.read != @conn.manager.primary,
|
90
90
|
"Read pool and primary pool are identical."
|
91
91
|
end
|
92
92
|
|
@@ -15,13 +15,13 @@ class ReplicaSetRefreshWithThreadsTest < Test::Unit::TestCase
|
|
15
15
|
|
16
16
|
def test_read_write_load_with_added_nodes
|
17
17
|
# MongoDB < 2.0 will disconnect clients on rs.reconfig()
|
18
|
-
return true if @rs.version
|
18
|
+
return true if @rs.version < "2"
|
19
19
|
|
20
20
|
seeds = build_seeds(3)
|
21
21
|
args = {
|
22
22
|
:refresh_interval => 5,
|
23
23
|
:refresh_mode => :sync,
|
24
|
-
:read => :
|
24
|
+
:read => :secondary_preferred
|
25
25
|
}
|
26
26
|
@conn = ReplSetConnection.new(seeds, args)
|
27
27
|
@duplicate = @conn[MONGO_TEST_DB]['duplicate']
|