From: AKhatskevich <avkhatskevich@tarantool.org> To: v.shpilevoy@tarantool.org, tarantool-patches@freelists.org Subject: [tarantool-patches] [PATCH][vshard] Reload reloadable fiber Date: Thu, 14 Jun 2018 14:42:02 +0300 [thread overview] Message-ID: <20180614114202.2634-1-avkhatskevich@tarantool.org> (raw) Fixed a problem: The `reloadable_fiber_f` was running an infinite where loop and preventing the whole module from being reloaded. This behavior is fixed by calling new version of `reloadable_fiber_f` in a return statement instead of the where loop. Note: calling a function in a return statement doesn't increase a stack size. Closes #116 --- Branch: https://github.com/tarantool/vshard/tree/kh/gh-116-reloadable Issue: https://github.com/tarantool/vshard/issues/116 test/router/reload.result | 4 +-- test/router/reload.test.lua | 4 +-- test/storage/reload.result | 6 ++-- test/storage/reload.test.lua | 6 ++-- vshard/util.lua | 78 +++++++++++++++++++++++++++++++------------- 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/test/router/reload.result b/test/router/reload.result index 19a9ead..47f3c2e 100644 --- a/test/router/reload.result +++ b/test/router/reload.result @@ -116,10 +116,10 @@ vshard.router.module_version() check_reloaded() --- ... -while test_run:grep_log('router_1', 'Failover has been reloaded') == nil do fiber.sleep(0.1) end +while test_run:grep_log('router_1', 'Failover has been started') == nil do fiber.sleep(0.1) end --- ... -while test_run:grep_log('router_1', 'Discovery has been reloaded') == nil do fiber.sleep(0.1) vshard.router.discovery_wakeup() end +while test_run:grep_log('router_1', 'Discovery has been started') == nil do fiber.sleep(0.1) vshard.router.discovery_wakeup() end --- ... check_reloaded() diff --git a/test/router/reload.test.lua b/test/router/reload.test.lua index 6e21b74..af2939d 100644 --- a/test/router/reload.test.lua +++ b/test/router/reload.test.lua @@ -59,8 +59,8 @@ vshard.router.module_version() check_reloaded() -while test_run:grep_log('router_1', 'Failover has been reloaded') == nil do fiber.sleep(0.1) end -while test_run:grep_log('router_1', 'Discovery has been reloaded') == nil do fiber.sleep(0.1) vshard.router.discovery_wakeup() end +while test_run:grep_log('router_1', 'Failover has been started') == nil do fiber.sleep(0.1) end +while test_run:grep_log('router_1', 'Discovery has been started') == nil do fiber.sleep(0.1) vshard.router.discovery_wakeup() end check_reloaded() diff --git a/test/storage/reload.result b/test/storage/reload.result index f689cf4..531d984 100644 --- a/test/storage/reload.result +++ b/test/storage/reload.result @@ -113,13 +113,13 @@ vshard.storage.module_version() check_reloaded() --- ... -while test_run:grep_log('storage_2_a', 'Garbage collector has been reloaded') == nil do fiber.sleep(0.1) end +while test_run:grep_log('storage_2_a', 'Garbage collector has been started') == nil do fiber.sleep(0.1) end --- ... -while test_run:grep_log('storage_2_a', 'Recovery has been reloaded') == nil do fiber.sleep(0.1) vshard.storage.recovery_wakeup() end +while test_run:grep_log('storage_2_a', 'Recovery has been started') == nil do fiber.sleep(0.1) vshard.storage.recovery_wakeup() end --- ... -while test_run:grep_log('storage_2_a', 'Rebalancer has been reloaded') == nil do fiber.sleep(0.1) vshard.storage.rebalancer_wakeup() end +while test_run:grep_log('storage_2_a', 'Rebalancer has been started') == nil do fiber.sleep(0.1) vshard.storage.rebalancer_wakeup() end --- ... check_reloaded() diff --git a/test/storage/reload.test.lua b/test/storage/reload.test.lua index 6e19a92..64c3a60 100644 --- a/test/storage/reload.test.lua +++ b/test/storage/reload.test.lua @@ -59,9 +59,9 @@ vshard.storage.module_version() check_reloaded() -while test_run:grep_log('storage_2_a', 'Garbage collector has been reloaded') == nil do fiber.sleep(0.1) end -while test_run:grep_log('storage_2_a', 'Recovery has been reloaded') == nil do fiber.sleep(0.1) vshard.storage.recovery_wakeup() end -while test_run:grep_log('storage_2_a', 'Rebalancer has been reloaded') == nil do fiber.sleep(0.1) vshard.storage.rebalancer_wakeup() end +while test_run:grep_log('storage_2_a', 'Garbage collector has been started') == nil do fiber.sleep(0.1) end +while test_run:grep_log('storage_2_a', 'Recovery has been started') == nil do fiber.sleep(0.1) vshard.storage.recovery_wakeup() end +while test_run:grep_log('storage_2_a', 'Rebalancer has been started') == nil do fiber.sleep(0.1) vshard.storage.rebalancer_wakeup() end check_reloaded() diff --git a/vshard/util.lua b/vshard/util.lua index bb71318..fa51701 100644 --- a/vshard/util.lua +++ b/vshard/util.lua @@ -2,6 +2,24 @@ local log = require('log') local fiber = require('fiber') +local MODULE_INTERNALS = '__module_vshard_util' +local M = rawget(_G, MODULE_INTERNALS) +if not M then + -- + -- The module is loaded for the first time. + -- + M = { + -- Latest versions of functions. + reloadable_fiber_f = nil, + errinj = { + RELOADABLE_STACK_MAX = nil, + RELOADABLE_EXIT = nil, + } + + } + rawset(_G, MODULE_INTERNALS, M) +end + -- -- Extract parts of a tuple. -- @param tuple Tuple to extract a key from. @@ -19,33 +37,43 @@ local function tuple_extract_key(tuple, parts) end -- --- Wrapper to run @a func in infinite loop and restart it on the --- module reload. This function CAN NOT BE AUTORELOADED. To update --- it you must manualy stop all fibers, run by this function, do --- reload, and then restart all stopped fibers. This can be done, --- for example, by calling vshard.storage/router.cfg() again with --- the same config as earlier. +-- Wrapper to run a func in infinite loop and restart it on +-- errors and module reload. +-- To handle module reload and run new version of a function +-- in the module, the function should just return. -- --- @param func Reloadable function to run. It must accept current --- module version as an argument, and interrupt itself, --- when it is changed. --- @param worker_name Name of the function. Usual infinite fiber --- represents a background subsystem, which has a name. For --- example: "Garbage Collector", "Recovery", "Discovery", --- "Rebalancer". --- @param M Module which can reload. +-- @param module Module which can be reloaded. +-- @param func_name Name of a function to be executed in the +-- module. +-- @param worker_name Name of the reloadable background subsystem. +-- For example: "Garbage Collector", "Recovery", "Discovery", +-- "Rebalancer". Used only for an activity logging. -- -local function reloadable_fiber_f(M, func_name, worker_name) - while true do - local ok, err = pcall(M[func_name], M.module_version) - if not ok then - log.error('%s has been failed: %s', worker_name, err) - fiber.yield() - else - log.info('%s has been reloaded', worker_name) - fiber.yield() +local function reloadable_fiber_f(module, func_name, worker_name) + log.info('%s has been started', worker_name) + local func = module[func_name] + local ok, err = pcall(func, module.module_version) + if not ok then + log.error('%s has been failed: %s', worker_name, err) + if func ~= module[func_name] then + log.warn('%s reloadable function %s has changed', + worker_name, func_name) end end + fiber.yield() + log.info('%s is reloading', worker_name) + if M.errinj.RELOADABLE_EXIT then + return + end + -- luajit drops this frame if next function is called in + -- return statement. + if M.errinj.RELOADABLE_STACK_MAX then + M.errinj.RELOADABLE_STACK_MAX = M.errinj.RELOADABLE_STACK_MAX - 1 + if M.errinj.RELOADABLE_STACK_MAX == 0 then + return + end + end + return M.reloadable_fiber_f(module, func_name, worker_name) end -- @@ -75,8 +103,12 @@ local function generate_self_checker(obj_name, func_name, mt, func) end end +-- Update latest versions of function +M.reloadable_fiber_f = reloadable_fiber_f + return { tuple_extract_key = tuple_extract_key, reloadable_fiber_f = reloadable_fiber_f, generate_self_checker = generate_self_checker, + internal = M, } -- 2.14.1
next reply other threads:[~2018-06-14 11:42 UTC|newest] Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-06-14 11:42 AKhatskevich [this message] 2018-06-14 11:58 ` AKhatskevich 2018-06-21 12:04 ` [tarantool-patches] " Vladislav Shpilevoy 2018-06-26 12:43 ` Alex Khatskevich 2018-06-26 12:50 ` Alex Khatskevich 2018-06-27 9:54 ` Vladislav Shpilevoy 2018-06-27 10:44 ` Alex Khatskevich 2018-06-27 11:34 ` Vladislav Shpilevoy 2018-06-27 11:45 ` Alex Khatskevich 2018-06-27 11:53 ` Vladislav Shpilevoy 2018-06-27 13:11 ` Vladislav Shpilevoy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20180614114202.2634-1-avkhatskevich@tarantool.org \ --to=avkhatskevich@tarantool.org \ --cc=tarantool-patches@freelists.org \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [tarantool-patches] [PATCH][vshard] Reload reloadable fiber' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox