void pushGenericCommand(redisClient *c, int where) {
robj *lobj = lookupKeyWrite(c->db,c->argv[1]);
+ c->argv[2] = tryObjectEncoding(c->argv[2]);
if (lobj == NULL) {
if (handleClientsWaitingListPush(c,c->argv[1],c->argv[2])) {
addReply(c,shared.cone);
}
void lpushxCommand(redisClient *c) {
+ c->argv[2] = tryObjectEncoding(c->argv[2]);
pushxGenericCommand(c,NULL,c->argv[2],REDIS_HEAD);
}
void rpushxCommand(redisClient *c) {
+ c->argv[2] = tryObjectEncoding(c->argv[2]);
pushxGenericCommand(c,NULL,c->argv[2],REDIS_TAIL);
}
void linsertCommand(redisClient *c) {
+ c->argv[4] = tryObjectEncoding(c->argv[4]);
if (strcasecmp(c->argv[2]->ptr,"after") == 0) {
pushxGenericCommand(c,c->argv[3],c->argv[4],REDIS_TAIL);
} else if (strcasecmp(c->argv[2]->ptr,"before") == 0) {
robj *o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr);
if (o == NULL || checkType(c,o,REDIS_LIST)) return;
int index = atoi(c->argv[2]->ptr);
- robj *value = c->argv[3];
+ robj *value = (c->argv[3] = tryObjectEncoding(c->argv[3]));
listTypeTryConversion(o,value);
if (o->encoding == REDIS_ENCODING_ZIPLIST) {
}
void lrangeCommand(redisClient *c) {
- robj *o, *value;
+ robj *o;
int start = atoi(c->argv[2]->ptr);
int end = atoi(c->argv[3]->ptr);
int llen;
- int rangelen, j;
- listTypeEntry entry;
+ int rangelen;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL
|| checkType(c,o,REDIS_LIST)) return;
/* Return the result in form of a multi-bulk reply */
addReplyMultiBulkLen(c,rangelen);
- listTypeIterator *li = listTypeInitIterator(o,start,REDIS_TAIL);
- for (j = 0; j < rangelen; j++) {
- redisAssert(listTypeNext(li,&entry));
- value = listTypeGet(&entry);
- addReplyBulk(c,value);
- decrRefCount(value);
+ if (o->encoding == REDIS_ENCODING_ZIPLIST) {
+ unsigned char *p = ziplistIndex(o->ptr,start);
+ unsigned char *vstr;
+ unsigned int vlen;
+ long long vlong;
+
+ while(rangelen--) {
+ ziplistGet(p,&vstr,&vlen,&vlong);
+ if (vstr) {
+ addReplyBulkCBuffer(c,vstr,vlen);
+ } else {
+ addReplyBulkLongLong(c,vlong);
+ }
+ p = ziplistNext(o->ptr,p);
+ }
+ } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
+ listNode *ln = listIndex(o->ptr,start);
+
+ while(rangelen--) {
+ addReplyBulk(c,ln->value);
+ ln = ln->next;
+ }
+ } else {
+ redisPanic("List encoding is not LINKEDLIST nor ZIPLIST!");
}
- listTypeReleaseIterator(li);
}
void ltrimCommand(redisClient *c) {
}
void lremCommand(redisClient *c) {
- robj *subject, *obj = c->argv[3];
+ robj *subject, *obj;
+ obj = c->argv[3] = tryObjectEncoding(c->argv[3]);
int toremove = atoi(c->argv[2]->ptr);
int removed = 0;
listTypeEntry entry;
/* Blocking RPOP/LPOP */
void blockingPopGenericCommand(redisClient *c, int where) {
robj *o;
+ long long lltimeout;
time_t timeout;
int j;
+ /* Make sure timeout is an integer value */
+ if (getLongLongFromObjectOrReply(c,c->argv[c->argc-1],&lltimeout,
+ "timeout is not an integer") != REDIS_OK) return;
+
+ /* Make sure the timeout is not negative */
+ if (lltimeout < 0) {
+ addReplyError(c,"timeout is negative");
+ return;
+ }
+
for (j = 1; j < c->argc-1; j++) {
o = lookupKeyWrite(c->db,c->argv[j]);
if (o != NULL) {
}
}
}
+
+ /* If we are inside a MULTI/EXEC and the list is empty the only thing
+ * we can do is treating it as a timeout (even with timeout 0). */
+ if (c->flags & REDIS_MULTI) {
+ addReply(c,shared.nullmultibulk);
+ return;
+ }
+
/* If the list is empty or the key does not exists we must block */
- timeout = strtol(c->argv[c->argc-1]->ptr,NULL,10);
+ timeout = lltimeout;
if (timeout > 0) timeout += time(NULL);
blockForKeys(c,c->argv+1,c->argc-2,timeout);
}