scripting.c 42 KB

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