]> git.saurik.com Git - redis.git/blame_incremental - src/scripting.c
Update makefile dependencies.
[redis.git] / src / scripting.c
... / ...
CommitLineData
1#include "redis.h"
2#include "sha1.h"
3#include "rand.h"
4
5#include <lua.h>
6#include <lauxlib.h>
7#include <lualib.h>
8#include <ctype.h>
9#include <math.h>
10
11char *redisProtocolToLuaType_Int(lua_State *lua, char *reply);
12char *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply);
13char *redisProtocolToLuaType_Status(lua_State *lua, char *reply);
14char *redisProtocolToLuaType_Error(lua_State *lua, char *reply);
15char *redisProtocolToLuaType_MultiBulk(lua_State *lua, char *reply);
16int redis_math_random (lua_State *L);
17int redis_math_randomseed (lua_State *L);
18void sha1hex(char *digest, char *script, size_t len);
19
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.
23 *
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.
29 *
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.
34 *
35 * Errors are returned as a table with a single 'err' field set to the
36 * error string.
37 */
38
39char *redisProtocolToLuaType(lua_State *lua, char* reply) {
40 char *p = reply;
41
42 switch(*p) {
43 case ':':
44 p = redisProtocolToLuaType_Int(lua,reply);
45 break;
46 case '$':
47 p = redisProtocolToLuaType_Bulk(lua,reply);
48 break;
49 case '+':
50 p = redisProtocolToLuaType_Status(lua,reply);
51 break;
52 case '-':
53 p = redisProtocolToLuaType_Error(lua,reply);
54 break;
55 case '*':
56 p = redisProtocolToLuaType_MultiBulk(lua,reply);
57 break;
58 }
59 return p;
60}
61
62char *redisProtocolToLuaType_Int(lua_State *lua, char *reply) {
63 char *p = strchr(reply+1,'\r');
64 long long value;
65
66 string2ll(reply+1,p-reply-1,&value);
67 lua_pushnumber(lua,(lua_Number)value);
68 return p+2;
69}
70
71char *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply) {
72 char *p = strchr(reply+1,'\r');
73 long long bulklen;
74
75 string2ll(reply+1,p-reply-1,&bulklen);
76 if (bulklen == -1) {
77 lua_pushboolean(lua,0);
78 return p+2;
79 } else {
80 lua_pushlstring(lua,p+2,bulklen);
81 return p+2+bulklen+2;
82 }
83}
84
85char *redisProtocolToLuaType_Status(lua_State *lua, char *reply) {
86 char *p = strchr(reply+1,'\r');
87
88 lua_newtable(lua);
89 lua_pushstring(lua,"ok");
90 lua_pushlstring(lua,reply+1,p-reply-1);
91 lua_settable(lua,-3);
92 return p+2;
93}
94
95char *redisProtocolToLuaType_Error(lua_State *lua, char *reply) {
96 char *p = strchr(reply+1,'\r');
97
98 lua_newtable(lua);
99 lua_pushstring(lua,"err");
100 lua_pushlstring(lua,reply+1,p-reply-1);
101 lua_settable(lua,-3);
102 return p+2;
103}
104
105char *redisProtocolToLuaType_MultiBulk(lua_State *lua, char *reply) {
106 char *p = strchr(reply+1,'\r');
107 long long mbulklen;
108 int j = 0;
109
110 string2ll(reply+1,p-reply-1,&mbulklen);
111 p += 2;
112 if (mbulklen == -1) {
113 lua_pushboolean(lua,0);
114 return p;
115 }
116 lua_newtable(lua);
117 for (j = 0; j < mbulklen; j++) {
118 lua_pushnumber(lua,j+1);
119 p = redisProtocolToLuaType(lua,p);
120 lua_settable(lua,-3);
121 }
122 return p;
123}
124
125void luaPushError(lua_State *lua, char *error) {
126 lua_newtable(lua);
127 lua_pushstring(lua,"err");
128 lua_pushstring(lua, error);
129 lua_settable(lua,-3);
130}
131
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).
135 *
136 * The array is sorted using table.sort itself, and assuming all the
137 * list elements are strings. */
138void 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 */
146
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 */
157 lua_call(lua,2,0);
158 }
159 /* Stack: array (sorted), table */
160 lua_pop(lua,1); /* Stack: array (sorted) */
161}
162
163int luaRedisGenericCommand(lua_State *lua, int raise_error) {
164 int j, argc = lua_gettop(lua);
165 struct redisCommand *cmd;
166 robj **argv;
167 redisClient *c = server.lua_client;
168 sds reply;
169
170 /* Build the arguments vector */
171 argv = zmalloc(sizeof(robj*)*argc);
172 for (j = 0; j < argc; j++) {
173 if (!lua_isstring(lua,j+1)) break;
174 argv[j] = createStringObject((char*)lua_tostring(lua,j+1),
175 lua_strlen(lua,j+1));
176 }
177
178 /* Check if one of the arguments passed by the Lua script
179 * is not a string or an integer (lua_isstring() return true for
180 * integers as well). */
181 if (j != argc) {
182 j--;
183 while (j >= 0) {
184 decrRefCount(argv[j]);
185 j--;
186 }
187 zfree(argv);
188 luaPushError(lua,
189 "Lua redis() command arguments must be strings or integers");
190 return 1;
191 }
192
193 /* Setup our fake client for command execution */
194 c->argv = argv;
195 c->argc = argc;
196
197 /* Command lookup */
198 cmd = lookupCommand(argv[0]->ptr);
199 if (!cmd || ((cmd->arity > 0 && cmd->arity != argc) ||
200 (argc < -cmd->arity)))
201 {
202 if (cmd)
203 luaPushError(lua,
204 "Wrong number of args calling Redis command From Lua script");
205 else
206 luaPushError(lua,"Unknown Redis command called from Lua script");
207 goto cleanup;
208 }
209
210 /* There are commands that are not allowed inside scripts. */
211 if (cmd->flags & REDIS_CMD_NOSCRIPT) {
212 luaPushError(lua, "This Redis command is not allowed from scripts");
213 goto cleanup;
214 }
215
216 /* Write commands are forbidden against read-only slaves, or if a
217 * command marked as non-deterministic was already called in the context
218 * of this script. */
219 if (cmd->flags & REDIS_CMD_WRITE) {
220 if (server.lua_random_dirty) {
221 luaPushError(lua,
222 "Write commands not allowed after non deterministic commands");
223 goto cleanup;
224 } else if (server.masterhost && server.repl_slave_ro &&
225 !(server.lua_caller->flags & REDIS_MASTER))
226 {
227 luaPushError(lua, shared.roslaveerr->ptr);
228 goto cleanup;
229 } else if (server.stop_writes_on_bgsave_err &&
230 server.saveparamslen > 0 &&
231 server.lastbgsave_status == REDIS_ERR)
232 {
233 luaPushError(lua, shared.bgsaveerr->ptr);
234 goto cleanup;
235 }
236 }
237
238 /* If we reached the memory limit configured via maxmemory, commands that
239 * could enlarge the memory usage are not allowed, but only if this is the
240 * first write in the context of this script, otherwise we can't stop
241 * in the middle. */
242 if (server.maxmemory && server.lua_write_dirty == 0 &&
243 (cmd->flags & REDIS_CMD_DENYOOM))
244 {
245 if (freeMemoryIfNeeded() == REDIS_ERR) {
246 luaPushError(lua, shared.oomerr->ptr);
247 goto cleanup;
248 }
249 }
250
251 if (cmd->flags & REDIS_CMD_RANDOM) server.lua_random_dirty = 1;
252 if (cmd->flags & REDIS_CMD_WRITE) server.lua_write_dirty = 1;
253
254 /* Run the command */
255 c->cmd = cmd;
256 call(c,REDIS_CALL_SLOWLOG | REDIS_CALL_STATS);
257
258 /* Convert the result of the Redis command into a suitable Lua type.
259 * The first thing we need is to create a single string from the client
260 * output buffers. */
261 reply = sdsempty();
262 if (c->bufpos) {
263 reply = sdscatlen(reply,c->buf,c->bufpos);
264 c->bufpos = 0;
265 }
266 while(listLength(c->reply)) {
267 robj *o = listNodeValue(listFirst(c->reply));
268
269 reply = sdscatlen(reply,o->ptr,sdslen(o->ptr));
270 listDelNode(c->reply,listFirst(c->reply));
271 }
272 if (raise_error && reply[0] != '-') raise_error = 0;
273 redisProtocolToLuaType(lua,reply);
274 /* Sort the output array if needed, assuming it is a non-null multi bulk
275 * reply as expected. */
276 if ((cmd->flags & REDIS_CMD_SORT_FOR_SCRIPT) &&
277 (reply[0] == '*' && reply[1] != '-')) {
278 /* Skip this step if command is SORT but output was already sorted */
279 if (cmd->proc != sortCommand || server.sort_dontsort)
280 luaSortArray(lua);
281 }
282 sdsfree(reply);
283
284cleanup:
285 /* Clean up. Command code may have changed argv/argc so we use the
286 * argv/argc of the client instead of the local variables. */
287 for (j = 0; j < c->argc; j++)
288 decrRefCount(c->argv[j]);
289 zfree(c->argv);
290
291 if (raise_error) {
292 /* If we are here we should have an error in the stack, in the
293 * form of a table with an "err" field. Extract the string to
294 * return the plain error. */
295 lua_pushstring(lua,"err");
296 lua_gettable(lua,-2);
297 return lua_error(lua);
298 }
299 return 1;
300}
301
302int luaRedisCallCommand(lua_State *lua) {
303 return luaRedisGenericCommand(lua,1);
304}
305
306int luaRedisPCallCommand(lua_State *lua) {
307 return luaRedisGenericCommand(lua,0);
308}
309
310/* This adds redis.sha1hex(string) to Lua scripts using the same hashing
311 * function used for sha1ing lua scripts. */
312int luaRedisSha1hexCommand(lua_State *lua) {
313 int argc = lua_gettop(lua);
314 char digest[41];
315 size_t len;
316 char *s;
317
318 if (argc != 1) {
319 luaPushError(lua, "wrong number of arguments");
320 return 1;
321 }
322
323 s = (char*)lua_tolstring(lua,1,&len);
324 sha1hex(digest,s,len);
325 lua_pushstring(lua,digest);
326 return 1;
327}
328
329int luaLogCommand(lua_State *lua) {
330 int j, argc = lua_gettop(lua);
331 int level;
332 sds log;
333
334 if (argc < 2) {
335 luaPushError(lua, "redis.log() requires two arguments or more.");
336 return 1;
337 } else if (!lua_isnumber(lua,-argc)) {
338 luaPushError(lua, "First argument must be a number (log level).");
339 return 1;
340 }
341 level = lua_tonumber(lua,-argc);
342 if (level < REDIS_DEBUG || level > REDIS_WARNING) {
343 luaPushError(lua, "Invalid debug level.");
344 return 1;
345 }
346
347 /* Glue together all the arguments */
348 log = sdsempty();
349 for (j = 1; j < argc; j++) {
350 size_t len;
351 char *s;
352
353 s = (char*)lua_tolstring(lua,(-argc)+j,&len);
354 if (s) {
355 if (j != 1) log = sdscatlen(log," ",1);
356 log = sdscatlen(log,s,len);
357 }
358 }
359 redisLogRaw(level,log);
360 sdsfree(log);
361 return 0;
362}
363
364void luaMaskCountHook(lua_State *lua, lua_Debug *ar) {
365 long long elapsed;
366 REDIS_NOTUSED(ar);
367 REDIS_NOTUSED(lua);
368
369 elapsed = (ustime()/1000) - server.lua_time_start;
370 if (elapsed >= server.lua_time_limit && server.lua_timedout == 0) {
371 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);
372 server.lua_timedout = 1;
373 /* Once the script timeouts we reenter the event loop to permit others
374 * to call SCRIPT KILL or SHUTDOWN NOSAVE if needed. For this reason
375 * we need to mask the client executing the script from the event loop.
376 * If we don't do that the client may disconnect and could no longer be
377 * here when the EVAL command will return. */
378 aeDeleteFileEvent(server.el, server.lua_caller->fd, AE_READABLE);
379 }
380 if (server.lua_timedout)
381 aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT);
382 if (server.lua_kill) {
383 redisLog(REDIS_WARNING,"Lua script killed by user with SCRIPT KILL.");
384 lua_pushstring(lua,"Script killed by user with SCRIPT KILL...");
385 lua_error(lua);
386 }
387}
388
389void luaLoadLib(lua_State *lua, const char *libname, lua_CFunction luafunc) {
390 lua_pushcfunction(lua, luafunc);
391 lua_pushstring(lua, libname);
392 lua_call(lua, 1, 0);
393}
394
395LUALIB_API int (luaopen_cjson) (lua_State *L);
396LUALIB_API int (luaopen_struct) (lua_State *L);
397LUALIB_API int (luaopen_cmsgpack) (lua_State *L);
398
399void luaLoadLibraries(lua_State *lua) {
400 luaLoadLib(lua, "", luaopen_base);
401 luaLoadLib(lua, LUA_TABLIBNAME, luaopen_table);
402 luaLoadLib(lua, LUA_STRLIBNAME, luaopen_string);
403 luaLoadLib(lua, LUA_MATHLIBNAME, luaopen_math);
404 luaLoadLib(lua, LUA_DBLIBNAME, luaopen_debug);
405 luaLoadLib(lua, "cjson", luaopen_cjson);
406 luaLoadLib(lua, "struct", luaopen_struct);
407 luaLoadLib(lua, "cmsgpack", luaopen_cmsgpack);
408
409#if 0 /* Stuff that we don't load currently, for sandboxing concerns. */
410 luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);
411 luaLoadLib(lua, LUA_OSLIBNAME, luaopen_os);
412#endif
413}
414
415/* Remove a functions that we don't want to expose to the Redis scripting
416 * environment. */
417void luaRemoveUnsupportedFunctions(lua_State *lua) {
418 lua_pushnil(lua);
419 lua_setglobal(lua,"loadfile");
420}
421
422/* This function installs metamethods in the global table _G that prevent
423 * the creation of globals accidentally.
424 *
425 * It should be the last to be called in the scripting engine initialization
426 * sequence, because it may interact with creation of globals. */
427void scriptingEnableGlobalsProtection(lua_State *lua) {
428 char *s[32];
429 sds code = sdsempty();
430 int j = 0;
431
432 /* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.
433 * Modified to be adapted to Redis. */
434 s[j++]="local mt = {}\n";
435 s[j++]="setmetatable(_G, mt)\n";
436 s[j++]="mt.__newindex = function (t, n, v)\n";
437 s[j++]=" if debug.getinfo(2) then\n";
438 s[j++]=" local w = debug.getinfo(2, \"S\").what\n";
439 s[j++]=" if w ~= \"main\" and w ~= \"C\" then\n";
440 s[j++]=" error(\"Script attempted to create global variable '\"..tostring(n)..\"'\", 2)\n";
441 s[j++]=" end\n";
442 s[j++]=" end\n";
443 s[j++]=" rawset(t, n, v)\n";
444 s[j++]="end\n";
445 s[j++]="mt.__index = function (t, n)\n";
446 s[j++]=" if debug.getinfo(2) and debug.getinfo(2, \"S\").what ~= \"C\" then\n";
447 s[j++]=" error(\"Script attempted to access unexisting global variable '\"..tostring(n)..\"'\", 2)\n";
448 s[j++]=" end\n";
449 s[j++]=" return rawget(t, n)\n";
450 s[j++]="end\n";
451 s[j++]=NULL;
452
453 for (j = 0; s[j] != NULL; j++) code = sdscatlen(code,s[j],strlen(s[j]));
454 luaL_loadbuffer(lua,code,sdslen(code),"@enable_strict_lua");
455 lua_pcall(lua,0,0,0);
456 sdsfree(code);
457}
458
459/* Initialize the scripting environment.
460 * It is possible to call this function to reset the scripting environment
461 * assuming that we call scriptingRelease() before.
462 * See scriptingReset() for more information. */
463void scriptingInit(void) {
464 lua_State *lua = lua_open();
465
466 luaLoadLibraries(lua);
467 luaRemoveUnsupportedFunctions(lua);
468
469 /* Initialize a dictionary we use to map SHAs to scripts.
470 * This is useful for replication, as we need to replicate EVALSHA
471 * as EVAL, so we need to remember the associated script. */
472 server.lua_scripts = dictCreate(&dbDictType,NULL);
473
474 /* Register the redis commands table and fields */
475 lua_newtable(lua);
476
477 /* redis.call */
478 lua_pushstring(lua,"call");
479 lua_pushcfunction(lua,luaRedisCallCommand);
480 lua_settable(lua,-3);
481
482 /* redis.pcall */
483 lua_pushstring(lua,"pcall");
484 lua_pushcfunction(lua,luaRedisPCallCommand);
485 lua_settable(lua,-3);
486
487 /* redis.log and log levels. */
488 lua_pushstring(lua,"log");
489 lua_pushcfunction(lua,luaLogCommand);
490 lua_settable(lua,-3);
491
492 lua_pushstring(lua,"LOG_DEBUG");
493 lua_pushnumber(lua,REDIS_DEBUG);
494 lua_settable(lua,-3);
495
496 lua_pushstring(lua,"LOG_VERBOSE");
497 lua_pushnumber(lua,REDIS_VERBOSE);
498 lua_settable(lua,-3);
499
500 lua_pushstring(lua,"LOG_NOTICE");
501 lua_pushnumber(lua,REDIS_NOTICE);
502 lua_settable(lua,-3);
503
504 lua_pushstring(lua,"LOG_WARNING");
505 lua_pushnumber(lua,REDIS_WARNING);
506 lua_settable(lua,-3);
507
508 /* redis.sha1hex */
509 lua_pushstring(lua, "sha1hex");
510 lua_pushcfunction(lua, luaRedisSha1hexCommand);
511 lua_settable(lua, -3);
512
513 /* Finally set the table as 'redis' global var. */
514 lua_setglobal(lua,"redis");
515
516 /* Replace math.random and math.randomseed with our implementations. */
517 lua_getglobal(lua,"math");
518
519 lua_pushstring(lua,"random");
520 lua_pushcfunction(lua,redis_math_random);
521 lua_settable(lua,-3);
522
523 lua_pushstring(lua,"randomseed");
524 lua_pushcfunction(lua,redis_math_randomseed);
525 lua_settable(lua,-3);
526
527 lua_setglobal(lua,"math");
528
529 /* Add a helper funciton that we use to sort the multi bulk output of non
530 * deterministic commands, when containing 'false' elements. */
531 {
532 char *compare_func = "function __redis__compare_helper(a,b)\n"
533 " if a == false then a = '' end\n"
534 " if b == false then b = '' end\n"
535 " return a<b\n"
536 "end\n";
537 luaL_loadbuffer(lua,compare_func,strlen(compare_func),"@cmp_func_def");
538 lua_pcall(lua,0,0,0);
539 }
540
541 /* Create the (non connected) client that we use to execute Redis commands
542 * inside the Lua interpreter.
543 * Note: there is no need to create it again when this function is called
544 * by scriptingReset(). */
545 if (server.lua_client == NULL) {
546 server.lua_client = createClient(-1);
547 server.lua_client->flags |= REDIS_LUA_CLIENT;
548 }
549
550 /* Lua beginners ofter don't use "local", this is likely to introduce
551 * subtle bugs in their code. To prevent problems we protect accesses
552 * to global variables. */
553 scriptingEnableGlobalsProtection(lua);
554
555 server.lua = lua;
556}
557
558/* Release resources related to Lua scripting.
559 * This function is used in order to reset the scripting environment. */
560void scriptingRelease(void) {
561 dictRelease(server.lua_scripts);
562 lua_close(server.lua);
563}
564
565void scriptingReset(void) {
566 scriptingRelease();
567 scriptingInit();
568}
569
570/* Perform the SHA1 of the input string. We use this both for hasing script
571 * bodies in order to obtain the Lua function name, and in the implementation
572 * of redis.sha1().
573 *
574 * 'digest' should point to a 41 bytes buffer: 40 for SHA1 converted into an
575 * hexadecimal number, plus 1 byte for null term. */
576void sha1hex(char *digest, char *script, size_t len) {
577 SHA1_CTX ctx;
578 unsigned char hash[20];
579 char *cset = "0123456789abcdef";
580 int j;
581
582 SHA1Init(&ctx);
583 SHA1Update(&ctx,(unsigned char*)script,len);
584 SHA1Final(hash,&ctx);
585
586 for (j = 0; j < 20; j++) {
587 digest[j*2] = cset[((hash[j]&0xF0)>>4)];
588 digest[j*2+1] = cset[(hash[j]&0xF)];
589 }
590 digest[40] = '\0';
591}
592
593void luaReplyToRedisReply(redisClient *c, lua_State *lua) {
594 int t = lua_type(lua,-1);
595
596 switch(t) {
597 case LUA_TSTRING:
598 addReplyBulkCBuffer(c,(char*)lua_tostring(lua,-1),lua_strlen(lua,-1));
599 break;
600 case LUA_TBOOLEAN:
601 addReply(c,lua_toboolean(lua,-1) ? shared.cone : shared.nullbulk);
602 break;
603 case LUA_TNUMBER:
604 addReplyLongLong(c,(long long)lua_tonumber(lua,-1));
605 break;
606 case LUA_TTABLE:
607 /* We need to check if it is an array, an error, or a status reply.
608 * Error are returned as a single element table with 'err' field.
609 * Status replies are returned as single elment table with 'ok' field */
610 lua_pushstring(lua,"err");
611 lua_gettable(lua,-2);
612 t = lua_type(lua,-1);
613 if (t == LUA_TSTRING) {
614 sds err = sdsnew(lua_tostring(lua,-1));
615 sdsmapchars(err,"\r\n"," ",2);
616 addReplySds(c,sdscatprintf(sdsempty(),"-%s\r\n",err));
617 sdsfree(err);
618 lua_pop(lua,2);
619 return;
620 }
621
622 lua_pop(lua,1);
623 lua_pushstring(lua,"ok");
624 lua_gettable(lua,-2);
625 t = lua_type(lua,-1);
626 if (t == LUA_TSTRING) {
627 sds ok = sdsnew(lua_tostring(lua,-1));
628 sdsmapchars(ok,"\r\n"," ",2);
629 addReplySds(c,sdscatprintf(sdsempty(),"+%s\r\n",ok));
630 sdsfree(ok);
631 lua_pop(lua,1);
632 } else {
633 void *replylen = addDeferredMultiBulkLength(c);
634 int j = 1, mbulklen = 0;
635
636 lua_pop(lua,1); /* Discard the 'ok' field value we popped */
637 while(1) {
638 lua_pushnumber(lua,j++);
639 lua_gettable(lua,-2);
640 t = lua_type(lua,-1);
641 if (t == LUA_TNIL) {
642 lua_pop(lua,1);
643 break;
644 }
645 luaReplyToRedisReply(c, lua);
646 mbulklen++;
647 }
648 setDeferredMultiBulkLength(c,replylen,mbulklen);
649 }
650 break;
651 default:
652 addReply(c,shared.nullbulk);
653 }
654 lua_pop(lua,1);
655}
656
657/* Set an array of Redis String Objects as a Lua array (table) stored into a
658 * global variable. */
659void luaSetGlobalArray(lua_State *lua, char *var, robj **elev, int elec) {
660 int j;
661
662 lua_newtable(lua);
663 for (j = 0; j < elec; j++) {
664 lua_pushlstring(lua,(char*)elev[j]->ptr,sdslen(elev[j]->ptr));
665 lua_rawseti(lua,-2,j+1);
666 }
667 lua_setglobal(lua,var);
668}
669
670/* Define a lua function with the specified function name and body.
671 * The function name musts be a 2 characters long string, since all the
672 * functions we defined in the Lua context are in the form:
673 *
674 * f_<hex sha1 sum>
675 *
676 * On success REDIS_OK is returned, and nothing is left on the Lua stack.
677 * On error REDIS_ERR is returned and an appropriate error is set in the
678 * client context. */
679int luaCreateFunction(redisClient *c, lua_State *lua, char *funcname, robj *body) {
680 sds funcdef = sdsempty();
681
682 funcdef = sdscat(funcdef,"function ");
683 funcdef = sdscatlen(funcdef,funcname,42);
684 funcdef = sdscatlen(funcdef,"() ",3);
685 funcdef = sdscatlen(funcdef,body->ptr,sdslen(body->ptr));
686 funcdef = sdscatlen(funcdef," end",4);
687
688 if (luaL_loadbuffer(lua,funcdef,sdslen(funcdef),"@user_script")) {
689 addReplyErrorFormat(c,"Error compiling script (new function): %s\n",
690 lua_tostring(lua,-1));
691 lua_pop(lua,1);
692 sdsfree(funcdef);
693 return REDIS_ERR;
694 }
695 sdsfree(funcdef);
696 if (lua_pcall(lua,0,0,0)) {
697 addReplyErrorFormat(c,"Error running script (new function): %s\n",
698 lua_tostring(lua,-1));
699 lua_pop(lua,1);
700 return REDIS_ERR;
701 }
702
703 /* We also save a SHA1 -> Original script map in a dictionary
704 * so that we can replicate / write in the AOF all the
705 * EVALSHA commands as EVAL using the original script. */
706 {
707 int retval = dictAdd(server.lua_scripts,
708 sdsnewlen(funcname+2,40),body);
709 redisAssertWithInfo(c,NULL,retval == DICT_OK);
710 incrRefCount(body);
711 }
712 return REDIS_OK;
713}
714
715void evalGenericCommand(redisClient *c, int evalsha) {
716 lua_State *lua = server.lua;
717 char funcname[43];
718 long long numkeys;
719 int delhook = 0;
720
721 /* We want the same PRNG sequence at every call so that our PRNG is
722 * not affected by external state. */
723 redisSrand48(0);
724
725 /* We set this flag to zero to remember that so far no random command
726 * was called. This way we can allow the user to call commands like
727 * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command
728 * is called (otherwise the replication and AOF would end with non
729 * deterministic sequences).
730 *
731 * Thanks to this flag we'll raise an error every time a write command
732 * is called after a random command was used. */
733 server.lua_random_dirty = 0;
734 server.lua_write_dirty = 0;
735
736 /* Get the number of arguments that are keys */
737 if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK)
738 return;
739 if (numkeys > (c->argc - 3)) {
740 addReplyError(c,"Number of keys can't be greater than number of args");
741 return;
742 }
743
744 /* We obtain the script SHA1, then check if this function is already
745 * defined into the Lua state */
746 funcname[0] = 'f';
747 funcname[1] = '_';
748 if (!evalsha) {
749 /* Hash the code if this is an EVAL call */
750 sha1hex(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr));
751 } else {
752 /* We already have the SHA if it is a EVALSHA */
753 int j;
754 char *sha = c->argv[1]->ptr;
755
756 for (j = 0; j < 40; j++)
757 funcname[j+2] = tolower(sha[j]);
758 funcname[42] = '\0';
759 }
760
761 /* Try to lookup the Lua function */
762 lua_getglobal(lua, funcname);
763 if (lua_isnil(lua,1)) {
764 lua_pop(lua,1); /* remove the nil from the stack */
765 /* Function not defined... let's define it if we have the
766 * body of the funciton. If this is an EVALSHA call we can just
767 * return an error. */
768 if (evalsha) {
769 addReply(c, shared.noscripterr);
770 return;
771 }
772 if (luaCreateFunction(c,lua,funcname,c->argv[1]) == REDIS_ERR) return;
773 /* Now the following is guaranteed to return non nil */
774 lua_getglobal(lua, funcname);
775 redisAssert(!lua_isnil(lua,1));
776 }
777
778 /* Populate the argv and keys table accordingly to the arguments that
779 * EVAL received. */
780 luaSetGlobalArray(lua,"KEYS",c->argv+3,numkeys);
781 luaSetGlobalArray(lua,"ARGV",c->argv+3+numkeys,c->argc-3-numkeys);
782
783 /* Select the right DB in the context of the Lua client */
784 selectDb(server.lua_client,c->db->id);
785
786 /* Set an hook in order to be able to stop the script execution if it
787 * is running for too much time.
788 * We set the hook only if the time limit is enabled as the hook will
789 * make the Lua script execution slower. */
790 server.lua_caller = c;
791 server.lua_time_start = ustime()/1000;
792 server.lua_kill = 0;
793 if (server.lua_time_limit > 0 && server.masterhost == NULL) {
794 lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000);
795 delhook = 1;
796 }
797
798 /* At this point whatever this script was never seen before or if it was
799 * already defined, we can call it. We have zero arguments and expect
800 * a single return value. */
801 if (lua_pcall(lua,0,1,0)) {
802 if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */
803 if (server.lua_timedout) {
804 server.lua_timedout = 0;
805 /* Restore the readable handler that was unregistered when the
806 * script timeout was detected. */
807 aeCreateFileEvent(server.el,c->fd,AE_READABLE,
808 readQueryFromClient,c);
809 }
810 server.lua_caller = NULL;
811 selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */
812 addReplyErrorFormat(c,"Error running script (call to %s): %s\n",
813 funcname, lua_tostring(lua,-1));
814 lua_pop(lua,1);
815 lua_gc(lua,LUA_GCCOLLECT,0);
816 return;
817 }
818 if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */
819 server.lua_timedout = 0;
820 server.lua_caller = NULL;
821 selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */
822 luaReplyToRedisReply(c,lua);
823 lua_gc(lua,LUA_GCSTEP,1);
824
825 /* If we have slaves attached we want to replicate this command as
826 * EVAL instead of EVALSHA. We do this also in the AOF as currently there
827 * is no easy way to propagate a command in a different way in the AOF
828 * and in the replication link.
829 *
830 * IMPROVEMENT POSSIBLE:
831 * 1) Replicate this command as EVALSHA in the AOF.
832 * 2) Remember what slave already received a given script, and replicate
833 * the EVALSHA against this slaves when possible.
834 */
835 if (evalsha) {
836 robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr);
837
838 redisAssertWithInfo(c,NULL,script != NULL);
839 rewriteClientCommandArgument(c,0,
840 resetRefCount(createStringObject("EVAL",4)));
841 rewriteClientCommandArgument(c,1,script);
842 }
843}
844
845void evalCommand(redisClient *c) {
846 evalGenericCommand(c,0);
847}
848
849void evalShaCommand(redisClient *c) {
850 if (sdslen(c->argv[1]->ptr) != 40) {
851 /* We know that a match is not possible if the provided SHA is
852 * not the right length. So we return an error ASAP, this way
853 * evalGenericCommand() can be implemented without string length
854 * sanity check */
855 addReply(c, shared.noscripterr);
856 return;
857 }
858 evalGenericCommand(c,1);
859}
860
861/* We replace math.random() with our implementation that is not affected
862 * by specific libc random() implementations and will output the same sequence
863 * (for the same seed) in every arch. */
864
865/* The following implementation is the one shipped with Lua itself but with
866 * rand() replaced by redisLrand48(). */
867int redis_math_random (lua_State *L) {
868 /* the `%' avoids the (rare) case of r==1, and is needed also because on
869 some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
870 lua_Number r = (lua_Number)(redisLrand48()%REDIS_LRAND48_MAX) /
871 (lua_Number)REDIS_LRAND48_MAX;
872 switch (lua_gettop(L)) { /* check number of arguments */
873 case 0: { /* no arguments */
874 lua_pushnumber(L, r); /* Number between 0 and 1 */
875 break;
876 }
877 case 1: { /* only upper limit */
878 int u = luaL_checkint(L, 1);
879 luaL_argcheck(L, 1<=u, 1, "interval is empty");
880 lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
881 break;
882 }
883 case 2: { /* lower and upper limits */
884 int l = luaL_checkint(L, 1);
885 int u = luaL_checkint(L, 2);
886 luaL_argcheck(L, l<=u, 2, "interval is empty");
887 lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
888 break;
889 }
890 default: return luaL_error(L, "wrong number of arguments");
891 }
892 return 1;
893}
894
895int redis_math_randomseed (lua_State *L) {
896 redisSrand48(luaL_checkint(L, 1));
897 return 0;
898}
899
900/* ---------------------------------------------------------------------------
901 * SCRIPT command for script environment introspection and control
902 * ------------------------------------------------------------------------- */
903
904void scriptCommand(redisClient *c) {
905 if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"flush")) {
906 scriptingReset();
907 addReply(c,shared.ok);
908 server.dirty++; /* Replicating this command is a good idea. */
909 } else if (c->argc >= 2 && !strcasecmp(c->argv[1]->ptr,"exists")) {
910 int j;
911
912 addReplyMultiBulkLen(c, c->argc-2);
913 for (j = 2; j < c->argc; j++) {
914 if (dictFind(server.lua_scripts,c->argv[j]->ptr))
915 addReply(c,shared.cone);
916 else
917 addReply(c,shared.czero);
918 }
919 } else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr,"load")) {
920 char funcname[43];
921 sds sha;
922
923 funcname[0] = 'f';
924 funcname[1] = '_';
925 sha1hex(funcname+2,c->argv[2]->ptr,sdslen(c->argv[2]->ptr));
926 sha = sdsnewlen(funcname+2,40);
927 if (dictFind(server.lua_scripts,sha) == NULL) {
928 if (luaCreateFunction(c,server.lua,funcname,c->argv[2])
929 == REDIS_ERR) {
930 sdsfree(sha);
931 return;
932 }
933 }
934 addReplyBulkCBuffer(c,funcname+2,40);
935 sdsfree(sha);
936 } else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"kill")) {
937 if (server.lua_caller == NULL) {
938 addReplyError(c,"No scripts in execution right now.");
939 } else if (server.lua_write_dirty) {
940 addReplyError(c, "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.");
941 } else {
942 server.lua_kill = 1;
943 addReply(c,shared.ok);
944 }
945 } else {
946 addReplyError(c, "Unknown SCRIPT subcommand or wrong # of args.");
947 }
948}