11 char *redisProtocolToLuaType_Int(lua_State
*lua
, char *reply
);
12 char *redisProtocolToLuaType_Bulk(lua_State
*lua
, char *reply
);
13 char *redisProtocolToLuaType_Status(lua_State
*lua
, char *reply
);
14 char *redisProtocolToLuaType_Error(lua_State
*lua
, char *reply
);
15 char *redisProtocolToLuaType_MultiBulk(lua_State
*lua
, char *reply
);
16 int redis_math_random (lua_State
*L
);
17 int redis_math_randomseed (lua_State
*L
);
18 void sha1hex(char *digest
, char *script
, size_t len
);
20 /* Take a Redis reply in the Redis protocol format and convert it into a
21 * Lua type. Thanks to this function, and the introduction of not connected
22 * clients, it is trvial to implement the redis() lua function.
24 * Basically we take the arguments, execute the Redis command in the context
25 * of a non connected client, then take the generated reply and convert it
26 * into a suitable Lua type. With this trick the scripting feature does not
27 * need the introduction of a full Redis internals API. Basically the script
28 * is like a normal client that bypasses all the slow I/O paths.
30 * Note: in this function we do not do any sanity check as the reply is
31 * generated by Redis directly. This allows us to go faster.
32 * The reply string can be altered during the parsing as it is discared
33 * after the conversion is completed.
35 * Errors are returned as a table with a single 'err' field set to the
39 char *redisProtocolToLuaType(lua_State
*lua
, char* reply
) {
44 p
= redisProtocolToLuaType_Int(lua
,reply
);
47 p
= redisProtocolToLuaType_Bulk(lua
,reply
);
50 p
= redisProtocolToLuaType_Status(lua
,reply
);
53 p
= redisProtocolToLuaType_Error(lua
,reply
);
56 p
= redisProtocolToLuaType_MultiBulk(lua
,reply
);
62 char *redisProtocolToLuaType_Int(lua_State
*lua
, char *reply
) {
63 char *p
= strchr(reply
+1,'\r');
66 string2ll(reply
+1,p
-reply
-1,&value
);
67 lua_pushnumber(lua
,(lua_Number
)value
);
71 char *redisProtocolToLuaType_Bulk(lua_State
*lua
, char *reply
) {
72 char *p
= strchr(reply
+1,'\r');
75 string2ll(reply
+1,p
-reply
-1,&bulklen
);
77 lua_pushboolean(lua
,0);
80 lua_pushlstring(lua
,p
+2,bulklen
);
85 char *redisProtocolToLuaType_Status(lua_State
*lua
, char *reply
) {
86 char *p
= strchr(reply
+1,'\r');
89 lua_pushstring(lua
,"ok");
90 lua_pushlstring(lua
,reply
+1,p
-reply
-1);
95 char *redisProtocolToLuaType_Error(lua_State
*lua
, char *reply
) {
96 char *p
= strchr(reply
+1,'\r');
99 lua_pushstring(lua
,"err");
100 lua_pushlstring(lua
,reply
+1,p
-reply
-1);
101 lua_settable(lua
,-3);
105 char *redisProtocolToLuaType_MultiBulk(lua_State
*lua
, char *reply
) {
106 char *p
= strchr(reply
+1,'\r');
110 string2ll(reply
+1,p
-reply
-1,&mbulklen
);
112 if (mbulklen
== -1) {
113 lua_pushboolean(lua
,0);
117 for (j
= 0; j
< mbulklen
; j
++) {
118 lua_pushnumber(lua
,j
+1);
119 p
= redisProtocolToLuaType(lua
,p
);
120 lua_settable(lua
,-3);
125 void luaPushError(lua_State
*lua
, char *error
) {
127 lua_pushstring(lua
,"err");
128 lua_pushstring(lua
, error
);
129 lua_settable(lua
,-3);
132 /* Sort the array currently in the stack. We do this to make the output
133 * of commands like KEYS or SMEMBERS something deterministic when called
134 * from Lua (to play well with AOf/replication).
136 * The array is sorted using table.sort itself, and assuming all the
137 * list elements are strings. */
138 void luaSortArray(lua_State
*lua
) {
139 /* Initial Stack: array */
140 lua_getglobal(lua
,"table");
141 lua_pushstring(lua
,"sort");
142 lua_gettable(lua
,-2); /* Stack: array, table, table.sort */
143 lua_pushvalue(lua
,-3); /* Stack: array, table, table.sort, array */
144 if (lua_pcall(lua
,1,0,0)) {
145 /* Stack: array, table, error */
147 /* We are not interested in the error, we assume that the problem is
148 * that there are 'false' elements inside the array, so we try
149 * again with a slower function but able to handle this case, that
150 * is: table.sort(table, __redis__compare_helper) */
151 lua_pop(lua
,1); /* Stack: array, table */
152 lua_pushstring(lua
,"sort"); /* Stack: array, table, sort */
153 lua_gettable(lua
,-2); /* Stack: array, table, table.sort */
154 lua_pushvalue(lua
,-3); /* Stack: array, table, table.sort, array */
155 lua_getglobal(lua
,"__redis__compare_helper");
156 /* Stack: array, table, table.sort, array, __redis__compare_helper */
159 /* Stack: array (sorted), table */
160 lua_pop(lua
,1); /* Stack: array (sorted) */
163 int luaRedisGenericCommand(lua_State
*lua
, int raise_error
) {
164 int j
, argc
= lua_gettop(lua
);
165 struct redisCommand
*cmd
;
167 redisClient
*c
= server
.lua_client
;
170 /* Require at least one argument */
173 "Please specify at least one argument for redis.call()");
177 /* Build the arguments vector */
178 argv
= zmalloc(sizeof(robj
*)*argc
);
179 for (j
= 0; j
< argc
; j
++) {
180 if (!lua_isstring(lua
,j
+1)) break;
181 argv
[j
] = createStringObject((char*)lua_tostring(lua
,j
+1),
182 lua_strlen(lua
,j
+1));
185 /* Check if one of the arguments passed by the Lua script
186 * is not a string or an integer (lua_isstring() return true for
187 * integers as well). */
191 decrRefCount(argv
[j
]);
196 "Lua redis() command arguments must be strings or integers");
200 /* Setup our fake client for command execution */
205 cmd
= lookupCommand(argv
[0]->ptr
);
206 if (!cmd
|| ((cmd
->arity
> 0 && cmd
->arity
!= argc
) ||
207 (argc
< -cmd
->arity
)))
211 "Wrong number of args calling Redis command From Lua script");
213 luaPushError(lua
,"Unknown Redis command called from Lua script");
217 /* There are commands that are not allowed inside scripts. */
218 if (cmd
->flags
& REDIS_CMD_NOSCRIPT
) {
219 luaPushError(lua
, "This Redis command is not allowed from scripts");
223 /* Write commands are forbidden against read-only slaves, or if a
224 * command marked as non-deterministic was already called in the context
226 if (cmd
->flags
& REDIS_CMD_WRITE
) {
227 if (server
.lua_random_dirty
) {
229 "Write commands not allowed after non deterministic commands");
231 } else if (server
.masterhost
&& server
.repl_slave_ro
&&
232 !(server
.lua_caller
->flags
& REDIS_MASTER
))
234 luaPushError(lua
, shared
.roslaveerr
->ptr
);
236 } else if (server
.stop_writes_on_bgsave_err
&&
237 server
.saveparamslen
> 0 &&
238 server
.lastbgsave_status
== REDIS_ERR
)
240 luaPushError(lua
, shared
.bgsaveerr
->ptr
);
245 /* If we reached the memory limit configured via maxmemory, commands that
246 * could enlarge the memory usage are not allowed, but only if this is the
247 * first write in the context of this script, otherwise we can't stop
249 if (server
.maxmemory
&& server
.lua_write_dirty
== 0 &&
250 (cmd
->flags
& REDIS_CMD_DENYOOM
))
252 if (freeMemoryIfNeeded() == REDIS_ERR
) {
253 luaPushError(lua
, shared
.oomerr
->ptr
);
258 if (cmd
->flags
& REDIS_CMD_RANDOM
) server
.lua_random_dirty
= 1;
259 if (cmd
->flags
& REDIS_CMD_WRITE
) server
.lua_write_dirty
= 1;
261 /* Run the command */
263 call(c
,REDIS_CALL_SLOWLOG
| REDIS_CALL_STATS
);
265 /* Convert the result of the Redis command into a suitable Lua type.
266 * The first thing we need is to create a single string from the client
270 reply
= sdscatlen(reply
,c
->buf
,c
->bufpos
);
273 while(listLength(c
->reply
)) {
274 robj
*o
= listNodeValue(listFirst(c
->reply
));
276 reply
= sdscatlen(reply
,o
->ptr
,sdslen(o
->ptr
));
277 listDelNode(c
->reply
,listFirst(c
->reply
));
279 if (raise_error
&& reply
[0] != '-') raise_error
= 0;
280 redisProtocolToLuaType(lua
,reply
);
281 /* Sort the output array if needed, assuming it is a non-null multi bulk
282 * reply as expected. */
283 if ((cmd
->flags
& REDIS_CMD_SORT_FOR_SCRIPT
) &&
284 (reply
[0] == '*' && reply
[1] != '-')) {
291 /* Clean up. Command code may have changed argv/argc so we use the
292 * argv/argc of the client instead of the local variables. */
293 for (j
= 0; j
< c
->argc
; j
++)
294 decrRefCount(c
->argv
[j
]);
298 /* If we are here we should have an error in the stack, in the
299 * form of a table with an "err" field. Extract the string to
300 * return the plain error. */
301 lua_pushstring(lua
,"err");
302 lua_gettable(lua
,-2);
303 return lua_error(lua
);
308 int luaRedisCallCommand(lua_State
*lua
) {
309 return luaRedisGenericCommand(lua
,1);
312 int luaRedisPCallCommand(lua_State
*lua
) {
313 return luaRedisGenericCommand(lua
,0);
316 /* This adds redis.sha1hex(string) to Lua scripts using the same hashing
317 * function used for sha1ing lua scripts. */
318 int luaRedisSha1hexCommand(lua_State
*lua
) {
319 int argc
= lua_gettop(lua
);
325 luaPushError(lua
, "wrong number of arguments");
329 s
= (char*)lua_tolstring(lua
,1,&len
);
330 sha1hex(digest
,s
,len
);
331 lua_pushstring(lua
,digest
);
335 /* Returns a table with a single field 'field' set to the string value
336 * passed as argument. This helper function is handy when returning
337 * a Redis Protocol error or status reply from Lua:
339 * return redis.error_reply("ERR Some Error")
340 * return redis.status_reply("ERR Some Error")
342 int luaRedisReturnSingleFieldTable(lua_State
*lua
, char *field
) {
343 if (lua_gettop(lua
) != 1 || lua_type(lua
,-1) != LUA_TSTRING
) {
344 luaPushError(lua
, "wrong number or type of arguments");
349 lua_pushstring(lua
, field
);
350 lua_pushvalue(lua
, -3);
351 lua_settable(lua
, -3);
355 int luaRedisErrorReplyCommand(lua_State
*lua
) {
356 return luaRedisReturnSingleFieldTable(lua
,"err");
359 int luaRedisStatusReplyCommand(lua_State
*lua
) {
360 return luaRedisReturnSingleFieldTable(lua
,"ok");
363 int luaLogCommand(lua_State
*lua
) {
364 int j
, argc
= lua_gettop(lua
);
369 luaPushError(lua
, "redis.log() requires two arguments or more.");
371 } else if (!lua_isnumber(lua
,-argc
)) {
372 luaPushError(lua
, "First argument must be a number (log level).");
375 level
= lua_tonumber(lua
,-argc
);
376 if (level
< REDIS_DEBUG
|| level
> REDIS_WARNING
) {
377 luaPushError(lua
, "Invalid debug level.");
381 /* Glue together all the arguments */
383 for (j
= 1; j
< argc
; j
++) {
387 s
= (char*)lua_tolstring(lua
,(-argc
)+j
,&len
);
389 if (j
!= 1) log
= sdscatlen(log
," ",1);
390 log
= sdscatlen(log
,s
,len
);
393 redisLogRaw(level
,log
);
398 void luaMaskCountHook(lua_State
*lua
, lua_Debug
*ar
) {
403 elapsed
= (ustime()/1000) - server
.lua_time_start
;
404 if (elapsed
>= server
.lua_time_limit
&& server
.lua_timedout
== 0) {
405 redisLog(REDIS_WARNING
,"Lua slow script detected: still in execution after %lld milliseconds. You can try killing the script using the SCRIPT KILL command.",elapsed
);
406 server
.lua_timedout
= 1;
407 /* Once the script timeouts we reenter the event loop to permit others
408 * to call SCRIPT KILL or SHUTDOWN NOSAVE if needed. For this reason
409 * we need to mask the client executing the script from the event loop.
410 * If we don't do that the client may disconnect and could no longer be
411 * here when the EVAL command will return. */
412 aeDeleteFileEvent(server
.el
, server
.lua_caller
->fd
, AE_READABLE
);
414 if (server
.lua_timedout
)
415 aeProcessEvents(server
.el
, AE_FILE_EVENTS
|AE_DONT_WAIT
);
416 if (server
.lua_kill
) {
417 redisLog(REDIS_WARNING
,"Lua script killed by user with SCRIPT KILL.");
418 lua_pushstring(lua
,"Script killed by user with SCRIPT KILL...");
423 void luaLoadLib(lua_State
*lua
, const char *libname
, lua_CFunction luafunc
) {
424 lua_pushcfunction(lua
, luafunc
);
425 lua_pushstring(lua
, libname
);
429 LUALIB_API
int (luaopen_cjson
) (lua_State
*L
);
430 LUALIB_API
int (luaopen_struct
) (lua_State
*L
);
431 LUALIB_API
int (luaopen_cmsgpack
) (lua_State
*L
);
433 void luaLoadLibraries(lua_State
*lua
) {
434 luaLoadLib(lua
, "", luaopen_base
);
435 luaLoadLib(lua
, LUA_TABLIBNAME
, luaopen_table
);
436 luaLoadLib(lua
, LUA_STRLIBNAME
, luaopen_string
);
437 luaLoadLib(lua
, LUA_MATHLIBNAME
, luaopen_math
);
438 luaLoadLib(lua
, LUA_DBLIBNAME
, luaopen_debug
);
439 luaLoadLib(lua
, "cjson", luaopen_cjson
);
440 luaLoadLib(lua
, "struct", luaopen_struct
);
441 luaLoadLib(lua
, "cmsgpack", luaopen_cmsgpack
);
443 #if 0 /* Stuff that we don't load currently, for sandboxing concerns. */
444 luaLoadLib(lua
, LUA_LOADLIBNAME
, luaopen_package
);
445 luaLoadLib(lua
, LUA_OSLIBNAME
, luaopen_os
);
449 /* Remove a functions that we don't want to expose to the Redis scripting
451 void luaRemoveUnsupportedFunctions(lua_State
*lua
) {
453 lua_setglobal(lua
,"loadfile");
456 /* This function installs metamethods in the global table _G that prevent
457 * the creation of globals accidentally.
459 * It should be the last to be called in the scripting engine initialization
460 * sequence, because it may interact with creation of globals. */
461 void scriptingEnableGlobalsProtection(lua_State
*lua
) {
463 sds code
= sdsempty();
466 /* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.
467 * Modified to be adapted to Redis. */
468 s
[j
++]="local mt = {}\n";
469 s
[j
++]="setmetatable(_G, mt)\n";
470 s
[j
++]="mt.__newindex = function (t, n, v)\n";
471 s
[j
++]=" if debug.getinfo(2) then\n";
472 s
[j
++]=" local w = debug.getinfo(2, \"S\").what\n";
473 s
[j
++]=" if w ~= \"main\" and w ~= \"C\" then\n";
474 s
[j
++]=" error(\"Script attempted to create global variable '\"..tostring(n)..\"'\", 2)\n";
477 s
[j
++]=" rawset(t, n, v)\n";
479 s
[j
++]="mt.__index = function (t, n)\n";
480 s
[j
++]=" if debug.getinfo(2) and debug.getinfo(2, \"S\").what ~= \"C\" then\n";
481 s
[j
++]=" error(\"Script attempted to access unexisting global variable '\"..tostring(n)..\"'\", 2)\n";
483 s
[j
++]=" return rawget(t, n)\n";
487 for (j
= 0; s
[j
] != NULL
; j
++) code
= sdscatlen(code
,s
[j
],strlen(s
[j
]));
488 luaL_loadbuffer(lua
,code
,sdslen(code
),"@enable_strict_lua");
489 lua_pcall(lua
,0,0,0);
493 /* Initialize the scripting environment.
494 * It is possible to call this function to reset the scripting environment
495 * assuming that we call scriptingRelease() before.
496 * See scriptingReset() for more information. */
497 void scriptingInit(void) {
498 lua_State
*lua
= lua_open();
500 luaLoadLibraries(lua
);
501 luaRemoveUnsupportedFunctions(lua
);
503 /* Initialize a dictionary we use to map SHAs to scripts.
504 * This is useful for replication, as we need to replicate EVALSHA
505 * as EVAL, so we need to remember the associated script. */
506 server
.lua_scripts
= dictCreate(&dbDictType
,NULL
);
508 /* Register the redis commands table and fields */
512 lua_pushstring(lua
,"call");
513 lua_pushcfunction(lua
,luaRedisCallCommand
);
514 lua_settable(lua
,-3);
517 lua_pushstring(lua
,"pcall");
518 lua_pushcfunction(lua
,luaRedisPCallCommand
);
519 lua_settable(lua
,-3);
521 /* redis.log and log levels. */
522 lua_pushstring(lua
,"log");
523 lua_pushcfunction(lua
,luaLogCommand
);
524 lua_settable(lua
,-3);
526 lua_pushstring(lua
,"LOG_DEBUG");
527 lua_pushnumber(lua
,REDIS_DEBUG
);
528 lua_settable(lua
,-3);
530 lua_pushstring(lua
,"LOG_VERBOSE");
531 lua_pushnumber(lua
,REDIS_VERBOSE
);
532 lua_settable(lua
,-3);
534 lua_pushstring(lua
,"LOG_NOTICE");
535 lua_pushnumber(lua
,REDIS_NOTICE
);
536 lua_settable(lua
,-3);
538 lua_pushstring(lua
,"LOG_WARNING");
539 lua_pushnumber(lua
,REDIS_WARNING
);
540 lua_settable(lua
,-3);
543 lua_pushstring(lua
, "sha1hex");
544 lua_pushcfunction(lua
, luaRedisSha1hexCommand
);
545 lua_settable(lua
, -3);
547 /* redis.error_reply and redis.status_reply */
548 lua_pushstring(lua
, "error_reply");
549 lua_pushcfunction(lua
, luaRedisErrorReplyCommand
);
550 lua_settable(lua
, -3);
551 lua_pushstring(lua
, "status_reply");
552 lua_pushcfunction(lua
, luaRedisStatusReplyCommand
);
553 lua_settable(lua
, -3);
555 /* Finally set the table as 'redis' global var. */
556 lua_setglobal(lua
,"redis");
558 /* Replace math.random and math.randomseed with our implementations. */
559 lua_getglobal(lua
,"math");
561 lua_pushstring(lua
,"random");
562 lua_pushcfunction(lua
,redis_math_random
);
563 lua_settable(lua
,-3);
565 lua_pushstring(lua
,"randomseed");
566 lua_pushcfunction(lua
,redis_math_randomseed
);
567 lua_settable(lua
,-3);
569 lua_setglobal(lua
,"math");
571 /* Add a helper funciton that we use to sort the multi bulk output of non
572 * deterministic commands, when containing 'false' elements. */
574 char *compare_func
= "function __redis__compare_helper(a,b)\n"
575 " if a == false then a = '' end\n"
576 " if b == false then b = '' end\n"
579 luaL_loadbuffer(lua
,compare_func
,strlen(compare_func
),"@cmp_func_def");
580 lua_pcall(lua
,0,0,0);
583 /* Create the (non connected) client that we use to execute Redis commands
584 * inside the Lua interpreter.
585 * Note: there is no need to create it again when this function is called
586 * by scriptingReset(). */
587 if (server
.lua_client
== NULL
) {
588 server
.lua_client
= createClient(-1);
589 server
.lua_client
->flags
|= REDIS_LUA_CLIENT
;
592 /* Lua beginners ofter don't use "local", this is likely to introduce
593 * subtle bugs in their code. To prevent problems we protect accesses
594 * to global variables. */
595 scriptingEnableGlobalsProtection(lua
);
600 /* Release resources related to Lua scripting.
601 * This function is used in order to reset the scripting environment. */
602 void scriptingRelease(void) {
603 dictRelease(server
.lua_scripts
);
604 lua_close(server
.lua
);
607 void scriptingReset(void) {
612 /* Perform the SHA1 of the input string. We use this both for hasing script
613 * bodies in order to obtain the Lua function name, and in the implementation
616 * 'digest' should point to a 41 bytes buffer: 40 for SHA1 converted into an
617 * hexadecimal number, plus 1 byte for null term. */
618 void sha1hex(char *digest
, char *script
, size_t len
) {
620 unsigned char hash
[20];
621 char *cset
= "0123456789abcdef";
625 SHA1Update(&ctx
,(unsigned char*)script
,len
);
626 SHA1Final(hash
,&ctx
);
628 for (j
= 0; j
< 20; j
++) {
629 digest
[j
*2] = cset
[((hash
[j
]&0xF0)>>4)];
630 digest
[j
*2+1] = cset
[(hash
[j
]&0xF)];
635 void luaReplyToRedisReply(redisClient
*c
, lua_State
*lua
) {
636 int t
= lua_type(lua
,-1);
640 addReplyBulkCBuffer(c
,(char*)lua_tostring(lua
,-1),lua_strlen(lua
,-1));
643 addReply(c
,lua_toboolean(lua
,-1) ? shared
.cone
: shared
.nullbulk
);
646 addReplyLongLong(c
,(long long)lua_tonumber(lua
,-1));
649 /* We need to check if it is an array, an error, or a status reply.
650 * Error are returned as a single element table with 'err' field.
651 * Status replies are returned as single elment table with 'ok' field */
652 lua_pushstring(lua
,"err");
653 lua_gettable(lua
,-2);
654 t
= lua_type(lua
,-1);
655 if (t
== LUA_TSTRING
) {
656 sds err
= sdsnew(lua_tostring(lua
,-1));
657 sdsmapchars(err
,"\r\n"," ",2);
658 addReplySds(c
,sdscatprintf(sdsempty(),"-%s\r\n",err
));
665 lua_pushstring(lua
,"ok");
666 lua_gettable(lua
,-2);
667 t
= lua_type(lua
,-1);
668 if (t
== LUA_TSTRING
) {
669 sds ok
= sdsnew(lua_tostring(lua
,-1));
670 sdsmapchars(ok
,"\r\n"," ",2);
671 addReplySds(c
,sdscatprintf(sdsempty(),"+%s\r\n",ok
));
675 void *replylen
= addDeferredMultiBulkLength(c
);
676 int j
= 1, mbulklen
= 0;
678 lua_pop(lua
,1); /* Discard the 'ok' field value we popped */
680 lua_pushnumber(lua
,j
++);
681 lua_gettable(lua
,-2);
682 t
= lua_type(lua
,-1);
687 luaReplyToRedisReply(c
, lua
);
690 setDeferredMultiBulkLength(c
,replylen
,mbulklen
);
694 addReply(c
,shared
.nullbulk
);
699 /* Set an array of Redis String Objects as a Lua array (table) stored into a
700 * global variable. */
701 void luaSetGlobalArray(lua_State
*lua
, char *var
, robj
**elev
, int elec
) {
705 for (j
= 0; j
< elec
; j
++) {
706 lua_pushlstring(lua
,(char*)elev
[j
]->ptr
,sdslen(elev
[j
]->ptr
));
707 lua_rawseti(lua
,-2,j
+1);
709 lua_setglobal(lua
,var
);
712 /* Define a lua function with the specified function name and body.
713 * The function name musts be a 2 characters long string, since all the
714 * functions we defined in the Lua context are in the form:
718 * On success REDIS_OK is returned, and nothing is left on the Lua stack.
719 * On error REDIS_ERR is returned and an appropriate error is set in the
721 int luaCreateFunction(redisClient
*c
, lua_State
*lua
, char *funcname
, robj
*body
) {
722 sds funcdef
= sdsempty();
724 funcdef
= sdscat(funcdef
,"function ");
725 funcdef
= sdscatlen(funcdef
,funcname
,42);
726 funcdef
= sdscatlen(funcdef
,"() ",3);
727 funcdef
= sdscatlen(funcdef
,body
->ptr
,sdslen(body
->ptr
));
728 funcdef
= sdscatlen(funcdef
," end",4);
730 if (luaL_loadbuffer(lua
,funcdef
,sdslen(funcdef
),"@user_script")) {
731 addReplyErrorFormat(c
,"Error compiling script (new function): %s\n",
732 lua_tostring(lua
,-1));
738 if (lua_pcall(lua
,0,0,0)) {
739 addReplyErrorFormat(c
,"Error running script (new function): %s\n",
740 lua_tostring(lua
,-1));
745 /* We also save a SHA1 -> Original script map in a dictionary
746 * so that we can replicate / write in the AOF all the
747 * EVALSHA commands as EVAL using the original script. */
749 int retval
= dictAdd(server
.lua_scripts
,
750 sdsnewlen(funcname
+2,40),body
);
751 redisAssertWithInfo(c
,NULL
,retval
== DICT_OK
);
757 void evalGenericCommand(redisClient
*c
, int evalsha
) {
758 lua_State
*lua
= server
.lua
;
763 /* We want the same PRNG sequence at every call so that our PRNG is
764 * not affected by external state. */
767 /* We set this flag to zero to remember that so far no random command
768 * was called. This way we can allow the user to call commands like
769 * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command
770 * is called (otherwise the replication and AOF would end with non
771 * deterministic sequences).
773 * Thanks to this flag we'll raise an error every time a write command
774 * is called after a random command was used. */
775 server
.lua_random_dirty
= 0;
776 server
.lua_write_dirty
= 0;
778 /* Get the number of arguments that are keys */
779 if (getLongLongFromObjectOrReply(c
,c
->argv
[2],&numkeys
,NULL
) != REDIS_OK
)
781 if (numkeys
> (c
->argc
- 3)) {
782 addReplyError(c
,"Number of keys can't be greater than number of args");
786 /* We obtain the script SHA1, then check if this function is already
787 * defined into the Lua state */
791 /* Hash the code if this is an EVAL call */
792 sha1hex(funcname
+2,c
->argv
[1]->ptr
,sdslen(c
->argv
[1]->ptr
));
794 /* We already have the SHA if it is a EVALSHA */
796 char *sha
= c
->argv
[1]->ptr
;
798 for (j
= 0; j
< 40; j
++)
799 funcname
[j
+2] = tolower(sha
[j
]);
803 /* Try to lookup the Lua function */
804 lua_getglobal(lua
, funcname
);
805 if (lua_isnil(lua
,1)) {
806 lua_pop(lua
,1); /* remove the nil from the stack */
807 /* Function not defined... let's define it if we have the
808 * body of the funciton. If this is an EVALSHA call we can just
809 * return an error. */
811 addReply(c
, shared
.noscripterr
);
814 if (luaCreateFunction(c
,lua
,funcname
,c
->argv
[1]) == REDIS_ERR
) return;
815 /* Now the following is guaranteed to return non nil */
816 lua_getglobal(lua
, funcname
);
817 redisAssert(!lua_isnil(lua
,1));
820 /* Populate the argv and keys table accordingly to the arguments that
822 luaSetGlobalArray(lua
,"KEYS",c
->argv
+3,numkeys
);
823 luaSetGlobalArray(lua
,"ARGV",c
->argv
+3+numkeys
,c
->argc
-3-numkeys
);
825 /* Select the right DB in the context of the Lua client */
826 selectDb(server
.lua_client
,c
->db
->id
);
828 /* Set an hook in order to be able to stop the script execution if it
829 * is running for too much time.
830 * We set the hook only if the time limit is enabled as the hook will
831 * make the Lua script execution slower. */
832 server
.lua_caller
= c
;
833 server
.lua_time_start
= ustime()/1000;
835 if (server
.lua_time_limit
> 0 && server
.masterhost
== NULL
) {
836 lua_sethook(lua
,luaMaskCountHook
,LUA_MASKCOUNT
,100000);
840 /* At this point whatever this script was never seen before or if it was
841 * already defined, we can call it. We have zero arguments and expect
842 * a single return value. */
843 if (lua_pcall(lua
,0,1,0)) {
844 if (delhook
) lua_sethook(lua
,luaMaskCountHook
,0,0); /* Disable hook */
845 if (server
.lua_timedout
) {
846 server
.lua_timedout
= 0;
847 /* Restore the readable handler that was unregistered when the
848 * script timeout was detected. */
849 aeCreateFileEvent(server
.el
,c
->fd
,AE_READABLE
,
850 readQueryFromClient
,c
);
852 server
.lua_caller
= NULL
;
853 selectDb(c
,server
.lua_client
->db
->id
); /* set DB ID from Lua client */
854 addReplyErrorFormat(c
,"Error running script (call to %s): %s\n",
855 funcname
, lua_tostring(lua
,-1));
857 lua_gc(lua
,LUA_GCCOLLECT
,0);
860 if (delhook
) lua_sethook(lua
,luaMaskCountHook
,0,0); /* Disable hook */
861 server
.lua_timedout
= 0;
862 server
.lua_caller
= NULL
;
863 selectDb(c
,server
.lua_client
->db
->id
); /* set DB ID from Lua client */
864 luaReplyToRedisReply(c
,lua
);
865 lua_gc(lua
,LUA_GCSTEP
,1);
867 /* If we have slaves attached we want to replicate this command as
868 * EVAL instead of EVALSHA. We do this also in the AOF as currently there
869 * is no easy way to propagate a command in a different way in the AOF
870 * and in the replication link.
872 * IMPROVEMENT POSSIBLE:
873 * 1) Replicate this command as EVALSHA in the AOF.
874 * 2) Remember what slave already received a given script, and replicate
875 * the EVALSHA against this slaves when possible.
878 robj
*script
= dictFetchValue(server
.lua_scripts
,c
->argv
[1]->ptr
);
880 redisAssertWithInfo(c
,NULL
,script
!= NULL
);
881 rewriteClientCommandArgument(c
,0,
882 resetRefCount(createStringObject("EVAL",4)));
883 rewriteClientCommandArgument(c
,1,script
);
887 void evalCommand(redisClient
*c
) {
888 evalGenericCommand(c
,0);
891 void evalShaCommand(redisClient
*c
) {
892 if (sdslen(c
->argv
[1]->ptr
) != 40) {
893 /* We know that a match is not possible if the provided SHA is
894 * not the right length. So we return an error ASAP, this way
895 * evalGenericCommand() can be implemented without string length
897 addReply(c
, shared
.noscripterr
);
900 evalGenericCommand(c
,1);
903 /* We replace math.random() with our implementation that is not affected
904 * by specific libc random() implementations and will output the same sequence
905 * (for the same seed) in every arch. */
907 /* The following implementation is the one shipped with Lua itself but with
908 * rand() replaced by redisLrand48(). */
909 int redis_math_random (lua_State
*L
) {
910 /* the `%' avoids the (rare) case of r==1, and is needed also because on
911 some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
912 lua_Number r
= (lua_Number
)(redisLrand48()%REDIS_LRAND
48_MAX
) /
913 (lua_Number
)REDIS_LRAND48_MAX
;
914 switch (lua_gettop(L
)) { /* check number of arguments */
915 case 0: { /* no arguments */
916 lua_pushnumber(L
, r
); /* Number between 0 and 1 */
919 case 1: { /* only upper limit */
920 int u
= luaL_checkint(L
, 1);
921 luaL_argcheck(L
, 1<=u
, 1, "interval is empty");
922 lua_pushnumber(L
, floor(r
*u
)+1); /* int between 1 and `u' */
925 case 2: { /* lower and upper limits */
926 int l
= luaL_checkint(L
, 1);
927 int u
= luaL_checkint(L
, 2);
928 luaL_argcheck(L
, l
<=u
, 2, "interval is empty");
929 lua_pushnumber(L
, floor(r
*(u
-l
+1))+l
); /* int between `l' and `u' */
932 default: return luaL_error(L
, "wrong number of arguments");
937 int redis_math_randomseed (lua_State
*L
) {
938 redisSrand48(luaL_checkint(L
, 1));
942 /* ---------------------------------------------------------------------------
943 * SCRIPT command for script environment introspection and control
944 * ------------------------------------------------------------------------- */
946 void scriptCommand(redisClient
*c
) {
947 if (c
->argc
== 2 && !strcasecmp(c
->argv
[1]->ptr
,"flush")) {
949 addReply(c
,shared
.ok
);
950 server
.dirty
++; /* Replicating this command is a good idea. */
951 } else if (c
->argc
>= 2 && !strcasecmp(c
->argv
[1]->ptr
,"exists")) {
954 addReplyMultiBulkLen(c
, c
->argc
-2);
955 for (j
= 2; j
< c
->argc
; j
++) {
956 if (dictFind(server
.lua_scripts
,c
->argv
[j
]->ptr
))
957 addReply(c
,shared
.cone
);
959 addReply(c
,shared
.czero
);
961 } else if (c
->argc
== 3 && !strcasecmp(c
->argv
[1]->ptr
,"load")) {
967 sha1hex(funcname
+2,c
->argv
[2]->ptr
,sdslen(c
->argv
[2]->ptr
));
968 sha
= sdsnewlen(funcname
+2,40);
969 if (dictFind(server
.lua_scripts
,sha
) == NULL
) {
970 if (luaCreateFunction(c
,server
.lua
,funcname
,c
->argv
[2])
976 addReplyBulkCBuffer(c
,funcname
+2,40);
978 } else if (c
->argc
== 2 && !strcasecmp(c
->argv
[1]->ptr
,"kill")) {
979 if (server
.lua_caller
== NULL
) {
980 addReplySds(c
,sdsnew("-NOTBUSY No scripts in execution right now.\r\n"));
981 } else if (server
.lua_write_dirty
) {
982 addReplySds(c
,sdsnew("-UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in an hard way using the SHUTDOWN NOSAVE command.\r\n"));
985 addReply(c
,shared
.ok
);
988 addReplyError(c
, "Unknown SCRIPT subcommand or wrong # of args.");