Skip to content

Commit a6e34e1

Browse files
committed
test: allow to count select requests on storages
I don't want to lean on box.stat() information here, because I don't control all iproto calls to storages: say, vshard rebalancer may perform them in background. Instead, I wrapped particular storage function I'm interested in. The goal is to be able to determine how much storages are involved into a select/pairs request. It is implemented as a helper for testing, but hopefully we'll implement some nice statistics as part of the module in a future (see #224). Part of #220
1 parent d13fe63 commit a6e34e1

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

test/helper.lua

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,76 @@ function helpers.call_on_servers(cluster, aliases, func)
179179
end
180180
end
181181

182+
-- Call given function for each server with the 'crud-storage'
183+
-- role.
184+
--
185+
-- 'func' accepts a server object, a replicaset config and all
186+
-- arguments passed after 'func'.
187+
--
188+
-- Usage example:
189+
--
190+
-- | local res = {}
191+
-- | helpers.call_on_storages(g.cluster, function(server, replicaset, res)
192+
-- | local instance_res = server.net_box:call(<...>)
193+
-- | res[replicaset.alias] = res[replicaset.alias] + instance_res
194+
-- | end)
195+
-- | t.assert_equals(res, {['s-1'] = 5, ['s-2'] = 6})
196+
function helpers.call_on_storages(cluster, func, ...)
197+
-- Accumulate storages into a map from the storage alias to
198+
-- the replicaset object. Only storages, skip other instances.
199+
--
200+
-- Example:
201+
--
202+
-- | {
203+
-- | ['s1-master'] = {
204+
-- | alias = 's-1',
205+
-- | roles = <...>,
206+
-- | servers = {
207+
-- | {
208+
-- | alias = 's1-master',
209+
-- | env = <...>,
210+
-- | instance_uuid = <...>,
211+
-- | },
212+
-- | <...>
213+
-- | },
214+
-- | uuid = <...>,
215+
-- | }
216+
-- | ['s1-replica'] = <...>,
217+
-- | ['s2-master'] = <...>,
218+
-- | ['s2-replica'] = <...>,
219+
-- | }
220+
--
221+
-- NB: The 'servers' field contains server configs. They are
222+
-- not the same as server objects: say, there is no 'net_box'
223+
-- field here.
224+
local alias_map = {}
225+
for _, replicaset in ipairs(cluster.replicasets) do
226+
-- Whether it is a storage replicaset?
227+
local has_crud_storage_role = false
228+
for _, role in ipairs(replicaset.roles) do
229+
if role == 'crud-storage' then
230+
has_crud_storage_role = true
231+
break
232+
end
233+
end
234+
235+
-- If so, add servers of the replicaset into the mapping.
236+
if has_crud_storage_role then
237+
for _, server in ipairs(replicaset.servers) do
238+
alias_map[server.alias] = replicaset
239+
end
240+
end
241+
end
242+
243+
-- Call given function for each storage node.
244+
for _, server in ipairs(cluster.servers) do
245+
local replicaset_alias = alias_map[server.alias]
246+
if replicaset_alias ~= nil then
247+
func(server, replicaset_alias, ...)
248+
end
249+
end
250+
end
251+
182252
function helpers.assert_ge(actual, expected, message)
183253
if not (actual >= expected) then
184254
local err = string.format('expected: %s >= %s', actual, expected)

test/helpers/storage_stat.lua

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
local checks = require('checks')
2+
local helpers = require('test.helper')
3+
4+
local storage_stat = {}
5+
6+
-- Wrap crud's select_on_storage() function to count selects
7+
-- and add storage_stat() function that returns resulting
8+
-- statistics.
9+
--
10+
-- Call it after crud's initialization.
11+
function storage_stat.init_on_storage()
12+
assert(_G._crud.select_on_storage ~= nil)
13+
14+
-- Here we count requests.
15+
local storage_stat_table = {
16+
select_requests = 0,
17+
}
18+
19+
-- Wrap select_on_storage() function.
20+
local select_on_storage_saved = _G._crud.select_on_storage
21+
_G._crud.select_on_storage = function(...)
22+
local requests = storage_stat_table.select_requests
23+
storage_stat_table.select_requests = requests + 1
24+
return select_on_storage_saved(...)
25+
end
26+
27+
-- Accessor for the statistics.
28+
rawset(_G, 'storage_stat', function()
29+
return storage_stat_table
30+
end)
31+
end
32+
33+
-- Accumulate statistics from storages.
34+
--
35+
-- The statistics is grouped by replicasets.
36+
--
37+
-- Example of a return value:
38+
--
39+
-- | {
40+
-- | ['s-1'] = {
41+
-- | select_requests = 1,
42+
-- | },
43+
-- | ['s-2'] = {
44+
-- | select_requests = 0,
45+
-- | },
46+
-- | }
47+
function storage_stat.collect(cluster)
48+
checks('table')
49+
50+
local res = {}
51+
52+
helpers.call_on_storages(cluster, function(server, replicaset)
53+
checks('table', 'table')
54+
55+
-- Collect the statistics.
56+
local storage_stat = server.net_box:call('storage_stat')
57+
58+
-- Initialize if needed.
59+
if res[replicaset.alias] == nil then
60+
res[replicaset.alias] = {}
61+
end
62+
63+
-- Accumulate the collected statistics.
64+
for key, val in pairs(storage_stat) do
65+
local old = res[replicaset.alias][key] or 0
66+
res[replicaset.alias][key] = old + val
67+
end
68+
end)
69+
70+
return res
71+
end
72+
73+
-- Difference between 'a' and 'b' storage statistics.
74+
--
75+
-- The return value structure is the same as for
76+
-- storage_stat.collect().
77+
function storage_stat.diff(a, b)
78+
checks('table', 'table')
79+
80+
local diff = table.deepcopy(a)
81+
82+
for replicaset_alias, stat_b in pairs(b) do
83+
-- Initialize if needed.
84+
if diff[replicaset_alias] == nil then
85+
diff[replicaset_alias] = {}
86+
end
87+
88+
-- Substract 'b' statistics from 'a'.
89+
for key, val in pairs(stat_b) do
90+
local old = diff[replicaset_alias][key] or 0
91+
diff[replicaset_alias][key] = old - val
92+
end
93+
end
94+
95+
return diff
96+
end
97+
98+
return storage_stat

0 commit comments

Comments
 (0)