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