From edcd30fe184259259d85c722cb4e5e06e2fbf148 Mon Sep 17 00:00:00 2001 From: Alexandr Lyapunov <a.lyapunov@corp.mail.ru> Date: Tue, 9 Jun 2015 12:03:31 +0300 Subject: [PATCH] *) added cwd() function to fio package *) added stress test for snapshotting *) moved finalizers.test.py to long_run --- src/lua/fio.cc | 21 ++ test/{box => long_run}/finalizers.result | 0 test/{box => long_run}/finalizers.test.py | 2 +- test/{box => long_run}/lua/finalizers.lua | 0 test/wal_off/snapshot_stress.result | 362 ++++++++++++++++++++++ test/wal_off/snapshot_stress.test.lua | 222 +++++++++++++ 6 files changed, 606 insertions(+), 1 deletion(-) rename test/{box => long_run}/finalizers.result (100%) rename test/{box => long_run}/finalizers.test.py (87%) rename test/{box => long_run}/lua/finalizers.lua (100%) create mode 100644 test/wal_off/snapshot_stress.result create mode 100644 test/wal_off/snapshot_stress.test.lua diff --git a/src/lua/fio.cc b/src/lua/fio.cc index 5dfb85b130..736be7548c 100644 --- a/src/lua/fio.cc +++ b/src/lua/fio.cc @@ -622,6 +622,26 @@ lbox_fio_tempdir(struct lua_State *L) return 1; } +static int +lbox_fio_cwd(struct lua_State *L) +{ + char *buf = (char *)lua_newuserdata(L, PATH_MAX); + if (!buf) { + errno = ENOMEM; + lua_pushnil(L); + return 1; + } + + + if (getcwd(buf, PATH_MAX)) { + lua_pushstring(L, buf); + lua_remove(L, -2); + } else { + lua_pushnil(L); + } + return 1; +} + static int lbox_fio_fsync(struct lua_State *L) { @@ -674,6 +694,7 @@ tarantool_lua_fio_init(struct lua_State *L) { "chmod", lbox_fio_chmod }, { "truncate", lbox_fio_truncate }, { "tempdir", lbox_fio_tempdir }, + { "cwd", lbox_fio_cwd }, { "sync", lbox_fio_sync }, { NULL, NULL } }; diff --git a/test/box/finalizers.result b/test/long_run/finalizers.result similarity index 100% rename from test/box/finalizers.result rename to test/long_run/finalizers.result diff --git a/test/box/finalizers.test.py b/test/long_run/finalizers.test.py similarity index 87% rename from test/box/finalizers.test.py rename to test/long_run/finalizers.test.py index ca20abac92..c471892f17 100644 --- a/test/box/finalizers.test.py +++ b/test/long_run/finalizers.test.py @@ -5,7 +5,7 @@ import yaml from lib.tarantool_server import TarantoolServer server = TarantoolServer(server.ini) -server.script = 'box/lua/finalizers.lua' +server.script = 'long_run/lua/finalizers.lua' server.vardir = os.path.join(server.vardir, 'finalizers') try: server.deploy() diff --git a/test/box/lua/finalizers.lua b/test/long_run/lua/finalizers.lua similarity index 100% rename from test/box/lua/finalizers.lua rename to test/long_run/lua/finalizers.lua diff --git a/test/wal_off/snapshot_stress.result b/test/wal_off/snapshot_stress.result new file mode 100644 index 0000000000..0646564ea9 --- /dev/null +++ b/test/wal_off/snapshot_stress.result @@ -0,0 +1,362 @@ +-- The test emulates account system. There are increasing number or accounts +-- and a lot of double entry transactions are made that moving random +-- ammount from random account to another random accont. +-- Snapshots are made every snapshot_interval seconds and then checked for consistency +-- Settings: You may increase theese value to make test longer +-- number of worker fibers: +workers_count = 80 +--- +... +-- number of iterations per fiber (operations + add new account + add space) +iteration_count = 8 +--- +... +-- number of operations per iterations +operation_count = 8 +--- +... +-- limit of random string length in every account +string_max_size = 128 +--- +... +-- initial number of accounts +accounts_start = 5 +--- +... +-- delay between snapshots +snapshot_interval = 0.005 +--- +... +fiber = require('fiber') +--- +... +fio = require('fio') +--- +... +tarantool_bin_path = arg[-1] +--- +... +work_dir = fio.cwd() +--- +... +snap_dir_as_expected = false +--- +... +snap_dir_as_expected = snap_dir_as_expected or box.cfg.snap_dir == nil +--- +... +snap_dir_as_expected = snap_dir_as_expected or box.cfg.snap_dir == '' +--- +... +snap_dir_as_expected = snap_dir_as_expected or box.cfg.snap_dir == '.' +--- +... +snap_dir_as_expected = snap_dir_as_expected or box.cfg.snap_dir == work_dir +--- +... +snap_dir_as_expected +--- +- true +... +box.cfg.snap_dir +--- +- . +... +script_path = fio.pathjoin(work_dir, 'snap_script.lua') +--- +... +cmd_template = [[/bin/sh -c 'cd "%s" && "%s" ./snap_script.lua 2> /dev/null']] +--- +... +cmd = string.format(cmd_template, work_dir, tarantool_bin_path) +--- +... +open_flags = {'O_CREAT', 'O_WRONLY', 'O_TRUNC'} +--- +... +script = fio.open(script_path, open_flags, tonumber('0777', 8)) +--- +... +script:write("os.exit(-1)") +--- +- true +... +script:close() +--- +- true +... +res = os.execute(cmd) +--- +... +str_res = 'precheck ' .. (res ~= 0 and ' ok(1)' or 'failed(1)') +--- +... +str_res +--- +- precheck ok(1) +... +script = fio.open(script_path, open_flags, tonumber('0777', 8)) +--- +... +script:write("os.exit(0)") +--- +- true +... +script:close() +--- +- true +... +res = os.execute(cmd) +--- +... +str_res = 'precheck ' .. (res == 0 and ' ok(2)' or 'failed(2)') +--- +... +str_res +--- +- precheck ok(2) +... +snap_search_wildcard = fio.pathjoin(box.cfg.snap_dir, '*.snap'); +--- +... +snaps = fio.glob(snap_search_wildcard); +--- +... +initial_snap_count = #snaps +--- +... +s1 = box.schema.create_space("accounts") +--- +... +i1 = s1:create_index('primary', { type = 'HASH', parts = {1, 'num'} }) +--- +... +s2 = box.schema.create_space("operations") +--- +... +i2 = s2:create_index('primary', { type = 'HASH', parts = {1, 'num'} }) +--- +... +n_accs = 0 +--- +... +n_ops = 0 +--- +... +n_spaces = 0 +--- +... +workers_done = 0 +--- +... +--# setopt delimiter ';' +garbage = {}; +--- +... +str = "" +for i = 1,string_max_size do + str = str .. '-' garbage[i - 1] = str +end; +--- +... +function get_new_space_name() + n_spaces = n_spaces + 1 + return "test" .. tostring(n_spaces - 1) +end; +--- +... +function get_rnd_acc() + return math.floor(math.random() * n_accs) +end; +--- +... +function get_rnd_val() + return math.floor(math.random() * 10) +end; +--- +... +function get_rnd_str() + return garbage[math.floor(math.random() * string_max_size)] +end; +--- +... +function add_space() + box.schema.create_space(get_new_space_name()):create_index('test') + n_spaces = n_spaces + 1 +end; +--- +... +function add_acc() + s1:insert{n_accs, 0} n_accs = n_accs + 1 +end; +--- +... +function add_op(n1, n2, v) + s2:insert{n_ops, n1, n2, v} + n_ops = n_ops + 1 +end; +--- +... +function acc_add(n, v) + s1:update({n}, {{'+', 2, v}, {'=', 3, get_rnd_str()}}) +end; +--- +... +function do_op(n1, n2, v) + box.begin() + add_op(n1, n2, v) + acc_add(n1, v) + acc_add(n2, -v) + box.commit() +end; +--- +... +function do_rand_op() + do_op(get_rnd_acc(), get_rnd_acc(), get_rnd_val()) +end; +--- +... +function init() + for i = 1,accounts_start do + add_acc() + end +end; +--- +... +function work_itr() + for j = 1,operation_count do + do_rand_op() + fiber.sleep(0) + end + add_acc() + add_space() +end; +--- +... +function work() + for i = 1,iteration_count do + work_itr() + end + workers_done = workers_done + 1 +end; +--- +... +function snaps() + while (workers_done ~= workers_count) do + pcall(box.snapshot) + fiber.sleep(snapshot_interval) + end snaps_done = true +end; +--- +... +function wait() + while (not snaps_done) do + fiber.sleep(1) + end +end; +--- +... +init(); +--- +... +print('creating snapshot start'); +--- +... +for i = 1,workers_count do + fiber.create(work) +end; +--- +... +local tmp_fib = fiber.create(snaps); +--- +... +wait(); +--- +... +print('creating snapshot done'); +--- +... +#s1:select{}; +--- +- 645 +... +#s2:select{}; +--- +- 5120 +... +s1:drop(); +--- +... +s2:drop(); +--- +... +script_code = [[ +box.cfg{ slab_alloc_arena = 0.5, snap_dir = ".", wal_mode = "none" } + +s1 = box.space.accounts +s2 = box.space.operations + +total_sum = 0 +t1 = {} +for k,v in s1:pairs() do t1[ v[1] ] = v[2] total_sum = total_sum + v[2] end +if total_sum ~= 0 then print('error: total sum mismatch') os.exit(-1) end + +t2 = {} +function acc_inc(n1, v) t2[n1] = (t2[n1] and t2[n1] or 0) + v end +for k,v in s2:pairs() do acc_inc(v[2], v[4]) acc_inc(v[3], -v[4]) end + +bad = false +for k,v in pairs(t1) do if (t2[k] and t2[k] or 0) ~= v then bad = true end end +for k,v in pairs(t2) do if (t1[k] and t1[k] or 0) ~= v then bad = true end end +if bad then print('error: operation apply mismatch') os.exit(-1) end + +print('success: snapshot is ok') +os.exit(0) +]]; +--- +... +script = fio.open(script_path, open_flags, tonumber('0777', 8)) +script:write(script_code) +script:close() + +print('checking snapshot start'); +--- +... +snaps = fio.glob(snap_search_wildcard); +--- +... +snaps_find_status = #snaps <= initial_snap_count and 'where are my snapshots?' or 'snaps found'; +--- +... +snaps_find_status; +--- +- snaps found +... +snapshot_check_status = "snap check ok"; +--- +... +while #snaps > initial_snap_count do + if os.execute(cmd) ~= 0 then + snapshot_check_status = "snap check failed!" + break + end + max_snap = nil + for k,v in pairs(snaps) do + if max_snap == nil or v > max_snap then + max_snap = v + max_snap_k = k + end + end + fio.unlink(fio.pathjoin(box.cfg.snap_dir, max_snap)) + snaps[max_snap_k] = nil +end; +--- +... +snapshot_check_status; +--- +- snap check ok +... +print('checking snapshot done'); +--- +... +--# setopt delimiter '' diff --git a/test/wal_off/snapshot_stress.test.lua b/test/wal_off/snapshot_stress.test.lua new file mode 100644 index 0000000000..afb9eea80a --- /dev/null +++ b/test/wal_off/snapshot_stress.test.lua @@ -0,0 +1,222 @@ +-- The test emulates account system. There are increasing number or accounts +-- and a lot of double entry transactions are made that moving random +-- ammount from random account to another random accont. +-- Snapshots are made every snapshot_interval seconds and then checked for consistency +-- Settings: You may increase theese value to make test longer +-- number of worker fibers: +workers_count = 80 +-- number of iterations per fiber (operations + add new account + add space) +iteration_count = 8 +-- number of operations per iterations +operation_count = 8 +-- limit of random string length in every account +string_max_size = 128 +-- initial number of accounts +accounts_start = 5 +-- delay between snapshots +snapshot_interval = 0.005 + +fiber = require('fiber') +fio = require('fio') + +tarantool_bin_path = arg[-1] +work_dir = fio.cwd() +snap_dir_as_expected = false +snap_dir_as_expected = snap_dir_as_expected or box.cfg.snap_dir == nil +snap_dir_as_expected = snap_dir_as_expected or box.cfg.snap_dir == '' +snap_dir_as_expected = snap_dir_as_expected or box.cfg.snap_dir == '.' +snap_dir_as_expected = snap_dir_as_expected or box.cfg.snap_dir == work_dir +snap_dir_as_expected +box.cfg.snap_dir +script_path = fio.pathjoin(work_dir, 'snap_script.lua') +cmd_template = [[/bin/sh -c 'cd "%s" && "%s" ./snap_script.lua 2> /dev/null']] +cmd = string.format(cmd_template, work_dir, tarantool_bin_path) + +open_flags = {'O_CREAT', 'O_WRONLY', 'O_TRUNC'} +script = fio.open(script_path, open_flags, tonumber('0777', 8)) +script:write("os.exit(-1)") +script:close() +res = os.execute(cmd) +str_res = 'precheck ' .. (res ~= 0 and ' ok(1)' or 'failed(1)') +str_res + +script = fio.open(script_path, open_flags, tonumber('0777', 8)) +script:write("os.exit(0)") +script:close() +res = os.execute(cmd) +str_res = 'precheck ' .. (res == 0 and ' ok(2)' or 'failed(2)') +str_res + +snap_search_wildcard = fio.pathjoin(box.cfg.snap_dir, '*.snap'); +snaps = fio.glob(snap_search_wildcard); +initial_snap_count = #snaps + +s1 = box.schema.create_space("accounts") +i1 = s1:create_index('primary', { type = 'HASH', parts = {1, 'num'} }) +s2 = box.schema.create_space("operations") +i2 = s2:create_index('primary', { type = 'HASH', parts = {1, 'num'} }) + +n_accs = 0 +n_ops = 0 +n_spaces = 0 +workers_done = 0 + +--# setopt delimiter ';' +garbage = {}; +str = "" +for i = 1,string_max_size do + str = str .. '-' garbage[i - 1] = str +end; + +function get_new_space_name() + n_spaces = n_spaces + 1 + return "test" .. tostring(n_spaces - 1) +end; + +function get_rnd_acc() + return math.floor(math.random() * n_accs) +end; + +function get_rnd_val() + return math.floor(math.random() * 10) +end; + +function get_rnd_str() + return garbage[math.floor(math.random() * string_max_size)] +end; + +function add_space() + box.schema.create_space(get_new_space_name()):create_index('test') + n_spaces = n_spaces + 1 +end; + +function add_acc() + s1:insert{n_accs, 0} n_accs = n_accs + 1 +end; + +function add_op(n1, n2, v) + s2:insert{n_ops, n1, n2, v} + n_ops = n_ops + 1 +end; + +function acc_add(n, v) + s1:update({n}, {{'+', 2, v}, {'=', 3, get_rnd_str()}}) +end; + +function do_op(n1, n2, v) + box.begin() + add_op(n1, n2, v) + acc_add(n1, v) + acc_add(n2, -v) + box.commit() +end; + +function do_rand_op() + do_op(get_rnd_acc(), get_rnd_acc(), get_rnd_val()) +end; + +function init() + for i = 1,accounts_start do + add_acc() + end +end; + +function work_itr() + for j = 1,operation_count do + do_rand_op() + fiber.sleep(0) + end + add_acc() + add_space() +end; + +function work() + for i = 1,iteration_count do + work_itr() + end + workers_done = workers_done + 1 +end; + +function snaps() + while (workers_done ~= workers_count) do + pcall(box.snapshot) + fiber.sleep(snapshot_interval) + end snaps_done = true +end; + +function wait() + while (not snaps_done) do + fiber.sleep(1) + end +end; + +init(); + +print('creating snapshot start'); +for i = 1,workers_count do + fiber.create(work) +end; +local tmp_fib = fiber.create(snaps); +wait(); +print('creating snapshot done'); + +#s1:select{}; +#s2:select{}; + +s1:drop(); +s2:drop(); + +script_code = [[ +box.cfg{ slab_alloc_arena = 0.5, snap_dir = ".", wal_mode = "none" } + +s1 = box.space.accounts +s2 = box.space.operations + +total_sum = 0 +t1 = {} +for k,v in s1:pairs() do t1[ v[1] ] = v[2] total_sum = total_sum + v[2] end +if total_sum ~= 0 then print('error: total sum mismatch') os.exit(-1) end + +t2 = {} +function acc_inc(n1, v) t2[n1] = (t2[n1] and t2[n1] or 0) + v end +for k,v in s2:pairs() do acc_inc(v[2], v[4]) acc_inc(v[3], -v[4]) end + +bad = false +for k,v in pairs(t1) do if (t2[k] and t2[k] or 0) ~= v then bad = true end end +for k,v in pairs(t2) do if (t1[k] and t1[k] or 0) ~= v then bad = true end end +if bad then print('error: operation apply mismatch') os.exit(-1) end + +print('success: snapshot is ok') +os.exit(0) +]]; +script = fio.open(script_path, open_flags, tonumber('0777', 8)) +script:write(script_code) +script:close() + +print('checking snapshot start'); + +snaps = fio.glob(snap_search_wildcard); +snaps_find_status = #snaps <= initial_snap_count and 'where are my snapshots?' or 'snaps found'; +snaps_find_status; +snapshot_check_status = "snap check ok"; +while #snaps > initial_snap_count do + if os.execute(cmd) ~= 0 then + snapshot_check_status = "snap check failed!" + break + end + max_snap = nil + for k,v in pairs(snaps) do + if max_snap == nil or v > max_snap then + max_snap = v + max_snap_k = k + end + end + fio.unlink(fio.pathjoin(box.cfg.snap_dir, max_snap)) + snaps[max_snap_k] = nil +end; +snapshot_check_status; +print('checking snapshot done'); + +--# setopt delimiter '' + + -- GitLab