]> git.saurik.com Git - redis.git/blobdiff - src/scripting.c
when creating not connected clients do not add them into the clients list, otherwise...
[redis.git] / src / scripting.c
index 42ba3bf95c48c58c38422cd6bd35e91e25b374f5..bde532ca6f65834a4106d8e7a3a777e88679bb89 100644 (file)
@@ -5,9 +5,69 @@
 #include <lauxlib.h>
 #include <lualib.h>
 
+int luaRedisCommand(lua_State *lua) {
+    int j, argc = lua_gettop(lua);
+    struct redisCommand *cmd;
+    robj **argv;
+    redisClient *c = server.lua_client;
+    sds reply;
+
+    argv = zmalloc(sizeof(robj*)*argc);
+    for (j = 0; j < argc; j++)
+        argv[j] = createStringObject((char*)lua_tostring(lua,j+1),lua_strlen(lua,j+1));
+
+    /* Command lookup */
+    cmd = lookupCommand(argv[0]->ptr);
+    if (!cmd) {
+        zfree(argv);
+        lua_pushnil(lua);
+        lua_pushstring(lua,"Unknown Redis command called from Lua script");
+        return 2;
+    }
+    /* Run the command in the context of a fake client */
+    c->argv = argv;
+    c->argc = argc;
+    cmd->proc(c);
+
+    /* Convert the result of the Redis command into a suitable Lua type.
+     * The first thing we need is to create a single string from the client
+     * output buffers. */
+    reply = sdsempty();
+    if (c->bufpos) {
+        reply = sdscatlen(reply,c->buf,c->bufpos);
+        c->bufpos = 0;
+    }
+    while(listLength(c->reply)) {
+        robj *o = listNodeValue(listFirst(c->reply));
+
+        sdscatlen(reply,o->ptr,sdslen(o->ptr));
+        listDelNode(c->reply,listFirst(c->reply));
+    }
+    lua_pushlstring(lua,reply,sdslen(reply));
+    sdsfree(reply);
+
+    /* Clean up. Command code may have changed argv/argc so we use the
+     * argv/argc of the client instead of the local variables. */
+    for (j = 0; j < c->argc; j++)
+        decrRefCount(c->argv[j]);
+    zfree(c->argv);
+
+    return 1;
+}
+
 void scriptingInit(void) {
     lua_State *lua = lua_open();
     luaL_openlibs(lua);
+
+    /* Register the 'r' command */
+    lua_pushcfunction(lua,luaRedisCommand);
+    lua_setglobal(lua,"r");
+
+    /* Create the (non connected) client that we use to execute Redis commands
+     * inside the Lua interpreter */
+    server.lua_client = createClient(-1);
+    server.lua_client->flags |= REDIS_LUA_CLIENT;
+
     server.lua = lua;
 }
 
@@ -76,8 +136,10 @@ void evalCommand(redisClient *c) {
             addReplyErrorFormat(c,"Error compiling script (new function): %s\n",
                 lua_tostring(lua,-1));
             lua_pop(lua,1);
+            sdsfree(funcdef);
             return;
         }
+        sdsfree(funcdef);
         if (lua_pcall(lua,0,0,0)) {
             addReplyErrorFormat(c,"Error running script (new function): %s\n",
                 lua_tostring(lua,-1));