From 3aec485d8ebba02e0c2b620376bb27df7c9e8822 Mon Sep 17 00:00:00 2001 From: Kirill Shcherbatov <kshcherbatov@tarantool.org> Date: Thu, 12 Jul 2018 11:22:39 +0300 Subject: [PATCH] box: support reload whole module Closes #2946. @TarantoolBot document Title: fixed module reload There was a bug in tarantool documentation: https://tarantool.io/en/doc/1.7/book/box/ box_schema/#lua-function.box.schema.func.reload Now it is allowed to reload all functions in loadable module via one method. Legacy method including finction name is forbidden. box.schema.func.reload("utils") -- ok since now box.schema.func.reload("utils.func1") -- forbidden since now Global reload is still unsupported because it seems to be useless. box.schema.func.reload() -- invalid! --- src/box/call.c | 23 +++++++++++++---------- src/box/call.h | 9 ++++++++- src/box/errcode.h | 1 + src/box/func.c | 16 ---------------- src/box/func.h | 11 ++++++++++- src/box/lua/call.c | 6 +++--- src/box/lua/schema.lua | 2 +- test/box/func_reload.result | 23 ++++++++--------------- test/box/func_reload.test.lua | 14 ++++++-------- test/box/misc.result | 1 + 10 files changed, 51 insertions(+), 55 deletions(-) diff --git a/src/box/call.c b/src/box/call.c index 438be190ed..b9750c5f37 100644 --- a/src/box/call.c +++ b/src/box/call.c @@ -132,20 +132,23 @@ box_c_call(struct func *func, struct call_request *request, struct port *port) } int -box_func_reload(const char *name) +box_module_reload(const char *name) { - size_t name_len = strlen(name); - struct func *func = NULL; - if ((access_check_func(name, name_len, &func)) != 0) - return -1; - if (func == NULL) { - diag_set(ClientError, ER_NO_SUCH_FUNCTION, name); + struct credentials *credentials = effective_user(); + if ((credentials->universal_access & (PRIV_X | PRIV_U)) != + (PRIV_X | PRIV_U)) { + struct user *user = user_find(credentials->uid); + if (user != NULL) + diag_set(AccessDeniedError, priv_name(PRIV_U), + schema_object_name(SC_UNIVERSE), "", + user->def->name); return -1; } - if (func->def->language != FUNC_LANGUAGE_C || func->func == NULL) - return 0; /* Nothing to do */ - if (func_reload(func) == 0) + struct module *module = NULL; + if (module_reload(name, name + strlen(name), &module) == 0 && + module != NULL) return 0; + diag_set(ClientError, ER_NO_SUCH_MODULE, name); return -1; } diff --git a/src/box/call.h b/src/box/call.h index eabba69763..1b54551be3 100644 --- a/src/box/call.h +++ b/src/box/call.h @@ -42,8 +42,15 @@ struct box_function_ctx { struct port *port; }; +/** + * Reload loadable module by name. + * + * @param name of the module to reload. + * @retval -1 on error. + * @retval 0 on success. + */ int -box_func_reload(const char *name); +box_module_reload(const char *name); int box_process_call(struct call_request *request, struct port *port); diff --git a/src/box/errcode.h b/src/box/errcode.h index c921559b42..0cf9578f83 100644 --- a/src/box/errcode.h +++ b/src/box/errcode.h @@ -217,6 +217,7 @@ struct errcode_record { /*162 */_(ER_FOREIGN_KEY_CONSTRAINT, "Can not commit transaction: deferred foreign keys violations are not resolved") \ /*163 */_(ER_TRANSACTION_YIELD, "Transaction has been aborted by a fiber yield") \ /*164 */_(ER_NO_SUCH_GROUP, "Replication group '%s' does not exist") \ + /*165 */_(ER_NO_SUCH_MODULE, "Module '%s' does not exist") \ /* * !IMPORTANT! Please follow instructions at start of the file diff --git a/src/box/func.c b/src/box/func.c index dfbc5f39b0..a817851fda 100644 --- a/src/box/func.c +++ b/src/box/func.c @@ -298,9 +298,6 @@ module_sym(struct module *module, const char *name) return f; } -/* - * Reload a dso. - */ int module_reload(const char *package, const char *package_end, struct module **module) { @@ -435,19 +432,6 @@ func_load(struct func *func) return 0; } -int -func_reload(struct func *func) -{ - struct func_name name; - func_split_name(func->def->name, &name); - struct module *module = NULL; - if (module_reload(name.package, name.package_end, &module) != 0) { - diag_log(); - return -1; - } - return 0; -} - int func_call(struct func *func, box_function_ctx_t *ctx, const char *args, const char *args_end) diff --git a/src/box/func.h b/src/box/func.h index 0957546c62..8dcd61d7b3 100644 --- a/src/box/func.h +++ b/src/box/func.h @@ -113,8 +113,17 @@ int func_call(struct func *func, box_function_ctx_t *ctx, const char *args, const char *args_end); +/** + * Reload dynamically loadable module. + * + * @param package name begin pointer. + * @param package_end package_end name end pointer. + * @param[out] module a pointer to store module object on success. + * @retval -1 on error. + * @retval 0 on success. + */ int -func_reload(struct func *func); +module_reload(const char *package, const char *package_end, struct module **module); #if defined(__cplusplus) } /* extern "C" */ diff --git a/src/box/lua/call.c b/src/box/lua/call.c index 8f3461afa7..d20cbbbcde 100644 --- a/src/box/lua/call.c +++ b/src/box/lua/call.c @@ -458,10 +458,10 @@ box_lua_eval(struct call_request *request, struct port *port) } static int -lbox_func_reload(lua_State *L) +lbox_module_reload(lua_State *L) { const char *name = luaL_checkstring(L, 1); - if (box_func_reload(name) != 0) + if (box_module_reload(name) != 0) return luaT_error(L); return 0; } @@ -469,7 +469,7 @@ lbox_func_reload(lua_State *L) static const struct luaL_Reg boxlib_internal[] = { {"call_loadproc", lbox_call_loadproc}, {"sql_create_function", lbox_sql_create_function}, - {"func_reload", lbox_func_reload}, + {"module_reload", lbox_module_reload}, {NULL, NULL} }; diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index e4c1b1d38e..4368583115 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -1953,7 +1953,7 @@ function box.schema.func.exists(name_or_id) return tuple ~= nil end -box.schema.func.reload = internal.func_reload +box.schema.func.reload = internal.module_reload box.internal.collation = {} box.internal.collation.create = function(name, coll_type, locale, opts) diff --git a/test/box/func_reload.result b/test/box/func_reload.result index 5aeb85c54a..b024cd143e 100644 --- a/test/box/func_reload.result +++ b/test/box/func_reload.result @@ -51,8 +51,9 @@ fio.symlink(reload1_path, reload_path) - true ... --check not fail on non-load func -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") --- +- error: Module 'reload' does not exist ... -- test of usual case reload. No hanging calls box.space.test:insert{0} @@ -74,7 +75,7 @@ fio.symlink(reload2_path, reload_path) --- - true ... -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") --- ... c:call("reload.foo") @@ -98,7 +99,7 @@ fio.symlink(reload1_path, reload_path) --- - true ... -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") --- ... fibers = 10 @@ -111,7 +112,7 @@ while box.space.test:count() < fibers do fiber.sleep(0.001) end --- ... -- double reload doesn't fail waiting functions -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") --- ... _ = fio.unlink(reload_path) @@ -121,7 +122,7 @@ fio.symlink(reload2_path, reload_path) --- - true ... -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") --- ... c:call("reload.foo") @@ -208,7 +209,7 @@ _ = fiber.create(function() ch:put(c:call("reload.test_reload")) end) while s:get({1}) == nil do fiber.yield(0.0001) end --- ... -box.schema.func.reload("reload.test_reload") +box.schema.func.reload("reload") --- ... _ = fiber.create(function() ch:put(c:call("reload.test_reload")) end) @@ -242,14 +243,6 @@ fio.symlink(reload1_path, reload_path) --- - true ... -s, e = pcall(box.schema.func.reload, "reload.test_reload") ---- -... -s, string.find(tostring(e), 'test_reload_fail') ~= nil ---- -- false -- true -... c:call("reload.test_reload") --- - [[2]] @@ -273,5 +266,5 @@ box.schema.func.reload() ... box.schema.func.reload("non-existing") --- -- error: Function 'non-existing' does not exist +- error: Module 'non-existing' does not exist ... diff --git a/test/box/func_reload.test.lua b/test/box/func_reload.test.lua index dc56d84dad..8906898ecb 100644 --- a/test/box/func_reload.test.lua +++ b/test/box/func_reload.test.lua @@ -20,7 +20,7 @@ _ = fio.unlink(reload_path) fio.symlink(reload1_path, reload_path) --check not fail on non-load func -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") -- test of usual case reload. No hanging calls box.space.test:insert{0} @@ -29,7 +29,7 @@ box.space.test:delete{0} _ = fio.unlink(reload_path) fio.symlink(reload2_path, reload_path) -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") c:call("reload.foo") box.space.test:select{} box.space.test:truncate() @@ -37,18 +37,18 @@ box.space.test:truncate() -- test case with hanging calls _ = fio.unlink(reload_path) fio.symlink(reload1_path, reload_path) -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") fibers = 10 for i = 1, fibers do fiber.create(function() c:call("reload.foo", {i}) end) end while box.space.test:count() < fibers do fiber.sleep(0.001) end -- double reload doesn't fail waiting functions -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") _ = fio.unlink(reload_path) fio.symlink(reload2_path, reload_path) -box.schema.func.reload("reload.foo") +box.schema.func.reload("reload") c:call("reload.foo") while box.space.test:count() < 2 * fibers + 1 do fiber.sleep(0.001) end @@ -71,7 +71,7 @@ _ = fio.unlink(reload_path) fio.symlink(reload2_path, reload_path) _ = fiber.create(function() ch:put(c:call("reload.test_reload")) end) while s:get({1}) == nil do fiber.yield(0.0001) end -box.schema.func.reload("reload.test_reload") +box.schema.func.reload("reload") _ = fiber.create(function() ch:put(c:call("reload.test_reload")) end) ch:get() ch:get() @@ -82,8 +82,6 @@ box.schema.user.grant('guest', 'execute', 'function', 'reload.test_reload_fail') c:call("reload.test_reload_fail") _ = fio.unlink(reload_path) fio.symlink(reload1_path, reload_path) -s, e = pcall(box.schema.func.reload, "reload.test_reload") -s, string.find(tostring(e), 'test_reload_fail') ~= nil c:call("reload.test_reload") c:call("reload.test_reload_fail") diff --git a/test/box/misc.result b/test/box/misc.result index f332a8c2f8..2f8cacf097 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -489,6 +489,7 @@ t; 162: box.error.FOREIGN_KEY_CONSTRAINT 163: box.error.TRANSACTION_YIELD 164: box.error.NO_SUCH_GROUP + 165: box.error.NO_SUCH_MODULE ... test_run:cmd("setopt delimiter ''"); --- -- GitLab