pretty big refactoring

This commit is contained in:
antirez 2010-03-15 23:59:40 +01:00
parent 92b27fe946
commit dd88747b78

514
redis.c
View File

@ -2478,6 +2478,13 @@ static void addReplyLong(redisClient *c, long l) {
char buf[128]; char buf[128];
size_t len; size_t len;
if (l == 0) {
addReply(c,shared.czero);
return;
} else if (l == 1) {
addReply(c,shared.cone);
return;
}
len = snprintf(buf,sizeof(buf),":%ld\r\n",l); len = snprintf(buf,sizeof(buf),":%ld\r\n",l);
addReplySds(c,sdsnewlen(buf,len)); addReplySds(c,sdsnewlen(buf,len));
} }
@ -2486,6 +2493,13 @@ static void addReplyUlong(redisClient *c, unsigned long ul) {
char buf[128]; char buf[128];
size_t len; size_t len;
if (ul == 0) {
addReply(c,shared.czero);
return;
} else if (ul == 1) {
addReply(c,shared.cone);
return;
}
len = snprintf(buf,sizeof(buf),":%lu\r\n",ul); len = snprintf(buf,sizeof(buf),":%lu\r\n",ul);
addReplySds(c,sdsnewlen(buf,len)); addReplySds(c,sdsnewlen(buf,len));
} }
@ -2511,6 +2525,12 @@ static void addReplyBulkLen(redisClient *c, robj *obj) {
addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n",(unsigned long)len)); addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n",(unsigned long)len));
} }
static void addReplyBulk(redisClient *c, robj *obj) {
addReplyBulkLen(c,obj);
addReply(c,obj);
addReply(c,shared.crlf);
}
static void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) { static void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
int cport, cfd; int cport, cfd;
char cip[128]; char cip[128];
@ -3682,9 +3702,7 @@ static void pingCommand(redisClient *c) {
} }
static void echoCommand(redisClient *c) { static void echoCommand(redisClient *c) {
addReplyBulkLen(c,c->argv[1]); addReplyBulk(c,c->argv[1]);
addReply(c,c->argv[1]);
addReply(c,shared.crlf);
} }
/*=================================== Strings =============================== */ /*=================================== Strings =============================== */
@ -3726,22 +3744,18 @@ static void setnxCommand(redisClient *c) {
} }
static int getGenericCommand(redisClient *c) { static int getGenericCommand(redisClient *c) {
robj *o = lookupKeyRead(c->db,c->argv[1]); robj *o;
if (o == NULL) { if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL)
addReply(c,shared.nullbulk);
return REDIS_OK; return REDIS_OK;
} else {
if (o->type != REDIS_STRING) { if (o->type != REDIS_STRING) {
addReply(c,shared.wrongtypeerr); addReply(c,shared.wrongtypeerr);
return REDIS_ERR; return REDIS_ERR;
} else { } else {
addReplyBulkLen(c,o); addReplyBulk(c,o);
addReply(c,o);
addReply(c,shared.crlf);
return REDIS_OK; return REDIS_OK;
} }
}
} }
static void getCommand(redisClient *c) { static void getCommand(redisClient *c) {
@ -3772,9 +3786,7 @@ static void mgetCommand(redisClient *c) {
if (o->type != REDIS_STRING) { if (o->type != REDIS_STRING) {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
} else { } else {
addReplyBulkLen(c,o); addReplyBulk(c,o);
addReply(c,o);
addReply(c,shared.crlf);
} }
} }
} }
@ -3934,17 +3946,12 @@ static void substrCommand(redisClient *c) {
robj *o; robj *o;
long start = atoi(c->argv[2]->ptr); long start = atoi(c->argv[2]->ptr);
long end = atoi(c->argv[3]->ptr); long end = atoi(c->argv[3]->ptr);
o = lookupKeyRead(c->db,c->argv[1]);
if (o == NULL) {
addReply(c,shared.nullbulk);
} else {
if (o->type != REDIS_STRING) {
addReply(c,shared.wrongtypeerr);
} else {
size_t rangelen, strlen; size_t rangelen, strlen;
sds range; sds range;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
checkType(c,o,REDIS_STRING)) return;
o = getDecodedObject(o); o = getDecodedObject(o);
strlen = sdslen(o->ptr); strlen = sdslen(o->ptr);
@ -3970,8 +3977,6 @@ static void substrCommand(redisClient *c) {
addReplySds(c,range); addReplySds(c,range);
addReply(c,shared.crlf); addReply(c,shared.crlf);
decrRefCount(o); decrRefCount(o);
}
}
} }
/* ========================= Type agnostic commands ========================= */ /* ========================= Type agnostic commands ========================= */
@ -3985,17 +3990,7 @@ static void delCommand(redisClient *c) {
deleted++; deleted++;
} }
} }
switch(deleted) { addReplyLong(c,deleted);
case 0:
addReply(c,shared.czero);
break;
case 1:
addReply(c,shared.cone);
break;
default:
addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",deleted));
break;
}
} }
static void existsCommand(redisClient *c) { static void existsCommand(redisClient *c) {
@ -4047,9 +4042,7 @@ static void keysCommand(redisClient *c) {
if ((pattern[0] == '*' && pattern[1] == '\0') || if ((pattern[0] == '*' && pattern[1] == '\0') ||
stringmatchlen(pattern,plen,key,sdslen(key),0)) { stringmatchlen(pattern,plen,key,sdslen(key),0)) {
if (expireIfNeeded(c->db,keyobj) == 0) { if (expireIfNeeded(c->db,keyobj) == 0) {
addReplyBulkLen(c,keyobj); addReplyBulk(c,keyobj);
addReply(c,keyobj);
addReply(c,shared.crlf);
numkeys++; numkeys++;
} }
} }
@ -4139,12 +4132,14 @@ static void shutdownCommand(redisClient *c) {
if (server.vm_enabled) unlink(server.vm_swap_file); if (server.vm_enabled) unlink(server.vm_swap_file);
exit(0); exit(0);
} else { } else {
/* Ooops.. error saving! The best we can do is to continue operating. /* Ooops.. error saving! The best we can do is to continue
* Note that if there was a background saving process, in the next * operating. Note that if there was a background saving process,
* cron() Redis will be notified that the background saving aborted, * in the next cron() Redis will be notified that the background
* handling special stuff like slaves pending for synchronization... */ * saving aborted, handling special stuff like slaves pending for
* synchronization... */
redisLog(REDIS_WARNING,"Error trying to save the DB, can't exit"); redisLog(REDIS_WARNING,"Error trying to save the DB, can't exit");
addReplySds(c,sdsnew("-ERR can't quit, problems saving the DB\r\n")); addReplySds(c,
sdsnew("-ERR can't quit, problems saving the DB\r\n"));
} }
} }
} }
@ -4158,11 +4153,9 @@ static void renameGenericCommand(redisClient *c, int nx) {
return; return;
} }
o = lookupKeyWrite(c->db,c->argv[1]); if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL)
if (o == NULL) {
addReply(c,shared.nokeyerr);
return; return;
}
incrRefCount(o); incrRefCount(o);
deleteIfVolatile(c->db,c->argv[2]); deleteIfVolatile(c->db,c->argv[2]);
if (dictAdd(c->db->dict,c->argv[2],o) == DICT_ERR) { if (dictAdd(c->db->dict,c->argv[2],o) == DICT_ERR) {
@ -4286,61 +4279,42 @@ static void llenCommand(redisClient *c) {
robj *o; robj *o;
list *l; list *l;
o = lookupKeyRead(c->db,c->argv[1]); if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
if (o == NULL) { checkType(c,o,REDIS_LIST)) return;
addReply(c,shared.czero);
return;
} else {
if (o->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
} else {
l = o->ptr; l = o->ptr;
addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",listLength(l))); addReplyUlong(c,listLength(l));
}
}
} }
static void lindexCommand(redisClient *c) { static void lindexCommand(redisClient *c) {
robj *o; robj *o;
int index = atoi(c->argv[2]->ptr); int index = atoi(c->argv[2]->ptr);
list *list;
o = lookupKeyRead(c->db,c->argv[1]);
if (o == NULL) {
addReply(c,shared.nullbulk);
} else {
if (o->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
} else {
list *list = o->ptr;
listNode *ln; listNode *ln;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
checkType(c,o,REDIS_LIST)) return;
list = o->ptr;
ln = listIndex(list, index); ln = listIndex(list, index);
if (ln == NULL) { if (ln == NULL) {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
} else { } else {
robj *ele = listNodeValue(ln); robj *ele = listNodeValue(ln);
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
}
}
} }
} }
static void lsetCommand(redisClient *c) { static void lsetCommand(redisClient *c) {
robj *o; robj *o;
int index = atoi(c->argv[2]->ptr); int index = atoi(c->argv[2]->ptr);
list *list;
o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) {
addReply(c,shared.nokeyerr);
} else {
if (o->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
} else {
list *list = o->ptr;
listNode *ln; listNode *ln;
if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL ||
checkType(c,o,REDIS_LIST)) return;
list = o->ptr;
ln = listIndex(list, index); ln = listIndex(list, index);
if (ln == NULL) { if (ln == NULL) {
addReply(c,shared.outofrangeerr); addReply(c,shared.outofrangeerr);
@ -4353,23 +4327,17 @@ static void lsetCommand(redisClient *c) {
addReply(c,shared.ok); addReply(c,shared.ok);
server.dirty++; server.dirty++;
} }
}
}
} }
static void popGenericCommand(redisClient *c, int where) { static void popGenericCommand(redisClient *c, int where) {
robj *o; robj *o;
list *list;
o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) {
addReply(c,shared.nullbulk);
} else {
if (o->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
} else {
list *list = o->ptr;
listNode *ln; listNode *ln;
if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
checkType(c,o,REDIS_LIST)) return;
list = o->ptr;
if (where == REDIS_HEAD) if (where == REDIS_HEAD)
ln = listFirst(list); ln = listFirst(list);
else else
@ -4379,14 +4347,10 @@ static void popGenericCommand(redisClient *c, int where) {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
} else { } else {
robj *ele = listNodeValue(ln); robj *ele = listNodeValue(ln);
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
listDelNode(list,ln); listDelNode(list,ln);
server.dirty++; server.dirty++;
} }
}
}
} }
static void lpopCommand(redisClient *c) { static void lpopCommand(redisClient *c) {
@ -4401,20 +4365,17 @@ static void lrangeCommand(redisClient *c) {
robj *o; robj *o;
int start = atoi(c->argv[2]->ptr); int start = atoi(c->argv[2]->ptr);
int end = atoi(c->argv[3]->ptr); int end = atoi(c->argv[3]->ptr);
int llen;
o = lookupKeyRead(c->db,c->argv[1]);
if (o == NULL) {
addReply(c,shared.nullmultibulk);
} else {
if (o->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
} else {
list *list = o->ptr;
listNode *ln;
int llen = listLength(list);
int rangelen, j; int rangelen, j;
list *list;
listNode *ln;
robj *ele; robj *ele;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullmultibulk)) == NULL ||
checkType(c,o,REDIS_LIST)) return;
list = o->ptr;
llen = listLength(list);
/* convert negative indexes */ /* convert negative indexes */
if (start < 0) start = llen+start; if (start < 0) start = llen+start;
if (end < 0) end = llen+end; if (end < 0) end = llen+end;
@ -4435,31 +4396,24 @@ static void lrangeCommand(redisClient *c) {
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",rangelen)); addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",rangelen));
for (j = 0; j < rangelen; j++) { for (j = 0; j < rangelen; j++) {
ele = listNodeValue(ln); ele = listNodeValue(ln);
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
ln = ln->next; ln = ln->next;
} }
}
}
} }
static void ltrimCommand(redisClient *c) { static void ltrimCommand(redisClient *c) {
robj *o; robj *o;
int start = atoi(c->argv[2]->ptr); int start = atoi(c->argv[2]->ptr);
int end = atoi(c->argv[3]->ptr); int end = atoi(c->argv[3]->ptr);
int llen;
o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) {
addReply(c,shared.ok);
} else {
if (o->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
} else {
list *list = o->ptr;
listNode *ln;
int llen = listLength(list);
int j, ltrim, rtrim; int j, ltrim, rtrim;
list *list;
listNode *ln;
if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.ok)) == NULL ||
checkType(c,o,REDIS_LIST)) return;
list = o->ptr;
llen = listLength(list);
/* convert negative indexes */ /* convert negative indexes */
if (start < 0) start = llen+start; if (start < 0) start = llen+start;
@ -4489,26 +4443,20 @@ static void ltrimCommand(redisClient *c) {
} }
server.dirty++; server.dirty++;
addReply(c,shared.ok); addReply(c,shared.ok);
}
}
} }
static void lremCommand(redisClient *c) { static void lremCommand(redisClient *c) {
robj *o; robj *o;
list *list;
o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) {
addReply(c,shared.czero);
} else {
if (o->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
} else {
list *list = o->ptr;
listNode *ln, *next; listNode *ln, *next;
int toremove = atoi(c->argv[2]->ptr); int toremove = atoi(c->argv[2]->ptr);
int removed = 0; int removed = 0;
int fromtail = 0; int fromtail = 0;
if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
checkType(c,o,REDIS_LIST)) return;
list = o->ptr;
if (toremove < 0) { if (toremove < 0) {
toremove = -toremove; toremove = -toremove;
fromtail = 1; fromtail = 1;
@ -4527,8 +4475,6 @@ static void lremCommand(redisClient *c) {
ln = next; ln = next;
} }
addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",removed)); addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",removed));
}
}
} }
/* This is the semantic of this command: /* This is the semantic of this command:
@ -4548,16 +4494,13 @@ static void lremCommand(redisClient *c) {
*/ */
static void rpoplpushcommand(redisClient *c) { static void rpoplpushcommand(redisClient *c) {
robj *sobj; robj *sobj;
list *srclist;
listNode *ln;
sobj = lookupKeyWrite(c->db,c->argv[1]); if ((sobj = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
if (sobj == NULL) { checkType(c,sobj,REDIS_LIST)) return;
addReply(c,shared.nullbulk); srclist = sobj->ptr;
} else { ln = listLast(srclist);
if (sobj->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
} else {
list *srclist = sobj->ptr;
listNode *ln = listLast(srclist);
if (ln == NULL) { if (ln == NULL) {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
@ -4586,19 +4529,14 @@ static void rpoplpushcommand(redisClient *c) {
} }
/* Send the element to the client as reply as well */ /* Send the element to the client as reply as well */
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
/* Finally remove the element from the source list */ /* Finally remove the element from the source list */
listDelNode(srclist,ln); listDelNode(srclist,ln);
server.dirty++; server.dirty++;
} }
}
}
} }
/* ==================================== Sets ================================ */ /* ==================================== Sets ================================ */
static void saddCommand(redisClient *c) { static void saddCommand(redisClient *c) {
@ -4627,14 +4565,9 @@ static void saddCommand(redisClient *c) {
static void sremCommand(redisClient *c) { static void sremCommand(redisClient *c) {
robj *set; robj *set;
set = lookupKeyWrite(c->db,c->argv[1]); if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
if (set == NULL) { checkType(c,set,REDIS_SET)) return;
addReply(c,shared.czero);
} else {
if (set->type != REDIS_SET) {
addReply(c,shared.wrongtypeerr);
return;
}
if (dictDelete(set->ptr,c->argv[2]) == DICT_OK) { if (dictDelete(set->ptr,c->argv[2]) == DICT_OK) {
server.dirty++; server.dirty++;
if (htNeedsResize(set->ptr)) dictResize(set->ptr); if (htNeedsResize(set->ptr)) dictResize(set->ptr);
@ -4642,7 +4575,6 @@ static void sremCommand(redisClient *c) {
} else { } else {
addReply(c,shared.czero); addReply(c,shared.czero);
} }
}
} }
static void smoveCommand(redisClient *c) { static void smoveCommand(redisClient *c) {
@ -4683,90 +4615,60 @@ static void smoveCommand(redisClient *c) {
static void sismemberCommand(redisClient *c) { static void sismemberCommand(redisClient *c) {
robj *set; robj *set;
set = lookupKeyRead(c->db,c->argv[1]); if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
if (set == NULL) { checkType(c,set,REDIS_SET)) return;
addReply(c,shared.czero);
} else {
if (set->type != REDIS_SET) {
addReply(c,shared.wrongtypeerr);
return;
}
if (dictFind(set->ptr,c->argv[2])) if (dictFind(set->ptr,c->argv[2]))
addReply(c,shared.cone); addReply(c,shared.cone);
else else
addReply(c,shared.czero); addReply(c,shared.czero);
}
} }
static void scardCommand(redisClient *c) { static void scardCommand(redisClient *c) {
robj *o; robj *o;
dict *s; dict *s;
o = lookupKeyRead(c->db,c->argv[1]); if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
if (o == NULL) { checkType(c,o,REDIS_SET)) return;
addReply(c,shared.czero);
return;
} else {
if (o->type != REDIS_SET) {
addReply(c,shared.wrongtypeerr);
} else {
s = o->ptr; s = o->ptr;
addReplySds(c,sdscatprintf(sdsempty(),":%lu\r\n", addReplyUlong(c,dictSize(s));
dictSize(s)));
}
}
} }
static void spopCommand(redisClient *c) { static void spopCommand(redisClient *c) {
robj *set; robj *set;
dictEntry *de; dictEntry *de;
set = lookupKeyWrite(c->db,c->argv[1]); if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
if (set == NULL) { checkType(c,set,REDIS_SET)) return;
addReply(c,shared.nullbulk);
} else {
if (set->type != REDIS_SET) {
addReply(c,shared.wrongtypeerr);
return;
}
de = dictGetRandomKey(set->ptr); de = dictGetRandomKey(set->ptr);
if (de == NULL) { if (de == NULL) {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
} else { } else {
robj *ele = dictGetEntryKey(de); robj *ele = dictGetEntryKey(de);
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
dictDelete(set->ptr,ele); dictDelete(set->ptr,ele);
if (htNeedsResize(set->ptr)) dictResize(set->ptr); if (htNeedsResize(set->ptr)) dictResize(set->ptr);
server.dirty++; server.dirty++;
} }
}
} }
static void srandmemberCommand(redisClient *c) { static void srandmemberCommand(redisClient *c) {
robj *set; robj *set;
dictEntry *de; dictEntry *de;
set = lookupKeyRead(c->db,c->argv[1]); if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
if (set == NULL) { checkType(c,set,REDIS_SET)) return;
addReply(c,shared.nullbulk);
} else {
if (set->type != REDIS_SET) {
addReply(c,shared.wrongtypeerr);
return;
}
de = dictGetRandomKey(set->ptr); de = dictGetRandomKey(set->ptr);
if (de == NULL) { if (de == NULL) {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
} else { } else {
robj *ele = dictGetEntryKey(de); robj *ele = dictGetEntryKey(de);
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
}
} }
} }
@ -4840,9 +4742,7 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, unsigned long
continue; /* at least one set does not contain the member */ continue; /* at least one set does not contain the member */
ele = dictGetEntryKey(de); ele = dictGetEntryKey(de);
if (!dstkey) { if (!dstkey) {
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
cardinality++; cardinality++;
} else { } else {
dictAdd(dstset->ptr,ele,NULL); dictAdd(dstset->ptr,ele,NULL);
@ -4947,9 +4847,7 @@ static void sunionDiffGenericCommand(redisClient *c, robj **setskeys, int setsnu
robj *ele; robj *ele;
ele = dictGetEntryKey(de); ele = dictGetEntryKey(de);
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
} }
dictReleaseIterator(di); dictReleaseIterator(di);
} else { } else {
@ -5284,11 +5182,11 @@ zskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank) {
x = zsl->header; x = zsl->header;
for (i = zsl->level-1; i >= 0; i--) { for (i = zsl->level-1; i >= 0; i--) {
while (x->forward[i] && (traversed + (i > 0 ? x->span[i-1] : 1)) <= rank) { while (x->forward[i] && (traversed + (i>0 ? x->span[i-1] : 1)) <= rank)
{
traversed += i > 0 ? x->span[i-1] : 1; traversed += i > 0 ? x->span[i-1] : 1;
x = x->forward[i]; x = x->forward[i];
} }
if (traversed == rank) { if (traversed == rank) {
return x; return x;
} }
@ -5396,19 +5294,13 @@ static void zincrbyCommand(redisClient *c) {
static void zremCommand(redisClient *c) { static void zremCommand(redisClient *c) {
robj *zsetobj; robj *zsetobj;
zset *zs; zset *zs;
zsetobj = lookupKeyWrite(c->db,c->argv[1]);
if (zsetobj == NULL) {
addReply(c,shared.czero);
} else {
dictEntry *de; dictEntry *de;
double *oldscore; double *oldscore;
int deleted; int deleted;
if (zsetobj->type != REDIS_ZSET) { if ((zsetobj = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
addReply(c,shared.wrongtypeerr); checkType(c,zsetobj,REDIS_ZSET)) return;
return;
}
zs = zsetobj->ptr; zs = zsetobj->ptr;
de = dictFind(zs->dict,c->argv[2]); de = dictFind(zs->dict,c->argv[2]);
if (de == NULL) { if (de == NULL) {
@ -5425,51 +5317,37 @@ static void zremCommand(redisClient *c) {
if (htNeedsResize(zs->dict)) dictResize(zs->dict); if (htNeedsResize(zs->dict)) dictResize(zs->dict);
server.dirty++; server.dirty++;
addReply(c,shared.cone); addReply(c,shared.cone);
}
} }
static void zremrangebyscoreCommand(redisClient *c) { static void zremrangebyscoreCommand(redisClient *c) {
double min = strtod(c->argv[2]->ptr,NULL); double min = strtod(c->argv[2]->ptr,NULL);
double max = strtod(c->argv[3]->ptr,NULL); double max = strtod(c->argv[3]->ptr,NULL);
long deleted;
robj *zsetobj; robj *zsetobj;
zset *zs; zset *zs;
zsetobj = lookupKeyWrite(c->db,c->argv[1]); if ((zsetobj = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
if (zsetobj == NULL) { checkType(c,zsetobj,REDIS_ZSET)) return;
addReply(c,shared.czero);
} else {
long deleted;
if (zsetobj->type != REDIS_ZSET) {
addReply(c,shared.wrongtypeerr);
return;
}
zs = zsetobj->ptr; zs = zsetobj->ptr;
deleted = zslDeleteRangeByScore(zs->zsl,min,max,zs->dict); deleted = zslDeleteRangeByScore(zs->zsl,min,max,zs->dict);
if (htNeedsResize(zs->dict)) dictResize(zs->dict); if (htNeedsResize(zs->dict)) dictResize(zs->dict);
server.dirty += deleted; server.dirty += deleted;
addReplySds(c,sdscatprintf(sdsempty(),":%lu\r\n",deleted)); addReplyLong(c,deleted);
}
} }
static void zremrangebyrankCommand(redisClient *c) { static void zremrangebyrankCommand(redisClient *c) {
int start = atoi(c->argv[2]->ptr); int start = atoi(c->argv[2]->ptr);
int end = atoi(c->argv[3]->ptr); int end = atoi(c->argv[3]->ptr);
int llen;
long deleted;
robj *zsetobj; robj *zsetobj;
zset *zs; zset *zs;
zsetobj = lookupKeyWrite(c->db,c->argv[1]); if ((zsetobj = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
if (zsetobj == NULL) { checkType(c,zsetobj,REDIS_ZSET)) return;
addReply(c,shared.czero);
} else {
if (zsetobj->type != REDIS_ZSET) {
addReply(c,shared.wrongtypeerr);
return;
}
zs = zsetobj->ptr; zs = zsetobj->ptr;
int llen = zs->zsl->length; llen = zs->zsl->length;
long deleted;
/* convert negative indexes */ /* convert negative indexes */
if (start < 0) start = llen+start; if (start < 0) start = llen+start;
@ -5490,7 +5368,6 @@ static void zremrangebyrankCommand(redisClient *c) {
if (htNeedsResize(zs->dict)) dictResize(zs->dict); if (htNeedsResize(zs->dict)) dictResize(zs->dict);
server.dirty += deleted; server.dirty += deleted;
addReplyLong(c, deleted); addReplyLong(c, deleted);
}
} }
typedef struct { typedef struct {
@ -5663,6 +5540,12 @@ static void zrangeGenericCommand(redisClient *c, int reverse) {
int start = atoi(c->argv[2]->ptr); int start = atoi(c->argv[2]->ptr);
int end = atoi(c->argv[3]->ptr); int end = atoi(c->argv[3]->ptr);
int withscores = 0; int withscores = 0;
int llen;
int rangelen, j;
zset *zsetobj;
zskiplist *zsl;
zskiplistNode *ln;
robj *ele;
if (c->argc == 5 && !strcasecmp(c->argv[4]->ptr,"withscores")) { if (c->argc == 5 && !strcasecmp(c->argv[4]->ptr,"withscores")) {
withscores = 1; withscores = 1;
@ -5671,20 +5554,11 @@ static void zrangeGenericCommand(redisClient *c, int reverse) {
return; return;
} }
o = lookupKeyRead(c->db,c->argv[1]); if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullmultibulk)) == NULL ||
if (o == NULL) { checkType(c,o,REDIS_ZSET)) return;
addReply(c,shared.nullmultibulk); zsetobj = o->ptr;
} else { zsl = zsetobj->zsl;
if (o->type != REDIS_ZSET) { llen = zsl->length;
addReply(c,shared.wrongtypeerr);
} else {
zset *zsetobj = o->ptr;
zskiplist *zsl = zsetobj->zsl;
zskiplistNode *ln;
int llen = zsl->length;
int rangelen, j;
robj *ele;
/* convert negative indexes */ /* convert negative indexes */
if (start < 0) start = llen+start; if (start < 0) start = llen+start;
@ -5706,7 +5580,8 @@ static void zrangeGenericCommand(redisClient *c, int reverse) {
if (reverse) { if (reverse) {
ln = start == 0 ? zsl->tail : zslGetElementByRank(zsl, llen-start); ln = start == 0 ? zsl->tail : zslGetElementByRank(zsl, llen-start);
} else { } else {
ln = start == 0 ? zsl->header->forward[0] : zslGetElementByRank(zsl, start+1); ln = start == 0 ?
zsl->header->forward[0] : zslGetElementByRank(zsl, start+1);
} }
/* Return the result in form of a multi-bulk reply */ /* Return the result in form of a multi-bulk reply */
@ -5714,15 +5589,11 @@ static void zrangeGenericCommand(redisClient *c, int reverse) {
withscores ? (rangelen*2) : rangelen)); withscores ? (rangelen*2) : rangelen));
for (j = 0; j < rangelen; j++) { for (j = 0; j < rangelen; j++) {
ele = ln->obj; ele = ln->obj;
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
if (withscores) if (withscores)
addReplyDouble(c,ln->score); addReplyDouble(c,ln->score);
ln = reverse ? ln->backward : ln->forward[0]; ln = reverse ? ln->backward : ln->forward[0];
} }
}
}
} }
static void zrangeCommand(redisClient *c) { static void zrangeCommand(redisClient *c) {
@ -5831,9 +5702,7 @@ static void genericZrangebyscoreCommand(redisClient *c, int justcount) {
if (limit == 0) break; if (limit == 0) break;
if (!justcount) { if (!justcount) {
ele = ln->obj; ele = ln->obj;
addReplyBulkLen(c,ele); addReplyBulk(c,ele);
addReply(c,ele);
addReply(c,shared.crlf);
if (withscores) if (withscores)
addReplyDouble(c,ln->score); addReplyDouble(c,ln->score);
} }
@ -5863,34 +5732,21 @@ static void zcardCommand(redisClient *c) {
robj *o; robj *o;
zset *zs; zset *zs;
o = lookupKeyRead(c->db,c->argv[1]); if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
if (o == NULL) { checkType(c,o,REDIS_ZSET)) return;
addReply(c,shared.czero);
return;
} else {
if (o->type != REDIS_ZSET) {
addReply(c,shared.wrongtypeerr);
} else {
zs = o->ptr; zs = o->ptr;
addReplySds(c,sdscatprintf(sdsempty(),":%lu\r\n",zs->zsl->length)); addReplyUlong(c,zs->zsl->length);
}
}
} }
static void zscoreCommand(redisClient *c) { static void zscoreCommand(redisClient *c) {
robj *o; robj *o;
zset *zs; zset *zs;
o = lookupKeyRead(c->db,c->argv[1]);
if (o == NULL) {
addReply(c,shared.nullbulk);
return;
} else {
if (o->type != REDIS_ZSET) {
addReply(c,shared.wrongtypeerr);
} else {
dictEntry *de; dictEntry *de;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
checkType(c,o,REDIS_ZSET)) return;
zs = o->ptr; zs = o->ptr;
de = dictFind(zs->dict,c->argv[2]); de = dictFind(zs->dict,c->argv[2]);
if (!de) { if (!de) {
@ -5900,32 +5756,28 @@ static void zscoreCommand(redisClient *c) {
addReplyDouble(c,*score); addReplyDouble(c,*score);
} }
}
}
} }
static void zrankGenericCommand(redisClient *c, int reverse) { static void zrankGenericCommand(redisClient *c, int reverse) {
robj *o; robj *o;
o = lookupKeyRead(c->db,c->argv[1]); zset *zs;
if (o == NULL) { zskiplist *zsl;
addReply(c,shared.nullbulk);
return;
}
if (o->type != REDIS_ZSET) {
addReply(c,shared.wrongtypeerr);
} else {
zset *zs = o->ptr;
zskiplist *zsl = zs->zsl;
dictEntry *de; dictEntry *de;
unsigned long rank; unsigned long rank;
double *score;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
checkType(c,o,REDIS_ZSET)) return;
zs = o->ptr;
zsl = zs->zsl;
de = dictFind(zs->dict,c->argv[2]); de = dictFind(zs->dict,c->argv[2]);
if (!de) { if (!de) {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
return; return;
} }
double *score = dictGetEntryVal(de); score = dictGetEntryVal(de);
rank = zslGetRank(zsl, *score, c->argv[2]); rank = zslGetRank(zsl, *score, c->argv[2]);
if (rank) { if (rank) {
if (reverse) { if (reverse) {
@ -5936,7 +5788,6 @@ static void zrankGenericCommand(redisClient *c, int reverse) {
} else { } else {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
} }
}
} }
static void zrankCommand(redisClient *c) { static void zrankCommand(redisClient *c) {
@ -6006,16 +5857,10 @@ static void hsetCommand(redisClient *c) {
} }
static void hgetCommand(redisClient *c) { static void hgetCommand(redisClient *c) {
robj *o = lookupKeyRead(c->db,c->argv[1]); robj *o;
if (o == NULL) { if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
addReply(c,shared.nullbulk); checkType(c,o,REDIS_HASH)) return;
return;
} else {
if (o->type != REDIS_HASH) {
addReply(c,shared.wrongtypeerr);
return;
}
if (o->encoding == REDIS_ENCODING_ZIPMAP) { if (o->encoding == REDIS_ENCODING_ZIPMAP) {
unsigned char *zm = o->ptr; unsigned char *zm = o->ptr;
@ -6040,27 +5885,17 @@ static void hgetCommand(redisClient *c) {
} else { } else {
robj *e = dictGetEntryVal(de); robj *e = dictGetEntryVal(de);
addReplyBulkLen(c,e); addReplyBulk(c,e);
addReply(c,e);
addReply(c,shared.crlf);
}
} }
} }
} }
static void hdelCommand(redisClient *c) { static void hdelCommand(redisClient *c) {
robj *o = lookupKeyWrite(c->db,c->argv[1]); robj *o;
if (o == NULL) {
addReply(c,shared.czero);
return;
} else {
int deleted = 0; int deleted = 0;
if (o->type != REDIS_HASH) { if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
addReply(c,shared.wrongtypeerr); checkType(c,o,REDIS_HASH)) return;
return;
}
if (o->encoding == REDIS_ENCODING_ZIPMAP) { if (o->encoding == REDIS_ENCODING_ZIPMAP) {
o->ptr = zipmapDel((unsigned char*) o->ptr, o->ptr = zipmapDel((unsigned char*) o->ptr,
@ -6070,14 +5905,13 @@ static void hdelCommand(redisClient *c) {
deleted = dictDelete((dict*)o->ptr,c->argv[2]) == DICT_OK; deleted = dictDelete((dict*)o->ptr,c->argv[2]) == DICT_OK;
} }
addReply(c,deleted ? shared.cone : shared.czero); addReply(c,deleted ? shared.cone : shared.czero);
}
} }
static void hlenCommand(redisClient *c) { static void hlenCommand(redisClient *c) {
robj *o; robj *o;
unsigned long len; unsigned long len;
if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
checkType(c,o,REDIS_HASH)) return; checkType(c,o,REDIS_HASH)) return;
len = (o->encoding == REDIS_ENCODING_ZIPMAP) ? len = (o->encoding == REDIS_ENCODING_ZIPMAP) ?
@ -6410,11 +6244,7 @@ static void sortCommand(redisClient *c) {
listNode *ln; listNode *ln;
listIter li; listIter li;
if (!getop) { if (!getop) addReplyBulk(c,vector[j].obj);
addReplyBulkLen(c,vector[j].obj);
addReply(c,vector[j].obj);
addReply(c,shared.crlf);
}
listRewind(operations,&li); listRewind(operations,&li);
while((ln = listNext(&li))) { while((ln = listNext(&li))) {
redisSortOperation *sop = ln->value; redisSortOperation *sop = ln->value;
@ -6425,9 +6255,7 @@ static void sortCommand(redisClient *c) {
if (!val || val->type != REDIS_STRING) { if (!val || val->type != REDIS_STRING) {
addReply(c,shared.nullbulk); addReply(c,shared.nullbulk);
} else { } else {
addReplyBulkLen(c,val); addReplyBulk(c,val);
addReply(c,val);
addReply(c,shared.crlf);
} }
} else { } else {
redisAssert(sop->type == REDIS_SORT_GET); /* always fails */ redisAssert(sop->type == REDIS_SORT_GET); /* always fails */
@ -6945,12 +6773,8 @@ static int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele) {
receiver = ln->value; receiver = ln->value;
addReplySds(receiver,sdsnew("*2\r\n")); addReplySds(receiver,sdsnew("*2\r\n"));
addReplyBulkLen(receiver,key); addReplyBulk(receiver,key);
addReply(receiver,key); addReplyBulk(receiver,ele);
addReply(receiver,shared.crlf);
addReplyBulkLen(receiver,ele);
addReply(receiver,ele);
addReply(receiver,shared.crlf);
unblockClientWaitingData(receiver); unblockClientWaitingData(receiver);
return 1; return 1;
} }
@ -6989,9 +6813,7 @@ static void blockingPopGenericCommand(redisClient *c, int where) {
* for us. If this souds like an hack to you it's just * for us. If this souds like an hack to you it's just
* because it is... */ * because it is... */
addReplySds(c,sdsnew("*2\r\n")); addReplySds(c,sdsnew("*2\r\n"));
addReplyBulkLen(c,argv[1]); addReplyBulk(c,argv[1]);
addReply(c,argv[1]);
addReply(c,shared.crlf);
popGenericCommand(c,where); popGenericCommand(c,where);
/* Fix the client structure with the original stuff */ /* Fix the client structure with the original stuff */