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

View File

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

View File

@ -603,6 +603,8 @@ void resetClient(redisClient *c);
void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask); void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask);
void sendReplyToClientWritev(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 addReply(redisClient *c, robj *obj);
void *addDeferredMultiBulkLength(redisClient *c);
void setDeferredMultiBulkLength(redisClient *c, void *node, long length);
void addReplySds(redisClient *c, sds s); void addReplySds(redisClient *c, sds s);
void processInputBuffer(redisClient *c); void processInputBuffer(redisClient *c);
void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask); 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) { void genericHgetallCommand(redisClient *c, int flags) {
robj *o, *lenobj, *obj; robj *o, *obj;
unsigned long count = 0; unsigned long count = 0;
hashTypeIterator *hi; hashTypeIterator *hi;
void *replylen = NULL;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL
|| checkType(c,o,REDIS_HASH)) return; || checkType(c,o,REDIS_HASH)) return;
lenobj = createObject(REDIS_STRING,NULL); replylen = addDeferredMultiBulkLength(c);
addReply(c,lenobj);
decrRefCount(lenobj);
hi = hashTypeInitIterator(o); hi = hashTypeInitIterator(o);
while (hashTypeNext(hi) != REDIS_ERR) { while (hashTypeNext(hi) != REDIS_ERR) {
if (flags & REDIS_HASH_KEY) { if (flags & REDIS_HASH_KEY) {
@ -377,8 +375,7 @@ void genericHgetallCommand(redisClient *c, int flags) {
} }
} }
hashTypeReleaseIterator(hi); hashTypeReleaseIterator(hi);
setDeferredMultiBulkLength(c,replylen,count);
lenobj->ptr = sdscatprintf(sdsempty(),"*%lu\r\n",count);
} }
void hkeysCommand(redisClient *c) { 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) { void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum, robj *dstkey) {
robj **sets = zmalloc(sizeof(robj*)*setnum); robj **sets = zmalloc(sizeof(robj*)*setnum);
setTypeIterator *si; setTypeIterator *si;
robj *ele, *lenobj = NULL, *dstset = NULL; robj *ele, *dstset = NULL;
void *replylen = NULL;
unsigned long j, cardinality = 0; unsigned long j, cardinality = 0;
for (j = 0; j < setnum; j++) { 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 * to the output list and save the pointer to later modify it with the
* right length */ * right length */
if (!dstkey) { if (!dstkey) {
lenobj = createObject(REDIS_STRING,NULL); replylen = addDeferredMultiBulkLength(c);
addReply(c,lenobj);
decrRefCount(lenobj);
} else { } else {
/* If we have a target key where to store the resulting set /* If we have a target key where to store the resulting set
* create this key with an empty set inside */ * 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); touchWatchedKey(c->db,dstkey);
server.dirty++; server.dirty++;
} else { } else {
lenobj->ptr = sdscatprintf(sdsempty(),"*%lu\r\n",cardinality); setDeferredMultiBulkLength(c,replylen,cardinality);
} }
zfree(sets); zfree(sets);
} }

View File

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