| 1033 | } |
| 1034 | |
| 1035 | Expected<std::string> LuaState::evalGenericCommand(Session* sess, int evalsha) { |
| 1036 | _sess = sess; |
| 1037 | const auto& args = sess->getArgs(); |
| 1038 | int delhook = 0; |
| 1039 | |
| 1040 | char funcname[43]; |
| 1041 | int64_t numkeys; |
| 1042 | int err; |
| 1043 | |
| 1044 | _rand.redisSrand48(0); |
| 1045 | |
| 1046 | lua_random_dirty = 0; |
| 1047 | lua_write_dirty = 0; |
| 1048 | int lua_always_replicate_commands = 1; // TODO(takenliu) |
| 1049 | lua_replicate_commands = lua_always_replicate_commands; |
| 1050 | // has_command_error = false; |
| 1051 | |
| 1052 | /* Get the number of arguments that are keys */ |
| 1053 | const auto& eNumkeys = ::tendisplus::stoll(args[2]); |
| 1054 | if (!eNumkeys.ok()) { |
| 1055 | return eNumkeys.status(); |
| 1056 | } |
| 1057 | numkeys = eNumkeys.value(); |
| 1058 | if (numkeys > static_cast<int>(args.size() - 3)) { |
| 1059 | return {ErrorCodes::ERR_LUA, |
| 1060 | "Number of keys can't be greater than number of args"}; |
| 1061 | } else if (numkeys < 0) { |
| 1062 | return {ErrorCodes::ERR_LUA, "Number of keys can't be negative"}; |
| 1063 | } |
| 1064 | funcname[0] = 'f'; |
| 1065 | funcname[1] = '_'; |
| 1066 | if (!evalsha) { |
| 1067 | /* Hash the code if this is an EVAL call */ |
| 1068 | sha1hex(funcname + 2, const_cast<char*>(args[1].c_str()), args[1].length()); |
| 1069 | } else { |
| 1070 | /* Convert to lowercase. */ |
| 1071 | for (int j = 0; j < 40; j++) |
| 1072 | funcname[j + 2] = (args[1][j] >= 'A' && args[1][j] <= 'Z') |
| 1073 | ? args[1][j] + ('a' - 'A') |
| 1074 | : args[1][j]; |
| 1075 | funcname[42] = '\0'; |
| 1076 | } |
| 1077 | /* Push the pcall error handler function on the stack. */ |
| 1078 | lua_getglobal(_lua, "__redis__err__handler"); |
| 1079 | |
| 1080 | /* Try to lookup the Lua function */ |
| 1081 | lua_getglobal(_lua, funcname); |
| 1082 | if (lua_isnil(_lua, -1)) { |
| 1083 | lua_pop(_lua, 1); /* remove the nil from the stack */ |
| 1084 | /* Function not defined... let's define it if we have the |
| 1085 | * body of the function. |
| 1086 | * (New in Tendis) If this is an EVALSHA call, we will get script content |
| 1087 | * from kvstore as Tendis stores all lua scripts received persistently. */ |
| 1088 | std::string shaString(funcname + 2, 40); |
| 1089 | if (evalsha) { |
| 1090 | /* try to get script content from kvstore */ |
| 1091 | auto expScript = _scriptMgr->getScriptContent(sess, shaString); |
| 1092 | if (!expScript.ok()) { /* not found in kvstore */ |
nothing calls this directly
no test coverage detected