MCPcopy Create free account
hub / github.com/apache/kvrocks / FunctionLoad

Function FunctionLoad

src/storage/scripting.cc:297–364  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

295}
296
297Status FunctionLoad(redis::Connection *conn, engine::Context *ctx, const std::string &script, bool need_to_store,
298 bool replace, [[maybe_unused]] std::string *lib_name) {
299 std::string first_line, lua_code;
300 if (auto pos = script.find('\n'); pos != std::string::npos) {
301 first_line = script.substr(0, pos);
302 lua_code = script.substr(pos + 1);
303 } else {
304 return {Status::NotOK, "Expect a Shebang statement in the first line"};
305 }
306
307 const auto libname = GET_OR_RET(ExtractLibNameFromShebang(first_line));
308
309 if (FunctionIsLibExist(conn, ctx, libname, need_to_store)) {
310 if (!replace) {
311 return {Status::NotOK, "library already exists, please specify REPLACE to force load"};
312 }
313 auto s = FunctionDelete(*ctx, conn, libname);
314 if (!s) return s;
315 }
316
317 auto srv = conn->GetServer();
318 auto lua = conn->Owner()->Lua();
319
320 ScriptRunCtx script_run_ctx;
321 script_run_ctx.conn = conn;
322 script_run_ctx.ctx = ctx;
323 // in FunctionLoad(), the script MUST be read-only,
324 // because this function can be called multiple times
325 // for one script from multiple threads,
326 // and it is dangerous and unexpected to allow writes here.
327 script_run_ctx.flags = ScriptFlagType::kScriptNoWrites;
328
329 SaveOnRegistry(lua, REGISTRY_SCRIPT_RUN_CTX_NAME, &script_run_ctx);
330
331 lua_pushstring(lua, libname.c_str());
332 lua_setglobal(lua, REDIS_FUNCTION_LIBNAME);
333 auto libname_exit = MakeScopeExit([lua] {
334 lua_pushnil(lua);
335 lua_setglobal(lua, REDIS_FUNCTION_LIBNAME);
336 });
337
338 lua_pushboolean(lua, need_to_store);
339 lua_setglobal(lua, REDIS_FUNCTION_NEEDSTORE);
340 auto need_store_exit = MakeScopeExit([lua] {
341 lua_pushnil(lua);
342 lua_setglobal(lua, REDIS_FUNCTION_NEEDSTORE);
343 });
344
345 if (luaL_loadbuffer(lua, lua_code.data(), lua_code.size(), "@user_script")) {
346 std::string err_msg = lua_tostring(lua, -1);
347 lua_pop(lua, 1);
348 return {Status::NotOK, "Error while compiling new function lib: " + err_msg};
349 }
350
351 if (lua_pcall(lua, 0, 0, 0)) {
352 std::string err_msg = lua_tostring(lua, -1);
353 lua_pop(lua, 1);
354 return {Status::NotOK, "Error while running new function lib: " + err_msg};

Callers 3

ExecuteMethod · 0.85
FunctionIsLibExistFunction · 0.85
FunctionCallFunction · 0.85

Calls 10

FunctionIsLibExistFunction · 0.85
FunctionDeleteFunction · 0.85
SaveOnRegistryFunction · 0.85
MakeScopeExitFunction · 0.85
RemoveFromRegistryFunction · 0.85
GetServerMethod · 0.80
LuaMethod · 0.80
OwnerMethod · 0.80
FunctionSetCodeMethod · 0.80

Tested by

no test coverage detected