}
int _ensureFileEvent(redisClient *c) {
+ if (c->fd <= 0) return REDIS_ERR;
if (c->bufpos == 0 && listLength(c->reply) == 0 &&
(c->replstate == REDIS_REPL_NONE ||
c->replstate == REDIS_REPL_ONLINE) &&
}
void addReplySds(redisClient *c, sds s) {
- if (_ensureFileEvent(c) != REDIS_OK) return;
+ if (_ensureFileEvent(c) != REDIS_OK) {
+ /* The caller expects the sds to be free'd. */
+ sdsfree(s);
+ return;
+ }
if (sdslen(s) < REDIS_REPLY_CHUNK_THRESHOLD) {
_addReplyStringToBuffer(c,s,sdslen(s));
sdsfree(s);
}
}
+/* 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;
_addReplyLongLong(c,ll,':');
}
-void addReplyUlong(redisClient *c, unsigned long ul) {
- _addReplyLongLong(c,(long long)ul,':');
+void addReplyMultiBulkLen(redisClient *c, long length) {
+ _addReplyLongLong(c,length,'*');
}
void addReplyBulkLen(redisClient *c, robj *obj) {