| 1525 | } |
| 1526 | |
| 1527 | void evalGenericCommand(client *c, int evalsha) { |
| 1528 | lua_State *lua = g_pserver->lua; |
| 1529 | char funcname[43]; |
| 1530 | long long numkeys; |
| 1531 | long long initial_server_dirty = g_pserver->dirty; |
| 1532 | int delhook = 0, err; |
| 1533 | |
| 1534 | if (g_pserver->m_pstorageFactory != nullptr) |
| 1535 | performEvictions(true); |
| 1536 | |
| 1537 | /* When we replicate whole scripts, we want the same PRNG sequence at |
| 1538 | * every call so that our PRNG is not affected by external state. */ |
| 1539 | redisSrand48(0); |
| 1540 | |
| 1541 | /* We set this flag to zero to remember that so far no random command |
| 1542 | * was called. This way we can allow the user to call commands like |
| 1543 | * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command |
| 1544 | * is called (otherwise the replication and AOF would end with non |
| 1545 | * deterministic sequences). |
| 1546 | * |
| 1547 | * Thanks to this flag we'll raise an error every time a write command |
| 1548 | * is called after a random command was used. */ |
| 1549 | g_pserver->lua_random_dirty = 0; |
| 1550 | g_pserver->lua_write_dirty = 0; |
| 1551 | g_pserver->lua_replicate_commands = g_pserver->lua_always_replicate_commands; |
| 1552 | g_pserver->lua_multi_emitted = 0; |
| 1553 | g_pserver->lua_repl = PROPAGATE_AOF|PROPAGATE_REPL; |
| 1554 | |
| 1555 | /* Get the number of arguments that are keys */ |
| 1556 | if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != C_OK) |
| 1557 | return; |
| 1558 | if (numkeys > (c->argc - 3)) { |
| 1559 | addReplyError(c,"Number of keys can't be greater than number of args"); |
| 1560 | return; |
| 1561 | } else if (numkeys < 0) { |
| 1562 | addReplyError(c,"Number of keys can't be negative"); |
| 1563 | return; |
| 1564 | } |
| 1565 | |
| 1566 | /* We obtain the script SHA1, then check if this function is already |
| 1567 | * defined into the Lua state */ |
| 1568 | funcname[0] = 'f'; |
| 1569 | funcname[1] = '_'; |
| 1570 | if (!evalsha) { |
| 1571 | /* Hash the code if this is an EVAL call */ |
| 1572 | sha1hex(funcname+2,(char*)ptrFromObj(c->argv[1]),sdslen((sds)ptrFromObj(c->argv[1]))); |
| 1573 | } else { |
| 1574 | /* We already have the SHA if it is an EVALSHA */ |
| 1575 | int j; |
| 1576 | char *sha = (char*)ptrFromObj(c->argv[1]); |
| 1577 | |
| 1578 | /* Convert to lowercase. We don't use tolower since the function |
| 1579 | * managed to always show up in the profiler output consuming |
| 1580 | * a non trivial amount of time. */ |
| 1581 | for (j = 0; j < 40; j++) |
| 1582 | funcname[j+2] = (sha[j] >= 'A' && sha[j] <= 'Z') ? |
| 1583 | sha[j]+('a'-'A') : sha[j]; |
| 1584 | funcname[42] = '\0'; |
no test coverage detected