]> git.saurik.com Git - redis.git/commitdiff
Server replies now in the new format, test-redis.tcl and redis-cli modified accordingly
authorantirez <antirez@gmail.com>
Tue, 24 Mar 2009 12:37:32 +0000 (13:37 +0100)
committerantirez <antirez@gmail.com>
Tue, 24 Mar 2009 12:37:32 +0000 (13:37 +0100)
redis-cli.c
redis.c
test-redis.tcl

index cd106684fbca6152a4fac051e4f048456d710dcd..6ced5abc55b29c414e42d696cfca294b29befa89 100644 (file)
 
 #define REDIS_CMD_INLINE 1
 #define REDIS_CMD_BULK 2
-#define REDIS_CMD_INTREPLY 4
-#define REDIS_CMD_RETCODEREPLY 8
-#define REDIS_CMD_BULKREPLY 16
-#define REDIS_CMD_MULTIBULKREPLY 32
-#define REDIS_CMD_SINGLELINEREPLY 64
 
 #define REDIS_NOTUSED(V) ((void) V)
 
@@ -60,54 +55,56 @@ struct redisCommand {
 };
 
 static struct redisCommand cmdTable[] = {
-    {"get",2,REDIS_CMD_INLINE|REDIS_CMD_BULKREPLY},
-    {"set",3,REDIS_CMD_BULK|REDIS_CMD_RETCODEREPLY},
-    {"setnx",3,REDIS_CMD_BULK|REDIS_CMD_INTREPLY},
-    {"del",2,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"exists",2,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"incr",2,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"decr",2,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"rpush",3,REDIS_CMD_BULK|REDIS_CMD_RETCODEREPLY},
-    {"lpush",3,REDIS_CMD_BULK|REDIS_CMD_RETCODEREPLY},
-    {"rpop",2,REDIS_CMD_INLINE|REDIS_CMD_BULKREPLY},
-    {"lpop",2,REDIS_CMD_INLINE|REDIS_CMD_BULKREPLY},
-    {"llen",2,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"lindex",3,REDIS_CMD_INLINE|REDIS_CMD_BULKREPLY},
-    {"lset",4,REDIS_CMD_BULK|REDIS_CMD_RETCODEREPLY},
-    {"lrange",4,REDIS_CMD_INLINE|REDIS_CMD_MULTIBULKREPLY},
-    {"ltrim",4,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"lrem",4,REDIS_CMD_BULK|REDIS_CMD_INTREPLY},
-    {"sadd",3,REDIS_CMD_BULK|REDIS_CMD_INTREPLY},
-    {"srem",3,REDIS_CMD_BULK|REDIS_CMD_INTREPLY},
-    {"sismember",3,REDIS_CMD_BULK|REDIS_CMD_INTREPLY},
-    {"scard",2,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"sinter",-2,REDIS_CMD_INLINE|REDIS_CMD_MULTIBULKREPLY},
-    {"sinterstore",-3,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"smembers",2,REDIS_CMD_INLINE|REDIS_CMD_MULTIBULKREPLY},
-    {"incrby",3,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"decrby",3,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"randomkey",1,REDIS_CMD_INLINE|REDIS_CMD_SINGLELINEREPLY},
-    {"select",2,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"move",3,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"rename",3,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"renamenx",3,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"keys",2,REDIS_CMD_INLINE|REDIS_CMD_BULKREPLY},
-    {"dbsize",1,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"ping",1,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"echo",2,REDIS_CMD_BULK|REDIS_CMD_BULKREPLY},
-    {"save",1,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"bgsave",1,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"shutdown",1,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"lastsave",1,REDIS_CMD_INLINE|REDIS_CMD_INTREPLY},
-    {"type",2,REDIS_CMD_INLINE|REDIS_CMD_SINGLELINEREPLY},
-    {"flushdb",1,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"flushall",1,REDIS_CMD_INLINE|REDIS_CMD_RETCODEREPLY},
-    {"sort",-2,REDIS_CMD_INLINE|REDIS_CMD_MULTIBULKREPLY},
-    {"info",1,REDIS_CMD_INLINE|REDIS_CMD_BULKREPLY},
-    {"mget",-2,REDIS_CMD_INLINE|REDIS_CMD_MULTIBULKREPLY},
+    {"get",2,REDIS_CMD_INLINE},
+    {"set",3,REDIS_CMD_BULK},
+    {"setnx",3,REDIS_CMD_BULK},
+    {"del",2,REDIS_CMD_INLINE},
+    {"exists",2,REDIS_CMD_INLINE},
+    {"incr",2,REDIS_CMD_INLINE},
+    {"decr",2,REDIS_CMD_INLINE},
+    {"rpush",3,REDIS_CMD_BULK},
+    {"lpush",3,REDIS_CMD_BULK},
+    {"rpop",2,REDIS_CMD_INLINE},
+    {"lpop",2,REDIS_CMD_INLINE},
+    {"llen",2,REDIS_CMD_INLINE},
+    {"lindex",3,REDIS_CMD_INLINE},
+    {"lset",4,REDIS_CMD_BULK},
+    {"lrange",4,REDIS_CMD_INLINE},
+    {"ltrim",4,REDIS_CMD_INLINE},
+    {"lrem",4,REDIS_CMD_BULK},
+    {"sadd",3,REDIS_CMD_BULK},
+    {"srem",3,REDIS_CMD_BULK},
+    {"sismember",3,REDIS_CMD_BULK},
+    {"scard",2,REDIS_CMD_INLINE},
+    {"sinter",-2,REDIS_CMD_INLINE},
+    {"sinterstore",-3,REDIS_CMD_INLINE},
+    {"smembers",2,REDIS_CMD_INLINE},
+    {"incrby",3,REDIS_CMD_INLINE},
+    {"decrby",3,REDIS_CMD_INLINE},
+    {"randomkey",1,REDIS_CMD_INLINE},
+    {"select",2,REDIS_CMD_INLINE},
+    {"move",3,REDIS_CMD_INLINE},
+    {"rename",3,REDIS_CMD_INLINE},
+    {"renamenx",3,REDIS_CMD_INLINE},
+    {"keys",2,REDIS_CMD_INLINE},
+    {"dbsize",1,REDIS_CMD_INLINE},
+    {"ping",1,REDIS_CMD_INLINE},
+    {"echo",2,REDIS_CMD_BULK},
+    {"save",1,REDIS_CMD_INLINE},
+    {"bgsave",1,REDIS_CMD_INLINE},
+    {"shutdown",1,REDIS_CMD_INLINE},
+    {"lastsave",1,REDIS_CMD_INLINE},
+    {"type",2,REDIS_CMD_INLINE},
+    {"flushdb",1,REDIS_CMD_INLINE},
+    {"flushall",1,REDIS_CMD_INLINE},
+    {"sort",-2,REDIS_CMD_INLINE},
+    {"info",1,REDIS_CMD_INLINE},
+    {"mget",-2,REDIS_CMD_INLINE},
     {NULL,0,0}
 };
 
