]> git.saurik.com Git - redis.git/commitdiff
EVALSHA implemented
authorantirez <antirez@gmail.com>
Fri, 13 May 2011 20:02:38 +0000 (22:02 +0200)
committerantirez <antirez@gmail.com>
Wed, 25 May 2011 10:32:49 +0000 (12:32 +0200)
src/redis.c
src/redis.h
src/scripting.c

index 72477356f3e0c57bbd7e230601aea777b898e055..d5470ff37f9dfd38aa77699659b69d88297c27e1 100644 (file)
@@ -194,7 +194,8 @@ struct redisCommand redisCommandTable[] = {
     {"dump",dumpCommand,2,0,NULL,0,0,0,0,0},
     {"object",objectCommand,-2,0,NULL,0,0,0,0,0},
     {"client",clientCommand,-2,0,NULL,0,0,0,0,0},
-    {"eval",evalCommand,-3,REDIS_CMD_DENYOOM,zunionInterGetKeys,0,0,0,0,0}
+    {"eval",evalCommand,-3,REDIS_CMD_DENYOOM,zunionInterGetKeys,0,0,0,0,0},
+    {"evalsha",evalShaCommand,-3,REDIS_CMD_DENYOOM,zunionInterGetKeys,0,0,0,0,0}
 };
 
 /*============================ Utility functions ============================ */
@@ -781,6 +782,8 @@ void createSharedObjects(void) {
         "-ERR source and destination objects are the same\r\n"));
     shared.outofrangeerr = createObject(REDIS_STRING,sdsnew(
         "-ERR index out of range\r\n"));
+    shared.noscripterr = createObject(REDIS_STRING,sdsnew(
+        "-NOSCRIPT No matching script. Please use EVAL.\r\n"));
     shared.loadingerr = createObject(REDIS_STRING,sdsnew(
         "-LOADING Redis is loading the dataset in memory\r\n"));
     shared.space = createObject(REDIS_STRING,sdsnew(" "));
index 50d669ae2d9caa03376178534b58f3bd188048a0..c2551eb8ac24219c26721b70cb976c222844b9a6 100644 (file)
@@ -365,7 +365,7 @@ struct sharedObjectsStruct {
     robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *cnegone, *pong, *space,
     *colon, *nullbulk, *nullmultibulk, *queued,
     *emptymultibulk, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr,
-    *outofrangeerr, *loadingerr, *plus,
+    *outofrangeerr, *noscripterr, *loadingerr, *plus,
     *select0, *select1, *select2, *select3, *select4,
     *select5, *select6, *select7, *select8, *select9,
     *messagebulk, *pmessagebulk, *subscribebulk, *unsubscribebulk, *mbulk3,
@@ -1217,6 +1217,7 @@ void dumpCommand(redisClient *c);
 void objectCommand(redisClient *c);
 void clientCommand(redisClient *c);
 void evalCommand(redisClient *c);
+void evalShaCommand(redisClient *c);
 
 #if defined(__GNUC__)
 void *calloc(size_t count, size_t size) __attribute__ ((deprecated));
index 21b3214db7d7743a7376b4d1fb3cf7b378672ad3..0b6eb616c63829ef0a90cb8d7556024810e30e2e 100644 (file)
@@ -4,6 +4,7 @@
 #include <lua.h>
 #include <lauxlib.h>
 #include <lualib.h>
+#include <ctype.h>
 
 char *redisProtocolToLuaType_Int(lua_State *lua, char *reply);
 char *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply);
@@ -320,7 +321,7 @@ void luaSetGlobalArray(lua_State *lua, char *var, robj **elev, int elec) {
     lua_setglobal(lua,var);
 }
 
-void evalCommand(redisClient *c) {
+void evalGenericCommand(redisClient *c, int evalsha) {
     lua_State *lua = server.lua;
     char funcname[43];
     long long numkeys;
@@ -337,11 +338,32 @@ void evalCommand(redisClient *c) {
      * defined into the Lua state */
     funcname[0] = 'f';
     funcname[1] = '_';
-    hashScript(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr));
+    if (!evalsha) {
+        /* Hash the code if this is an EVAL call */
+        hashScript(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr));
+    } else {
+        /* We already have the SHA if it is a EVALSHA */
+        int j;
+        char *sha = c->argv[1]->ptr;
+
+        for (j = 0; j < 40; j++)
+            funcname[j+2] = tolower(sha[j]);
+        funcname[42] = '\0';
+    }
+
     lua_getglobal(lua, funcname);
     if (lua_isnil(lua,1)) {
-        /* Function not defined... let's define it. */
-        sds funcdef = sdsempty();
+        sds funcdef;
+      
+        /* Function not defined... let's define it if we have the
+         * body of the funciton. If this is an EVALSHA call we can just
+         * return an error. */
+        if (evalsha) {
+            addReply(c, shared.noscripterr);
+            lua_pop(lua,1); /* remove the nil from the stack */
+            return;
+        }
+        funcdef = sdsempty();
 
         lua_pop(lua,1); /* remove the nil from the stack */
         funcdef = sdscat(funcdef,"function ");
@@ -402,3 +424,19 @@ void evalCommand(redisClient *c) {
     luaReplyToRedisReply(c,lua);
     lua_gc(lua,LUA_GCSTEP,1);
 }
+
+void evalCommand(redisClient *c) {
+    evalGenericCommand(c,0);
+}
+
+void evalShaCommand(redisClient *c) {
+    if (sdslen(c->argv[1]->ptr) != 40) {
+        /* We know that a match is not possible if the provided SHA is
+         * not the right length. So we return an error ASAP, this way
+         * evalGenericCommand() can be implemented without string length
+         * sanity check */
+        addReply(c, shared.noscripterr);
+        return;
+    }
+    evalGenericCommand(c,1);
+}