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