+static int cliReadReply(int fd);
+
 static struct redisCommand *lookupCommand(char *name) {
     int j = 0;
     while(cmdTable[j].name != NULL) {
@@ -150,38 +147,26 @@ static sds cliReadLine(int fd) {
     return sdstrim(line,"\r\n");
 }
 
-static int cliReadInlineReply(int fd, int type) {
+static int cliReadSingleLineReply(int fd) {
     sds reply = cliReadLine(fd);
 
     if (reply == NULL) return 1;
     printf("%s\n", reply);
-    if (type == REDIS_CMD_SINGLELINEREPLY) return 0;
-    if (type == REDIS_CMD_INTREPLY) return atoi(reply) < 0;
-    if (type == REDIS_CMD_RETCODEREPLY) return reply[0] == '-';
     return 0;
 }
 
-static int cliReadBulkReply(int fd, int multibulk) {
+static int cliReadBulkReply(int fd) {
     sds replylen = cliReadLine(fd);
     char *reply, crlf[2];
-    int bulklen, error = 0;
+    int bulklen;
 
     if (replylen == NULL) return 1;
-    if (strcmp(replylen,"nil") == 0) {
-        sdsfree(replylen);
-        printf("(nil)\n");
-        return 0;
-    }
     bulklen = atoi(replylen);
-    if (multibulk && bulklen == -1) {
+    if (bulklen == -1) {
         sdsfree(replylen);
         printf("(nil)");
         return 0;
     }
-    if (bulklen < 0) {
-        bulklen = -bulklen;
-        error = 1;
-    }
     reply = zmalloc(bulklen);
     anetRead(fd,reply,bulklen);
     anetRead(fd,crlf,2);
@@ -189,10 +174,10 @@ static int cliReadBulkReply(int fd, int multibulk) {
         zfree(reply);
         return 1;
     }
-    if (!multibulk && isatty(fileno(stdout)) && reply[bulklen-1] != '\n')
+    if (isatty(fileno(stdout)) && reply[bulklen-1] != '\n')
         printf("\n");
     zfree(reply);
-    return error;
+    return 0;
 }
 
 static int cliReadMultiBulkReply(int fd) {
@@ -200,21 +185,45 @@ static int cliReadMultiBulkReply(int fd) {
     int elements, c = 1;
 
     if (replylen == NULL) return 1;
-    if (strcmp(replylen,"nil") == 0) {
+    elements = atoi(replylen);
+    if (elements == -1) {
         sdsfree(replylen);
         printf("(nil)\n");
         return 0;
     }
-    elements = atoi(replylen);
+    if (elements == 0) {
+        printf("(empty list or set)\n");
+    }
     while(elements--) {
         printf("%d. ", c);
-        if (cliReadBulkReply(fd,1)) return 1;
-        printf("\n");
+        if (cliReadReply(fd)) return 1;
         c++;
     }
     return 0;
 }
 
+static int cliReadReply(int fd) {
+    char type;
+
+    if (anetRead(fd,&type,1) <= 0) exit(1);
+    switch(type) {
+    case '-':
+        printf("(error) ");
+        cliReadSingleLineReply(fd);
+        return 1;
+    case '+':
+    case ':':
+        return cliReadSingleLineReply(fd);
+    case '$':
+        return cliReadBulkReply(fd);
+    case '*':
+        return cliReadMultiBulkReply(fd);
+    default:
+        printf("protocol error, got '%c' as reply type byte\n", type);
+        return 1;
+    }
+}
+
 static int cliSendCommand(int argc, char **argv) {
     struct redisCommand *rc = lookupCommand(argv[0]);
     int fd, j, retval = 0;
@@ -247,17 +256,7 @@ static int cliSendCommand(int argc, char **argv) {
         cmd = sdscat(cmd,"\r\n");
     }
     anetWrite(fd,cmd,sdslen(cmd));
-    if (rc->flags & REDIS_CMD_INTREPLY) {
-        retval = cliReadInlineReply(fd,REDIS_CMD_INTREPLY);
-    } else if (rc->flags & REDIS_CMD_RETCODEREPLY) {
-        retval = cliReadInlineReply(fd,REDIS_CMD_RETCODEREPLY);
-    } else if (rc->flags & REDIS_CMD_SINGLELINEREPLY) {
-        retval = cliReadInlineReply(fd,REDIS_CMD_SINGLELINEREPLY);
-    } else if (rc->flags & REDIS_CMD_BULKREPLY) {
-        retval = cliReadBulkReply(fd,0);
-    } else if (rc->flags & REDIS_CMD_MULTIBULKREPLY) {
-        retval = cliReadMultiBulkReply(fd);
-    }
+    retval = cliReadReply(fd);
     if (retval) {
         close(fd);
         return retval;
diff --git a/redis.c b/redis.c
index 58b8560603bb8c63cd5caad062f1f94a48e13cea..5174b33388d711b147822a530e2798160dc88727 100644 (file)
--- a/redis.c
+++ b/redis.c
@@ -214,10 +214,10 @@ typedef struct _redisSortOperation {
 } redisSortOperation;
 
 struct sharedObjectsStruct {
-    robj *crlf, *ok, *err, *zerobulk, *nil, *zero, *one, *pong, *space,
-    *minus1, *minus2, *minus3, *minus4,
-    *wrongtypeerr, *nokeyerr, *wrongtypeerrbulk, *nokeyerrbulk,
-    *syntaxerr, *syntaxerrbulk,
+    robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *pong, *space,
+    *colon, *minus1, *nullbulk, *nullmultibulk,
+    *emptymultibulk, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr,
+    *outofrangeerr, *plus,
     *select0, *select1, *select2, *select3, *select4,
     *select5, *select6, *select7, *select8, *select9;
 } shared;
@@ -660,29 +660,28 @@ static void createSharedObjects(void) {
     shared.crlf = createObject(REDIS_STRING,sdsnew("\r\n"));
     shared.ok = createObject(REDIS_STRING,sdsnew("+OK\r\n"));
     shared.err = createObject(REDIS_STRING,sdsnew("-ERR\r\n"));
-    shared.zerobulk = createObject(REDIS_STRING,sdsnew("0\r\n\r\n"));
-    shared.nil = createObject(REDIS_STRING,sdsnew("nil\r\n"));
-    shared.zero = createObject(REDIS_STRING,sdsnew("0\r\n"));
-    shared.one = createObject(REDIS_STRING,sdsnew("1\r\n"));
+    shared.emptybulk = createObject(REDIS_STRING,sdsnew("$0\r\n\r\n"));
+    shared.czero = createObject(REDIS_STRING,sdsnew(":0\r\n"));
+    shared.cone = createObject(REDIS_STRING,sdsnew(":1\r\n"));
+    shared.nullbulk = createObject(REDIS_STRING,sdsnew("$-1\r\n"));
+    shared.nullmultibulk = createObject(REDIS_STRING,sdsnew("*-1\r\n"));
+    shared.emptymultibulk = createObject(REDIS_STRING,sdsnew("*0\r\n"));
     /* no such key */
     shared.minus1 = createObject(REDIS_STRING,sdsnew("-1\r\n"));
-    /* operation against key holding a value of the wrong type */
-    shared.minus2 = createObject(REDIS_STRING,sdsnew("-2\r\n"));
-    /* src and dest objects are the same */
-    shared.minus3 = createObject(REDIS_STRING,sdsnew("-3\r\n"));
-    /* out of range argument */
-    shared.minus4 = createObject(REDIS_STRING,sdsnew("-4\r\n"));
     shared.pong = createObject(REDIS_STRING,sdsnew("+PONG\r\n"));
     shared.wrongtypeerr = createObject(REDIS_STRING,sdsnew(
         "-ERR Operation against a key holding the wrong kind of value\r\n"));
-    shared.wrongtypeerrbulk = createObject(REDIS_STRING,sdscatprintf(sdsempty(),"%d\r\n%s",-sdslen(shared.wrongtypeerr->ptr)+2,shared.wrongtypeerr->ptr));
     shared.nokeyerr = createObject(REDIS_STRING,sdsnew(
         "-ERR no such key\r\n"));
-    shared.nokeyerrbulk = createObject(REDIS_STRING,sdscatprintf(sdsempty(),"%d\r\n%s",-sdslen(shared.nokeyerr->ptr)+2,shared.nokeyerr->ptr));
     shared.syntaxerr = createObject(REDIS_STRING,sdsnew(
         "-ERR syntax error\r\n"));
-    shared.syntaxerrbulk = createObject(REDIS_STRING,sdscatprintf(sdsempty(),"%d\r\n%s",-sdslen(shared.syntaxerr->ptr)+2,shared.syntaxerr->ptr));
+    shared.sameobjecterr = createObject(REDIS_STRING,sdsnew(
+        "-ERR source and destination objects are the same\r\n"));
+    shared.outofrangeerr = createObject(REDIS_STRING,sdsnew(
+        "-ERR index out of range\r\n"));
     shared.space = createObject(REDIS_STRING,sdsnew(" "));
+    shared.colon = createObject(REDIS_STRING,sdsnew(":"));
+    shared.plus = createObject(REDIS_STRING,sdsnew("+"));
     shared.select0 = createStringObject("select 0\r\n",10);
     shared.select1 = createStringObject("select 1\r\n",10);
     shared.select2 = createStringObject("select 2\r\n",10);
@@ -1654,7 +1653,7 @@ static void pingCommand(redisClient *c) {
 }
 
 static void echoCommand(redisClient *c) {
-    addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",
+    addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",
         (int)sdslen(c->argv[1]->ptr)));
     addReply(c,c->argv[1]);
     addReply(c,shared.crlf);
@@ -1671,7 +1670,7 @@ static void setGenericCommand(redisClient *c, int nx) {
             dictReplace(c->dict,c->argv[1],c->argv[2]);
             incrRefCount(c->argv[2]);
         } else {
-            addReply(c,shared.zero);
+            addReply(c,shared.czero);
             return;
         }
     } else {
@@ -1679,7 +1678,7 @@ static void setGenericCommand(redisClient *c, int nx) {
         incrRefCount(c->argv[2]);
     }
     server.dirty++;
-    addReply(c, nx ? shared.one : shared.ok);
+    addReply(c, nx ? shared.cone : shared.ok);
 }
 
 static void setCommand(redisClient *c) {
@@ -1695,14 +1694,14 @@ static void getCommand(redisClient *c) {
     
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.nil);
+        addReply(c,shared.nullbulk);
     } else {
         robj *o = dictGetEntryVal(de);
         
         if (o->type != REDIS_STRING) {
-            addReply(c,shared.wrongtypeerrbulk);
+            addReply(c,shared.wrongtypeerr);
         } else {
-            addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",(int)sdslen(o->ptr)));
+            addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(o->ptr)));
             addReply(c,o);
             addReply(c,shared.crlf);
         }
@@ -1713,18 +1712,18 @@ static void mgetCommand(redisClient *c) {
     dictEntry *de;
     int j;
   
-    addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",c->argc-1));
+    addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",c->argc-1));
     for (j = 1; j < c->argc; j++) {
         de = dictFind(c->dict,c->argv[j]);
         if (de == NULL) {
-            addReply(c,shared.minus1);
+            addReply(c,shared.nullbulk);
         } else {
             robj *o = dictGetEntryVal(de);
             
             if (o->type != REDIS_STRING) {
-                addReply(c,shared.minus1);
+                addReply(c,shared.nullbulk);
             } else {
-                addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",(int)sdslen(o->ptr)));
+                addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(o->ptr)));
                 addReply(c,o);
                 addReply(c,shared.crlf);
             }
@@ -1762,6 +1761,7 @@ static void incrDecrCommand(redisClient *c, int incr) {
         incrRefCount(c->argv[1]);
     }
     server.dirty++;
+    addReply(c,shared.colon);
     addReply(c,o);
     addReply(c,shared.crlf);
 }
@@ -1789,9 +1789,9 @@ static void decrbyCommand(redisClient *c) {
 static void delCommand(redisClient *c) {
     if (dictDelete(c->dict,c->argv[1]) == DICT_OK) {
         server.dirty++;
-        addReply(c,shared.one);
+        addReply(c,shared.cone);
     } else {
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
     }
 }
 
@@ -1800,9 +1800,9 @@ static void existsCommand(redisClient *c) {
     
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL)
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
     else
-        addReply(c,shared.one);
+        addReply(c,shared.cone);
 }
 
 static void selectCommand(redisClient *c) {
@@ -1822,6 +1822,7 @@ static void randomkeyCommand(redisClient *c) {
     if (de == NULL) {
         addReply(c,shared.crlf);
     } else {
+        addReply(c,shared.plus);
         addReply(c,dictGetEntryKey(de));
         addReply(c,shared.crlf);
     }
@@ -1852,18 +1853,18 @@ static void keysCommand(redisClient *c) {
         }
     }
     dictReleaseIterator(di);
-    lenobj->ptr = sdscatprintf(sdsempty(),"%lu\r\n",keyslen+(numkeys ? (numkeys-1) : 0));
+    lenobj->ptr = sdscatprintf(sdsempty(),"$%lu\r\n",keyslen+(numkeys ? (numkeys-1) : 0));
     addReply(c,shared.crlf);
 }
 
 static void dbsizeCommand(redisClient *c) {
     addReplySds(c,
-        sdscatprintf(sdsempty(),"%lu\r\n",dictGetHashTableUsed(c->dict)));
+        sdscatprintf(sdsempty(),":%lu\r\n",dictGetHashTableUsed(c->dict)));
 }
 
 static void lastsaveCommand(redisClient *c) {
     addReplySds(c,
-        sdscatprintf(sdsempty(),"%lu\r\n",server.lastsave));
+        sdscatprintf(sdsempty(),":%lu\r\n",server.lastsave));
 }
 
 static void typeCommand(redisClient *c) {
@@ -1872,14 +1873,14 @@ static void typeCommand(redisClient *c) {
     
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        type = "none";
+        type = "+none";
     } else {
         robj *o = dictGetEntryVal(de);
         
         switch(o->type) {
-        case REDIS_STRING: type = "string"; break;
-        case REDIS_LIST: type = "list"; break;
-        case REDIS_SET: type = "set"; break;
+        case REDIS_STRING: type = "+string"; break;
+        case REDIS_LIST: type = "+list"; break;
+        case REDIS_SET: type = "+set"; break;
         default: type = "unknown"; break;
         }
     }
@@ -1927,19 +1928,13 @@ static void renameGenericCommand(redisClient *c, int nx) {
 
     /* To use the same key as src and dst is probably an error */
     if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) {
-        if (nx)
-            addReply(c,shared.minus3);
-        else
-            addReplySds(c,sdsnew("-ERR src and dest key are the same\r\n"));
+        addReply(c,shared.sameobjecterr);
         return;
     }
 
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        if (nx)
-            addReply(c,shared.minus1);
-        else
-            addReply(c,shared.nokeyerr);
+        addReply(c,shared.nokeyerr);
         return;
     }
     o = dictGetEntryVal(de);
@@ -1947,7 +1942,7 @@ static void renameGenericCommand(redisClient *c, int nx) {
     if (dictAdd(c->dict,c->argv[2],o) == DICT_ERR) {
         if (nx) {
             decrRefCount(o);
-            addReply(c,shared.zero);
+            addReply(c,shared.czero);
             return;
         }
         dictReplace(c->dict,c->argv[2],o);
@@ -1956,7 +1951,7 @@ static void renameGenericCommand(redisClient *c, int nx) {
     }
     dictDelete(c->dict,c->argv[1]);
     server.dirty++;
-    addReply(c,nx ? shared.one : shared.ok);
+    addReply(c,nx ? shared.cone : shared.ok);
 }
 
 static void renameCommand(redisClient *c) {
@@ -1977,7 +1972,7 @@ static void moveCommand(redisClient *c) {
     src = c->dict;
     srcid = c->dictid;
     if (selectDb(c,atoi(c->argv[2]->ptr)) == REDIS_ERR) {
-        addReply(c,shared.minus4);
+        addReply(c,shared.outofrangeerr);
         return;
     }
     dst = c->dict;
@@ -1987,14 +1982,14 @@ static void moveCommand(redisClient *c) {
     /* If the user is moving using as target the same
      * DB as the source DB it is probably an error. */
     if (src == dst) {
-        addReply(c,shared.minus3);
+        addReply(c,shared.sameobjecterr);
         return;
     }
 
     /* Check if the element exists and get a reference */
     de = dictFind(c->dict,c->argv[1]);
     if (!de) {
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
         return;
     }
 
@@ -2002,7 +1997,7 @@ static void moveCommand(redisClient *c) {
     key = dictGetEntryKey(de);
     o = dictGetEntryVal(de);
     if (dictAdd(dst,key,o) == DICT_ERR) {
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
         return;
     }
     incrRefCount(key);
@@ -2011,7 +2006,7 @@ static void moveCommand(redisClient *c) {
     /* OK! key moved, free the entry in the source DB */
     dictDelete(src,c->argv[1]);
     server.dirty++;
-    addReply(c,shared.one);
+    addReply(c,shared.cone);
 }
 
 /* =================================== Lists ================================ */
@@ -2064,15 +2059,15 @@ static void llenCommand(redisClient *c) {
     
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
         return;
     } else {
         robj *o = dictGetEntryVal(de);
         if (o->type != REDIS_LIST) {
-            addReply(c,shared.minus2);
+            addReply(c,shared.wrongtypeerr);
         } else {
             l = o->ptr;
-            addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",listLength(l)));
+            addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",listLength(l)));
         }
     }
 }
@@ -2083,22 +2078,22 @@ static void lindexCommand(redisClient *c) {
     
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.nil);
+        addReply(c,shared.nullbulk);
     } else {
         robj *o = dictGetEntryVal(de);
         
         if (o->type != REDIS_LIST) {
-            addReply(c,shared.wrongtypeerrbulk);
+            addReply(c,shared.wrongtypeerr);
         } else {
             list *list = o->ptr;
             listNode *ln;
             
             ln = listIndex(list, index);
             if (ln == NULL) {
-                addReply(c,shared.nil);
+                addReply(c,shared.nullbulk);
             } else {
                 robj *ele = listNodeValue(ln);
-                addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",(int)sdslen(ele->ptr)));
+                addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(ele->ptr)));
                 addReply(c,ele);
                 addReply(c,shared.crlf);
             }
@@ -2124,7 +2119,7 @@ static void lsetCommand(redisClient *c) {
             
             ln = listIndex(list, index);
             if (ln == NULL) {
-                addReplySds(c,sdsnew("-ERR index out of range\r\n"));
+                addReply(c,shared.outofrangeerr);
             } else {
                 robj *ele = listNodeValue(ln);
 
@@ -2143,12 +2138,12 @@ static void popGenericCommand(redisClient *c, int where) {
     
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.nil);
+        addReply(c,shared.nullbulk);
     } else {
         robj *o = dictGetEntryVal(de);
         
         if (o->type != REDIS_LIST) {
-            addReply(c,shared.wrongtypeerrbulk);
+            addReply(c,shared.wrongtypeerr);
         } else {
             list *list = o->ptr;
             listNode *ln;
@@ -2159,10 +2154,10 @@ static void popGenericCommand(redisClient *c, int where) {
                 ln = listLast(list);
 
             if (ln == NULL) {
-                addReply(c,shared.nil);
+                addReply(c,shared.nullbulk);
             } else {
                 robj *ele = listNodeValue(ln);
-                addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",(int)sdslen(ele->ptr)));
+                addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(ele->ptr)));
                 addReply(c,ele);
                 addReply(c,shared.crlf);
                 listDelNode(list,ln);
@@ -2187,12 +2182,12 @@ static void lrangeCommand(redisClient *c) {
     
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.nil);
+        addReply(c,shared.nullmultibulk);
     } else {
         robj *o = dictGetEntryVal(de);
         
         if (o->type != REDIS_LIST) {
-            addReply(c,shared.wrongtypeerrbulk);
+            addReply(c,shared.wrongtypeerr);
         } else {
             list *list = o->ptr;
             listNode *ln;
@@ -2209,7 +2204,7 @@ static void lrangeCommand(redisClient *c) {
             /* indexes sanity checks */
             if (start > end || start >= llen) {
                 /* Out of range start or start > end result in empty list */
-                addReply(c,shared.zero);
+                addReply(c,shared.emptymultibulk);
                 return;
             }
             if (end >= llen) end = llen-1;
@@ -2217,10 +2212,10 @@ static void lrangeCommand(redisClient *c) {
 
             /* Return the result in form of a multi-bulk reply */
             ln = listIndex(list, start);
-            addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",rangelen));
+            addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",rangelen));
             for (j = 0; j < rangelen; j++) {
                 ele = listNodeValue(ln);
-                addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",(int)sdslen(ele->ptr)));
+                addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",(int)sdslen(ele->ptr)));
                 addReply(c,ele);
                 addReply(c,shared.crlf);
                 ln = ln->next;
@@ -2290,7 +2285,7 @@ static void lremCommand(redisClient *c) {
         robj *o = dictGetEntryVal(de);
         
         if (o->type != REDIS_LIST) {
-            addReply(c,shared.minus2);
+            addReply(c,shared.wrongtypeerr);
         } else {
             list *list = o->ptr;
             listNode *ln, *next;
@@ -2314,7 +2309,7 @@ static void lremCommand(redisClient *c) {
                 }
                 ln = next;
             }
-            addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",removed));
+            addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",removed));
         }
     }
 }
@@ -2333,16 +2328,16 @@ static void saddCommand(redisClient *c) {
     } else {
         set = dictGetEntryVal(de);
         if (set->type != REDIS_SET) {
-            addReply(c,shared.minus2);
+            addReply(c,shared.wrongtypeerr);
             return;
         }
     }
     if (dictAdd(set->ptr,c->argv[2],NULL) == DICT_OK) {
         incrRefCount(c->argv[2]);
         server.dirty++;
-        addReply(c,shared.one);
+        addReply(c,shared.cone);
     } else {
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
     }
 }
 
@@ -2351,20 +2346,20 @@ static void sremCommand(redisClient *c) {
 
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
     } else {
         robj *set;
 
         set = dictGetEntryVal(de);
         if (set->type != REDIS_SET) {
-            addReply(c,shared.minus2);
+            addReply(c,shared.wrongtypeerr);
             return;
         }
         if (dictDelete(set->ptr,c->argv[2]) == DICT_OK) {
             server.dirty++;
-            addReply(c,shared.one);
+            addReply(c,shared.cone);
         } else {
-            addReply(c,shared.zero);
+            addReply(c,shared.czero);
         }
     }
 }
@@ -2374,19 +2369,19 @@ static void sismemberCommand(redisClient *c) {
 
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
     } else {
         robj *set;
 
         set = dictGetEntryVal(de);
         if (set->type != REDIS_SET) {
-            addReply(c,shared.minus2);
+            addReply(c,shared.wrongtypeerr);
             return;
         }
         if (dictFind(set->ptr,c->argv[2]))
-            addReply(c,shared.one);
+            addReply(c,shared.cone);
         else
-            addReply(c,shared.zero);
+            addReply(c,shared.czero);
     }
 }
 
@@ -2396,15 +2391,15 @@ static void scardCommand(redisClient *c) {
     
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.zero);
+        addReply(c,shared.czero);
         return;
     } else {
         robj *o = dictGetEntryVal(de);
         if (o->type != REDIS_SET) {
-            addReply(c,shared.minus2);
+            addReply(c,shared.wrongtypeerr);
         } else {
             s = o->ptr;
-            addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",
+            addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",
                 dictGetHashTableUsed(s)));
         }
     }
@@ -2431,13 +2426,13 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
         de = dictFind(c->dict,setskeys[j]);
         if (!de) {
             zfree(dv);
-            addReply(c,dstkey ? shared.nokeyerr : shared.nil);
+            addReply(c,shared.nokeyerr);
             return;
         }
         setobj = dictGetEntryVal(de);
         if (setobj->type != REDIS_SET) {
             zfree(dv);
-            addReply(c,dstkey ? shared.wrongtypeerr : shared.wrongtypeerrbulk);
+            addReply(c,shared.wrongtypeerr);
             return;
         }
         dv[j] = setobj->ptr;
@@ -2479,7 +2474,7 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
             continue; /* at least one set does not contain the member */
         ele = dictGetEntryKey(de);
         if (!dstkey) {
-            addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",sdslen(ele->ptr)));
+            addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",sdslen(ele->ptr)));
             addReply(c,ele);
             addReply(c,shared.crlf);
             cardinality++;
@@ -2491,7 +2486,7 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
     dictReleaseIterator(di);
 
     if (!dstkey)
-        lenobj->ptr = sdscatprintf(sdsempty(),"%d\r\n",cardinality);
+        lenobj->ptr = sdscatprintf(sdsempty(),"*%d\r\n",cardinality);
     else
         addReply(c,shared.ok);
     zfree(dv);
@@ -2621,12 +2616,12 @@ static void sortCommand(redisClient *c) {
     /* Lookup the key to sort. It must be of the right types */
     de = dictFind(c->dict,c->argv[1]);
     if (de == NULL) {
-        addReply(c,shared.nokeyerrbulk);
+        addReply(c,shared.nokeyerr);
         return;
     }
     sortval = dictGetEntryVal(de);
     if (sortval->type != REDIS_SET && sortval->type != REDIS_LIST) {
-        addReply(c,shared.wrongtypeerrbulk);
+        addReply(c,shared.wrongtypeerr);
         return;
     }
 
@@ -2680,7 +2675,7 @@ static void sortCommand(redisClient *c) {
         } else {
             decrRefCount(sortval);
             listRelease(operations);
-            addReply(c,shared.syntaxerrbulk);
+            addReply(c,shared.syntaxerr);
             return;
         }
         j++;
@@ -2761,11 +2756,11 @@ static void sortCommand(redisClient *c) {
     /* Send command output to the output buffer, performing the specified
      * GET/DEL/INCR/DECR operations if any. */
     outputlen = getop ? getop*(end-start+1) : end-start+1;
-    addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",outputlen));
+    addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",outputlen));
     for (j = start; j <= end; j++) {
         listNode *ln = operations->head;
         if (!getop) {
-            addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",
+            addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",
                 sdslen(vector[j].obj->ptr)));
             addReply(c,vector[j].obj);
             addReply(c,shared.crlf);
@@ -2779,7 +2774,7 @@ static void sortCommand(redisClient *c) {
                 if (!val || val->type != REDIS_STRING) {
                     addReply(c,shared.minus1);
                 } else {
-                    addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",
+                    addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",
                         sdslen(val->ptr)));
                     addReply(c,val);
                     addReply(c,shared.crlf);
@@ -2827,7 +2822,7 @@ static void infoCommand(redisClient *c) {
         uptime,
         uptime/(3600*24)
     );
-    addReplySds(c,sdscatprintf(sdsempty(),"%d\r\n",sdslen(info)));
+    addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n",sdslen(info)));
     addReplySds(c,info);
     addReply(c,shared.crlf);
 }
@@ -2930,7 +2925,7 @@ static void syncCommand(redisClient *c) {
     if (fd == -1 || fstat(fd,&sb) == -1) goto closeconn;
     len = sb.st_size;
 
-    snprintf(sizebuf,32,"%d\r\n",len);
+    snprintf(sizebuf,32,"$%d\r\n",len);
     if (syncWrite(c->fd,sizebuf,strlen(sizebuf),5) == -1) goto closeconn;
     while(len) {
         char buf[1024];
@@ -2982,7 +2977,7 @@ static int syncWithMaster(void) {
             strerror(errno));
         return REDIS_ERR;
     }
-    dumpsize = atoi(buf);
+    dumpsize = atoi(buf+1);
     redisLog(REDIS_NOTICE,"Receiving %d bytes data dump from MASTER",dumpsize);
     /* Read the bulk write data on a temp file */
     snprintf(tmpfile,256,"temp-%d.%ld.rdb",(int)time(NULL),(long int)random());
index 9bfab2048958d6974df432b70bfb1be35f722160..bc39f85db2acea63eb55d59e3029e6d9a2530fb3 100644 (file)
@@ -124,16 +124,16 @@ proc main {server port} {
         puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
         flush $fd
         set res {}
-        append res [string match +OK* [redis_read_retcode $fd]]
-        append res [redis_bulk_read $fd]
-        append res [string match +PONG* [redis_read_retcode $fd]]
+        append res [string match OK* [redis_read_reply $fd]]
+        append res [redis_read_reply $fd]
+        append res [string match PONG* [redis_read_reply $fd]]
         format $res
     } {1xyzk1}
 
     test {Non existing command} {
         puts -nonewline $fd "foo\r\n"
         flush $fd
-        string match -ERR* [redis_read_retcode $fd]
+        string match ERR* [redis_read_reply $fd]
     } {1}
 
     test {Basic LPUSH, RPUSH, LLENGTH, LINDEX} {
@@ -181,19 +181,19 @@ proc main {server port} {
         redis_del $fd mylist
         redis_set $fd mylist foobar
         redis_llen $fd mylist
-    } {-2}
+    } {ERR*}
 
     test {LINDEX against non-list value error} {
         redis_lindex $fd mylist 0
-    } {*ERROR*}
+    } {ERR*}
 
     test {LPUSH against non-list value error} {
         redis_lpush $fd mylist 0
-    } {-ERR*}
+    } {ERR*}
 
     test {RPUSH against non-list value error} {
         redis_rpush $fd mylist 0
-    } {-ERR*}
+    } {ERR*}
 
     test {RENAME basic usage} {
         redis_set $fd mykey hello
@@ -236,11 +236,11 @@ proc main {server port} {
 
     test {RENAME against non existing source key} {
         redis_rename $fd nokey foobar
-    } {-ERR*}
+    } {ERR*}
 
     test {RENAME where source and dest key is the same} {
         redis_rename $fd mykey mykey
-    } {-ERR*}
+    } {ERR*}
 
     test {DEL all keys again (DB 0)} {
         foreach key [redis_keys $fd *] {
@@ -309,7 +309,7 @@ proc main {server port} {
     test {LPOP against non list value} {
         redis_set $fd notalist foo
         redis_lpop $fd notalist
-    } {*ERROR*against*}
+    } {ERR*kind*}
 
     test {Mass LPUSH/LPOP} {
         set sum 0
@@ -363,16 +363,16 @@ proc main {server port} {
 
     test {LSET out of range index} {
         redis_lset $fd mylist 10 foo
-    } {-ERR*range*}
+    } {ERR*range*}
 
     test {LSET against non existing key} {
         redis_lset $fd nosuchkey 10 foo
-    } {-ERR*key*}
+    } {ERR*key*}
 
     test {LSET against non list value} {
         redis_set $fd nolist foobar
         redis_lset $fd nolist 0 foo
-    } {-ERR*value*}
+    } {ERR*value*}
 
     test {SADD, SCARD, SISMEMBER, SMEMBERS basics} {
         redis_sadd $fd myset foo
@@ -391,7 +391,7 @@ proc main {server port} {
 
     test {SADD against non set} {
         redis_sadd $fd mylist foo
-    } {-2}
+    } {ERR*kind*}
 
     test {SREM basics} {
         redis_sadd $fd myset ciao
@@ -431,7 +431,7 @@ proc main {server port} {
         redis_set $fd myemptykey {}
         redis_set $fd mynormalkey {blablablba}
         redis_save $fd
-    } {+OK}
+    } {OK}
     
     test {Create a random list} {
         set tosort {}
@@ -606,221 +606,224 @@ proc redis_readnl {fd len} {
     return $buf
 }
 
-proc redis_bulk_read {fd {multi 0}} {
-    set count [redis_read_integer $fd]
-    if {$count eq {nil}} return {}
-    if {$multi && $count == -1} return {}
-    set len [expr {abs($count)}]
-    set buf [redis_readnl $fd $len]
-    if {$count < 0} {return "***ERROR*** $buf"}
+proc redis_bulk_read {fd} {
+    set count [redis_read_line $fd]
+    if {$count == -1} return {}
+    set buf [redis_readnl $fd $count]
     return $buf
 }
 
 proc redis_multi_bulk_read fd {
-    set count [redis_read_integer $fd]
-    if {$count eq {nil}} return {}
-    if {$count < 0} {
-        set len [expr {abs($count)}]
-        set buf [redis_readnl $fd $len]
-        return "***ERROR*** $buf"
-    }
+    set count [redis_read_line $fd]
+    if {$count == -1} return {}
     set l {}
     for {set i 0} {$i < $count} {incr i} {
-        lappend l [redis_bulk_read $fd 1]
+        lappend l [redis_read_reply $fd]
     }
     return $l
 }
 
-proc redis_read_retcode fd {
-    set retcode [string trim [gets $fd]]
-    # puts "S: $retcode"
-    return $retcode
+proc redis_read_line fd {
+    string trim [gets $fd]
 }
 
-proc redis_read_integer fd {
-    string trim [gets $fd]
+proc redis_read_reply fd {
+    set type [read $fd 1]
+    if {$type eq {:}} {
+        redis_read_line $fd
+    } elseif {$type eq {-}} {
+        redis_read_line $fd
+    } elseif {$type eq {+}} {
+        redis_read_line $fd
+    } elseif {$type eq {$}} {
+        redis_bulk_read $fd
+    } elseif {$type eq {*}} {
+        redis_multi_bulk_read $fd
+    } else {
+        error "Bad protocol: $type as initial reply byte"
+    }
 }
 
 ### Actual API ###
 
 proc redis_set {fd key val} {
     redis_writenl $fd "set $key [string length $val]\r\n$val"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_setnx {fd key val} {
     redis_writenl $fd "setnx $key [string length $val]\r\n$val"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_get {fd key} {
     redis_writenl $fd "get $key"
-    redis_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_select {fd id} {
     redis_writenl $fd "select $id"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_move {fd key id} {
     redis_writenl $fd "move $key $id"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_del {fd key} {
     redis_writenl $fd "del $key"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_keys {fd pattern} {
     redis_writenl $fd "keys $pattern"
-    split [redis_bulk_read $fd]
+    split [redis_read_reply $fd]
 }
 
 proc redis_dbsize {fd} {
     redis_writenl $fd "dbsize"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_incr {fd key} {
     redis_writenl $fd "incr $key"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_decr {fd key} {
     redis_writenl $fd "decr $key"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_exists {fd key} {
     redis_writenl $fd "exists $key"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_lpush {fd key val} {
     redis_writenl $fd "lpush $key [string length $val]\r\n$val"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_rpush {fd key val} {
     redis_writenl $fd "rpush $key [string length $val]\r\n$val"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_llen {fd key} {
     redis_writenl $fd "llen $key"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_scard {fd key} {
     redis_writenl $fd "scard $key"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_lindex {fd key index} {
     redis_writenl $fd "lindex $key $index"
-    redis_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_lrange {fd key first last} {
     redis_writenl $fd "lrange $key $first $last"
-    redis_multi_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_mget {fd args} {
     redis_writenl $fd "mget [join $args]"
-    redis_multi_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_sort {fd key {params {}}} {
     redis_writenl $fd "sort $key $params"
-    redis_multi_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_ltrim {fd key first last} {
     redis_writenl $fd "ltrim $key $first $last"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_rename {fd key1 key2} {
     redis_writenl $fd "rename $key1 $key2"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_renamenx {fd key1 key2} {
     redis_writenl $fd "renamenx $key1 $key2"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_lpop {fd key} {
     redis_writenl $fd "lpop $key"
-    redis_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_rpop {fd key} {
     redis_writenl $fd "rpop $key"
-    redis_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_lset {fd key index val} {
     redis_writenl $fd "lset $key $index [string length $val]\r\n$val"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_sadd {fd key val} {
     redis_writenl $fd "sadd $key [string length $val]\r\n$val"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_srem {fd key val} {
     redis_writenl $fd "srem $key [string length $val]\r\n$val"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_sismember {fd key val} {
     redis_writenl $fd "sismember $key [string length $val]\r\n$val"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc redis_sinter {fd args} {
     redis_writenl $fd "sinter [join $args]"
-    redis_multi_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_sinterstore {fd args} {
     redis_writenl $fd "sinterstore [join $args]"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_smembers {fd key} {
     redis_writenl $fd "smembers $key"
-    redis_multi_bulk_read $fd
+    redis_read_reply $fd
 }
 
 proc redis_echo {fd str} {
     redis_writenl $fd "echo [string length $str]\r\n$str"
-    redis_writenl $fd "smembers $key"
+    redis_read_reply $fd
 }
 
 proc redis_save {fd} {
     redis_writenl $fd "save"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_flushall {fd} {
     redis_writenl $fd "flushall"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_flushdb {fd} {
     redis_writenl $fd "flushdb"
-    redis_read_retcode $fd
+    redis_read_reply $fd
 }
 
 proc redis_lrem {fd key count val} {
     redis_writenl $fd "lrem $key $count [string length $val]\r\n$val"
-    redis_read_integer $fd
+    redis_read_reply $fd
 }
 
 proc stress {} {