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