| 506 | #define LUA_CMD_OBJCACHE_SIZE 32 |
| 507 | #define LUA_CMD_OBJCACHE_MAX_LEN 64 |
| 508 | int luaRedisGenericCommand(lua_State *lua, int raise_error) { |
| 509 | int j, argc = lua_gettop(lua); |
| 510 | int call_flags = CMD_CALL_SLOWLOG | CMD_CALL_STATS; |
| 511 | struct redisCommand *cmd; |
| 512 | client *c = serverTL->lua_client; |
| 513 | sds reply; |
| 514 | |
| 515 | // Ensure our client is on the right thread |
| 516 | serverAssert(!(c->flags & CLIENT_PENDING_WRITE)); |
| 517 | serverAssert(!(c->flags & CLIENT_UNBLOCKED)); |
| 518 | serverAssert(GlobalLocksAcquired()); |
| 519 | c->iel = serverTL - g_pserver->rgthreadvar; |
| 520 | |
| 521 | /* Cached across calls. */ |
| 522 | static robj **argv = NULL; |
| 523 | static int argv_size = 0; |
| 524 | static robj *cached_objects[LUA_CMD_OBJCACHE_SIZE]; |
| 525 | static size_t cached_objects_len[LUA_CMD_OBJCACHE_SIZE]; |
| 526 | static int inuse = 0; /* Recursive calls detection. */ |
| 527 | |
| 528 | /* By using Lua debug hooks it is possible to trigger a recursive call |
| 529 | * to luaRedisGenericCommand(), which normally should never happen. |
| 530 | * To make this function reentrant is futile and makes it slower, but |
| 531 | * we should at least detect such a misuse, and abort. */ |
| 532 | if (inuse) { |
| 533 | const char *recursion_warning = |
| 534 | "luaRedisGenericCommand() recursive call detected. " |
| 535 | "Are you doing funny stuff with Lua debug hooks?"; |
| 536 | serverLog(LL_WARNING,"%s",recursion_warning); |
| 537 | luaPushError(lua,recursion_warning); |
| 538 | return 1; |
| 539 | } |
| 540 | inuse++; |
| 541 | std::unique_lock<decltype(c->lock)> ulock(c->lock); |
| 542 | |
| 543 | { // Begin GOTO protected variables |
| 544 | /* Require at least one argument */ |
| 545 | if (argc == 0) { |
| 546 | luaPushError(lua, |
| 547 | "Please specify at least one argument for redis.call()"); |
| 548 | inuse--; |
| 549 | return raise_error ? luaRaiseError(lua) : 1; |
| 550 | } |
| 551 | |
| 552 | /* Build the arguments vector */ |
| 553 | if (argv_size < argc) { |
| 554 | argv = (robj**)zrealloc(argv,sizeof(robj*)*argc, MALLOC_LOCAL); |
| 555 | argv_size = argc; |
| 556 | } |
| 557 | |
| 558 | for (j = 0; j < argc; j++) { |
| 559 | char *obj_s; |
| 560 | size_t obj_len; |
| 561 | char dbuf[64]; |
| 562 | |
| 563 | if (lua_type(lua,j+1) == LUA_TNUMBER) { |
| 564 | /* We can't use lua_tolstring() for number -> string conversion |
| 565 | * since Lua uses a format specifier that loses precision. */ |
no test coverage detected