Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
be02a7c0
Commit
be02a7c0
authored
May 31, 2010
by
Pieter Noordhuis
Browse files
update list iteration semantic to work as expected (i.e. "while(lNext(..))")
parent
6a8e35ad
Changes
1
Show whitespace changes
Inline
Side-by-side
redis.c
View file @
be02a7c0
...
@@ -4806,7 +4806,7 @@ static robj *lPop(robj *subject, int where) {
...
@@ -4806,7 +4806,7 @@ static robj *lPop(robj *subject, int where) {
value = createStringObjectFromLongLong(vval);
value = createStringObjectFromLongLong(vval);
}
}
}
}
subject->ptr = ziplistDelete(subject->ptr,&p
,ZIPLIST_TAIL
);
subject->ptr = ziplistDelete(subject->ptr,&p);
} else if (subject->encoding == REDIS_ENCODING_LIST) {
} else if (subject->encoding == REDIS_ENCODING_LIST) {
list *list = subject->ptr;
list *list = subject->ptr;
listNode *ln;
listNode *ln;
...
@@ -4840,15 +4840,24 @@ static unsigned long lLength(robj *subject) {
...
@@ -4840,15 +4840,24 @@ static unsigned long lLength(robj *subject) {
typedef struct {
typedef struct {
robj *subject;
robj *subject;
unsigned char encoding;
unsigned char encoding;
unsigned char direction; /* Iteration direction */
unsigned char *zi;
unsigned char *zi;
listNode *ln;
listNode *ln;
} lIterator;
} lIterator;
/* Structure for an entry while iterating over a list. */
typedef struct {
lIterator *li;
unsigned char *zi; /* Entry in ziplist */
listNode *ln; /* Entry in linked list */
} lEntry;
/* Initialize an iterator at the specified index. */
/* Initialize an iterator at the specified index. */
static lIterator *lInitIterator(robj *subject, int index) {
static lIterator *lInitIterator(robj *subject, int index
, unsigned char direction
) {
lIterator *li = zmalloc(sizeof(lIterator));
lIterator *li = zmalloc(sizeof(lIterator));
li->subject = subject;
li->subject = subject;
li->encoding = subject->encoding;
li->encoding = subject->encoding;
li->direction = direction;
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
li->zi = ziplistIndex(subject->ptr,index);
li->zi = ziplistIndex(subject->ptr,index);
} else if (li->encoding == REDIS_ENCODING_LIST) {
} else if (li->encoding == REDIS_ENCODING_LIST) {
...
@@ -4864,26 +4873,45 @@ static void lReleaseIterator(lIterator *li) {
...
@@ -4864,26 +4873,45 @@ static void lReleaseIterator(lIterator *li) {
zfree(li);
zfree(li);
}
}
/* Whether the entry pointed at is a valid entry. */
/* Stores pointer to current the entry in the provided entry structure
static int lIsEntry(lIterator *li) {
* and advances the position of the iterator. Returns 1 when the current
* entry is in fact an entry, 0 otherwise. */
static int lNext(lIterator *li, lEntry *entry) {
entry->li = li;
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
return li->zi != NULL;
entry->zi = li->zi;
if (entry->zi != NULL) {
if (li->direction == REDIS_TAIL)
li->zi = ziplistNext(li->subject->ptr,li->zi);
else
li->zi = ziplistPrev(li->subject->ptr,li->zi);
return 1;
}
} else if (li->encoding == REDIS_ENCODING_LIST) {
} else if (li->encoding == REDIS_ENCODING_LIST) {
return li->ln != NULL;
entry->ln = li->ln;
if (entry->ln != NULL) {
if (li->direction == REDIS_TAIL)
li->ln = li->ln->next;
else
li->ln = li->ln->prev;
return 1;
}
} else {
} else {
redisPanic("Unknown list encoding");
redisPanic("Unknown list encoding");
}
}
return 0;
}
}
/* Return entry or NULL at the current position of the iterator. */
/* Return entry or NULL at the current position of the iterator. */
static robj *lGet(lIterator *li) {
static robj *lGet(lEntry *entry) {
lIterator *li = entry->li;
robj *value = NULL;
robj *value = NULL;
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
char *v;
char *v;
unsigned int vlen;
unsigned int vlen;
long long vval;
long long vval;
redisAssert(
li
->zi != NULL);
redisAssert(
entry
->zi != NULL);
if (ziplistGet(
li
->zi,&v,&vlen,&vval)) {
if (ziplistGet(
entry
->zi,&v,&vlen,&vval)) {
if (v) {
if (v) {
value = createStringObject(v,vlen);
value = createStringObject(v,vlen);
} else {
} else {
...
@@ -4891,8 +4919,8 @@ static robj *lGet(lIterator *li) {
...
@@ -4891,8 +4919,8 @@ static robj *lGet(lIterator *li) {
}
}
}
}
} else if (li->encoding == REDIS_ENCODING_LIST) {
} else if (li->encoding == REDIS_ENCODING_LIST) {
redisAssert(
li
->ln != NULL);
redisAssert(
entry
->ln != NULL);
value = listNodeValue(
li
->ln);
value = listNodeValue(
entry
->ln);
incrRefCount(value);
incrRefCount(value);
} else {
} else {
redisPanic("Unknown list encoding");
redisPanic("Unknown list encoding");
...
@@ -4900,50 +4928,39 @@ static robj *lGet(lIterator *li) {
...
@@ -4900,50 +4928,39 @@ static robj *lGet(lIterator *li) {
return value;
return value;
}
}
/* Delete the element pointed to. */
static void lDelete(lIterator *li, int direction) {
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
direction = (direction == REDIS_HEAD) ? ZIPLIST_HEAD : ZIPLIST_TAIL;
li->subject->ptr = ziplistDelete(li->subject->ptr,&li->zi,direction);
} else if (li->encoding == REDIS_ENCODING_LIST) {
listNode *next;
if (direction == REDIS_HEAD)
next = li->ln->prev;
else
next = li->ln->next;
listDelNode(li->subject->ptr,li->ln);
li->ln = next;
} else {
redisPanic("Unknown list encoding");
}
}
/* Compare the given object with the entry at the current position. */
/* Compare the given object with the entry at the current position. */
static int lEqualTo(lIterator *li, robj *o) {
static int lEqual(lEntry *entry, robj *o) {
lIterator *li = entry->li;
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
redisAssert(o->encoding == REDIS_ENCODING_RAW);
redisAssert(o->encoding == REDIS_ENCODING_RAW);
return ziplistCompare(
li
->zi,o->ptr,sdslen(o->ptr));
return ziplistCompare(
entry
->zi,o->ptr,sdslen(o->ptr));
} else if (li->encoding == REDIS_ENCODING_LIST) {
} else if (li->encoding == REDIS_ENCODING_LIST) {
return equalStringObjects(o,listNodeValue(
li
->ln));
return equalStringObjects(o,listNodeValue(
entry
->ln));
} else {
} else {
redisPanic("Unknown list encoding");
redisPanic("Unknown list encoding");
}
}
}
}
/* Move to the next or previous entry in the list. */
/* Delete the element pointed to. */
static void lMove(lIterator *li, int where) {
static void lDelete(lEntry *entry) {
lIterator *li = entry->li;
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
redisAssert(li->zi != NULL);
unsigned char *p = entry->zi;
if (where == REDIS_HEAD)
li->subject->ptr = ziplistDelete(li->subject->ptr,&p);
li->zi = ziplistPrev(li->zi);
/* Update position of the iterator depending on the direction */
if (li->direction == REDIS_TAIL)
li->zi = p;
else
else
li->zi = ziplist
Next
(li->
zi
);
li->zi = ziplist
Prev
(li->
subject->ptr,p
);
} else if (li->encoding == REDIS_ENCODING_LIST) {
} else if (
entry->
li->encoding == REDIS_ENCODING_LIST) {
redisAssert(li->ln != NULL)
;
listNode *next
;
if (
where
== REDIS_
HEAD
)
if (
li->direction
== REDIS_
TAIL
)
li->ln = li
->ln->
prev
;
next = entry
->ln->
next
;
else
else
li->ln = li->ln->next;
next = entry->ln->prev;
listDelNode(li->subject->ptr,entry->ln);
li->ln = next;
} else {
} else {
redisPanic("Unknown list encoding");
redisPanic("Unknown list encoding");
}
}
...
@@ -5037,7 +5054,7 @@ static void lsetCommand(redisClient *c) {
...
@@ -5037,7 +5054,7 @@ static void lsetCommand(redisClient *c) {
if (p == NULL) {
if (p == NULL) {
addReply(c,shared.outofrangeerr);
addReply(c,shared.outofrangeerr);
} else {
} else {
o->ptr = ziplistDelete(o->ptr,&p
,ZIPLIST_TAIL
);
o->ptr = ziplistDelete(o->ptr,&p);
value = getDecodedObject(value);
value = getDecodedObject(value);
o->ptr = ziplistInsert(o->ptr,p,value->ptr,sdslen(value->ptr));
o->ptr = ziplistInsert(o->ptr,p,value->ptr,sdslen(value->ptr));
decrRefCount(value);
decrRefCount(value);
...
@@ -5089,6 +5106,7 @@ static void lrangeCommand(redisClient *c) {
...
@@ -5089,6 +5106,7 @@ static void lrangeCommand(redisClient *c) {
int end = atoi(c->argv[3]->ptr);
int end = atoi(c->argv[3]->ptr);
int llen;
int llen;
int rangelen, j;
int rangelen, j;
lEntry entry;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL
|| checkType(c,o,REDIS_LIST)) return;
|| checkType(c,o,REDIS_LIST)) return;
...
@@ -5111,12 +5129,12 @@ static void lrangeCommand(redisClient *c) {
...
@@ -5111,12 +5129,12 @@ static void lrangeCommand(redisClient *c) {
/* Return the result in form of a multi-bulk reply */
/* Return the result in form of a multi-bulk reply */
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",rangelen));
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",rangelen));
lIterator *li = lInitIterator(o,start);
lIterator *li = lInitIterator(o,start
,REDIS_TAIL
);
for (j = 0; j < rangelen; j++) {
for (j = 0; j < rangelen; j++) {
value = lGet(li
);
redisAssert(lNext(li,&entry)
);
redisAssert(
value
!
=
NULL
);
value =
lGet(&entry
);
addReplyBulk(c,value);
addReplyBulk(c,value);
lMove(li,REDIS_TAIL
);
decrRefCount(value
);
}
}
lReleaseIterator(li);
lReleaseIterator(li);
}
}
...
@@ -5177,7 +5195,7 @@ static void lremCommand(redisClient *c) {
...
@@ -5177,7 +5195,7 @@ static void lremCommand(redisClient *c) {
robj *subject, *obj = c->argv[3];
robj *subject, *obj = c->argv[3];
int toremove = atoi(c->argv[2]->ptr);
int toremove = atoi(c->argv[2]->ptr);
int removed = 0;
int removed = 0;
int direction
;
lEntry entry
;
subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero);
subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero);
if (subject == NULL || checkType(c,subject,REDIS_LIST)) return;
if (subject == NULL || checkType(c,subject,REDIS_LIST)) return;
...
@@ -5189,21 +5207,17 @@ static void lremCommand(redisClient *c) {
...
@@ -5189,21 +5207,17 @@ static void lremCommand(redisClient *c) {
lIterator *li;
lIterator *li;
if (toremove < 0) {
if (toremove < 0) {
toremove = -toremove;
toremove = -toremove;
direction = REDIS_HEAD;
li = lInitIterator(subject,-1,REDIS_HEAD);
li = lInitIterator(subject,-1);
} else {
} else {
direction = REDIS_TAIL;
li = lInitIterator(subject,0,REDIS_TAIL);
li = lInitIterator(subject,0);
}
}
while (l
IsEntry(li
)) {
while (l
Next(li,&entry
)) {
if (lEqual
To(li
,obj)) {
if (lEqual
(&entry
,obj)) {
lDelete(
li,direction
);
lDelete(
&entry
);
server.dirty++;
server.dirty++;
removed++;
removed++;
if (toremove && removed == toremove) break;
if (toremove && removed == toremove) break;
} else {
lMove(li,direction);
}
}
}
}
lReleaseIterator(li);
lReleaseIterator(li);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment