Skip to content

Commit f77b922

Browse files
committed
RUBY-736 Clone sets and lists of pools before returning in PoolManager
1 parent 84811ab commit f77b922

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

lib/mongo/connection/pool_manager.rb

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,9 @@ class PoolManager
1717
include ThreadLocalVariableManager
1818

1919
attr_reader :client,
20-
:arbiters,
2120
:primary,
22-
:secondaries,
2321
:primary_pool,
24-
:secondary_pools,
25-
:hosts,
2622
:seeds,
27-
:pools,
2823
:max_bson_size,
2924
:max_message_size,
3025
:max_wire_version,
@@ -145,6 +140,47 @@ def read
145140
read_pool.host_port
146141
end
147142

143+
def hosts
144+
@connect_mutex.synchronize do
145+
@hosts.nil? ? nil : @hosts.clone
146+
end
147+
end
148+
149+
def pools
150+
@connect_mutex.synchronize do
151+
@pools.nil? ? nil : @pools.clone
152+
end
153+
end
154+
155+
def secondaries
156+
@connect_mutex.synchronize do
157+
@secondaries.nil? ? nil : @secondaries.clone
158+
end
159+
end
160+
161+
def secondary_pools
162+
@connect_mutex.synchronize do
163+
@secondary_pools.nil? ? nil : @secondary_pools.clone
164+
end
165+
end
166+
167+
def arbiters
168+
@connect_mutex.synchronize do
169+
@arbiters.nil? ? nil : @arbiters.clone
170+
end
171+
end
172+
173+
def state_snapshot
174+
@connect_mutex.synchronize do
175+
{ :pools => @pools.nil? ? nil : @pools.clone,
176+
:secondaries => @secondaries.nil? ? nil : @secondaries.clone,
177+
:secondary_pools => @secondary_pools.nil? ? nil : @secondary_pools.clone,
178+
:hosts => @hosts.nil? ? nil : @hosts.clone,
179+
:arbiters => @arbiters.nil? ? nil : @arbiters.clone
180+
}
181+
end
182+
end
183+
148184
private
149185

150186
def update_max_sizes

test/unit/pool_manager_test.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,37 @@ class PoolManagerUnitTest < Test::Unit::TestCase
106106
assert_equal [['localhost', 27020]], manager.arbiters
107107
end
108108

109+
should "return clones of pool lists" do
110+
111+
@db.stubs(:command).returns(
112+
# First call to get a socket.
113+
@ismaster.merge({'ismaster' => true}),
114+
115+
# Subsequent calls to configure pools.
116+
@ismaster.merge({'ismaster' => true}),
117+
@ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 500}),
118+
@ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 700}),
119+
@ismaster.merge({'arbiterOnly' => true})
120+
)
121+
122+
seeds = [['localhost', 27017], ['localhost', 27018]]
123+
manager = Mongo::PoolManager.new(@client, seeds)
124+
@client.stubs(:local_manager).returns(manager)
125+
manager.connect
126+
127+
assert_not_equal manager.instance_variable_get(:@arbiters).object_id, manager.arbiters.object_id
128+
assert_not_equal manager.instance_variable_get(:@secondaries).object_id, manager.secondaries.object_id
129+
assert_not_equal manager.instance_variable_get(:@secondary_pools).object_id, manager.secondary_pools.object_id
130+
assert_not_equal manager.instance_variable_get(:@hosts).object_id, manager.hosts.object_id
131+
assert_not_equal manager.instance_variable_get(:@pools).object_id, manager.pools.object_id
132+
133+
assert_not_equal manager.instance_variable_get(:@arbiters).object_id, manager.state_snapshot[:arbiters].object_id
134+
assert_not_equal manager.instance_variable_get(:@secondaries).object_id, manager.state_snapshot[:secondaries].object_id
135+
assert_not_equal manager.instance_variable_get(:@secondary_pools).object_id, manager.state_snapshot[:secondary_pools].object_id
136+
assert_not_equal manager.instance_variable_get(:@hosts).object_id, manager.state_snapshot[:hosts].object_id
137+
assert_not_equal manager.instance_variable_get(:@pools).object_id, manager.state_snapshot[:pools].object_id
138+
end
139+
109140
end
110141

111142
end

0 commit comments

Comments
 (0)