Wrapper for adding unknown multi bulk length to reply list

This commit is contained in:
Pieter Noordhuis 2010-08-30 16:02:06 +02:00
parent 834ef78e27
commit b301c1fc2b
7 changed files with 47 additions and 28 deletions

View File

@ -332,13 +332,10 @@ badfmt: /* Bad format errors */
void configGetCommand(redisClient *c) {
robj *o = getDecodedObject(c->argv[2]);
robj *lenobj = createObject(REDIS_STRING,NULL);
void *replylen = addDeferredMultiBulkLength(c);
char *pattern = o->ptr;
int matches = 0;
addReply(c,lenobj);
decrRefCount(lenobj);
if (stringmatch(pattern,"dbfilename",0)) {
addReplyBulkCString(c,"dbfilename");
addReplyBulkCString(c,server.dbfilename);
@ -410,7 +407,7 @@ void configGetCommand(redisClient *c) {
matches++;
}
decrRefCount(o);
lenobj->ptr = sdscatprintf(sdsempty(),"*%d\r\n",matches*2);
setDeferredMultiBulkLength(c,replylen,matches*2);
}
void configCommand(redisClient *c) {

View File

@ -223,11 +223,9 @@ void keysCommand(redisClient *c) {
sds pattern = c->argv[1]->ptr;
int plen = sdslen(pattern);
unsigned long numkeys = 0;
robj *lenobj = createObject(REDIS_STRING,NULL);
void *replylen = addDeferredMultiBulkLength(c);
di = dictGetIterator(c->db->dict);
addReply(c,lenobj);
decrRefCount(lenobj);
while((de = dictNext(di)) != NULL) {
sds key = dictGetEntryKey(de);
robj *keyobj;
@ -243,7 +241,7 @@ void keysCommand(redisClient *c) {
}
}
dictReleaseIterator(di);
lenobj->ptr = sdscatprintf(sdsempty(),"*%lu\r\n",numkeys);
setDeferredMultiBulkLength(c,replylen,numkeys);
}
void dbsizeCommand(redisClient *c) {

View File

@ -145,6 +145,34 @@ void addReplyString(redisClient *c, char *s, size_t len) {
}
}
/* Adds an empty object to the reply list that will contain the multi bulk
* length, which is not known when this function is called. */
void *addDeferredMultiBulkLength(redisClient *c) {
if (_ensureFileEvent(c) != REDIS_OK) return NULL;
_addReplyObjectToList(c,createObject(REDIS_STRING,NULL));
return listLast(c->reply);
}
/* Populate the length object and try glueing it to the next chunk. */
void setDeferredMultiBulkLength(redisClient *c, void *node, long length) {
listNode *ln = (listNode*)node;
robj *len, *next;
/* Abort when *node is NULL (see addDeferredMultiBulkLength). */
if (node == NULL) return;
len = listNodeValue(ln);
len->ptr = sdscatprintf(sdsempty(),"*%ld\r\n",length);
if (ln->next != NULL) {
next = listNodeValue(ln->next);
/* Only glue when the next node is a reply chunk. */
if (next->type == REDIS_REPLY_NODE) {
len->ptr = sdscatlen(len->ptr,next->ptr,sdslen(next->ptr));
listDelNode(c->reply,ln->next);
}
}
}
void addReplyDouble(redisClient *c, double d) {
char dbuf[128], sbuf[128];
int dlen, slen;

View File

@ -603,6 +603,8 @@ void resetClient(redisClient *c);
void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask);
void sendReplyToClientWritev(aeEventLoop *el, int fd, void *privdata, int mask);
void addReply(redisClient *c, robj *obj);
void *addDeferredMultiBulkLength(redisClient *c);
void setDeferredMultiBulkLength(redisClient *c, void *node, long length);
void addReplySds(redisClient *c, sds s);
void processInputBuffer(redisClient *c);
void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask);

View File

@ -350,17 +350,15 @@ void hlenCommand(redisClient *c) {
}
void genericHgetallCommand(redisClient *c, int flags) {
robj *o, *lenobj, *obj;
robj *o, *obj;
unsigned long count = 0;
hashTypeIterator *hi;
void *replylen = NULL;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL
|| checkType(c,o,REDIS_HASH)) return;
lenobj = createObject(REDIS_STRING,NULL);
addReply(c,lenobj);
decrRefCount(lenobj);
replylen = addDeferredMultiBulkLength(c);
hi = hashTypeInitIterator(o);
while (hashTypeNext(hi) != REDIS_ERR) {
if (flags & REDIS_HASH_KEY) {
@ -377,8 +375,7 @@ void genericHgetallCommand(redisClient *c, int flags) {
}
}
hashTypeReleaseIterator(hi);
lenobj->ptr = sdscatprintf(sdsempty(),"*%lu\r\n",count);
setDeferredMultiBulkLength(c,replylen,count);
}
void hkeysCommand(redisClient *c) {

View File

@ -320,7 +320,8 @@ int qsortCompareSetsByCardinality(const void *s1, const void *s2) {
void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum, robj *dstkey) {
robj **sets = zmalloc(sizeof(robj*)*setnum);
setTypeIterator *si;
robj *ele, *lenobj = NULL, *dstset = NULL;
robj *ele, *dstset = NULL;
void *replylen = NULL;
unsigned long j, cardinality = 0;
for (j = 0; j < setnum; j++) {
@ -356,9 +357,7 @@ void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum,
* to the output list and save the pointer to later modify it with the
* right length */
if (!dstkey) {
lenobj = createObject(REDIS_STRING,NULL);
addReply(c,lenobj);
decrRefCount(lenobj);
replylen = addDeferredMultiBulkLength(c);
} else {
/* If we have a target key where to store the resulting set
* create this key with an empty set inside */
@ -400,7 +399,7 @@ void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum,
touchWatchedKey(c->db,dstkey);
server.dirty++;
} else {
lenobj->ptr = sdscatprintf(sdsempty(),"*%lu\r\n",cardinality);
setDeferredMultiBulkLength(c,replylen,cardinality);
}
zfree(sets);
}

View File

@ -866,7 +866,8 @@ void genericZrangebyscoreCommand(redisClient *c, int justcount) {
zset *zsetobj = o->ptr;
zskiplist *zsl = zsetobj->zsl;
zskiplistNode *ln;
robj *ele, *lenobj = NULL;
robj *ele;
void *replylen = NULL;
unsigned long rangelen = 0;
/* Get the first node with the score >= min, or with
@ -884,11 +885,8 @@ void genericZrangebyscoreCommand(redisClient *c, int justcount) {
* are in the list, so we push this object that will represent
* the multi-bulk length in the output buffer, and will "fix"
* it later */
if (!justcount) {
lenobj = createObject(REDIS_STRING,NULL);
addReply(c,lenobj);
decrRefCount(lenobj);
}
if (!justcount)
replylen = addDeferredMultiBulkLength(c);
while(ln && (maxex ? (ln->score < max) : (ln->score <= max))) {
if (offset) {
@ -910,7 +908,7 @@ void genericZrangebyscoreCommand(redisClient *c, int justcount) {
if (justcount) {
addReplyLongLong(c,(long)rangelen);
} else {
lenobj->ptr = sdscatprintf(sdsempty(),"*%lu\r\n",
setDeferredMultiBulkLength(c,replylen,
withscores ? (rangelen*2) : rangelen);
}
}