FunctionCall will firstly find the function in the lua runtime, if it is not found, it will try to load the library where the function is located from storage
| 398 | // FunctionCall will firstly find the function in the lua runtime, |
| 399 | // if it is not found, it will try to load the library where the function is located from storage |
| 400 | Status FunctionCall(redis::Connection *conn, engine::Context *ctx, const std::string &name, |
| 401 | const std::vector<std::string> &keys, const std::vector<std::string> &argv, std::string *output, |
| 402 | bool read_only) { |
| 403 | auto srv = conn->GetServer(); |
| 404 | auto lua = conn->Owner()->Lua(); |
| 405 | |
| 406 | lua_getglobal(lua, "__redis__err__handler"); |
| 407 | |
| 408 | lua_getglobal(lua, (REDIS_LUA_REGISTER_FUNC_PREFIX + name).c_str()); |
| 409 | if (lua_isnil(lua, -1)) { |
| 410 | lua_pop(lua, 1); |
| 411 | |
| 412 | std::string libname; |
| 413 | auto s = srv->FunctionGetLib(name, &libname); |
| 414 | if (!s) return s.Prefixed("No such function name found in storage"); |
| 415 | |
| 416 | std::string libcode; |
| 417 | s = srv->FunctionGetCode(libname, &libcode); |
| 418 | if (!s) return s; |
| 419 | s = FunctionLoad(conn, ctx, libcode, false, false, &libname); |
| 420 | if (!s) return s; |
| 421 | |
| 422 | lua_getglobal(lua, (REDIS_LUA_REGISTER_FUNC_PREFIX + name).c_str()); |
| 423 | } |
| 424 | |
| 425 | ScriptRunCtx script_run_ctx; |
| 426 | script_run_ctx.conn = conn; |
| 427 | script_run_ctx.ctx = ctx; |
| 428 | script_run_ctx.flags = read_only ? ScriptFlagType::kScriptNoWrites : 0; |
| 429 | lua_getglobal(lua, (REDIS_LUA_REGISTER_FUNC_FLAGS_PREFIX + name).c_str()); |
| 430 | if (!lua_isnil(lua, -1)) { |
| 431 | // It should be ensured that the conversion is successful |
| 432 | auto function_flags = lua_tointeger(lua, -1); |
| 433 | script_run_ctx.flags |= function_flags; |
| 434 | } |
| 435 | lua_pop(lua, 1); |
| 436 | |
| 437 | SaveOnRegistry(lua, REGISTRY_SCRIPT_RUN_CTX_NAME, &script_run_ctx); |
| 438 | |
| 439 | // save keys on registry the to perform key touching check |
| 440 | SaveOnRegistry(lua, REGISTRY_KEYS_NAME, &keys); |
| 441 | |
| 442 | PushArray(lua, keys); |
| 443 | PushArray(lua, argv); |
| 444 | if (lua_pcall(lua, 2, 1, -4)) { |
| 445 | std::string err_msg = lua_tostring(lua, -1); |
| 446 | lua_pop(lua, 2); |
| 447 | return {Status::NotOK, fmt::format("Error while running function `{}`: {}", name, err_msg)}; |
| 448 | } else { |
| 449 | *output = ReplyToRedisReply(conn, lua); |
| 450 | lua_pop(lua, 2); |
| 451 | } |
| 452 | |
| 453 | RemoveFromRegistry(lua, REGISTRY_KEYS_NAME); |
| 454 | RemoveFromRegistry(lua, REGISTRY_SCRIPT_RUN_CTX_NAME); |
| 455 | |
| 456 | /* Call the Lua garbage collector from time to time to avoid a |
| 457 | * full cycle performed by Lua, which adds too latency. |
no test coverage detected