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
aaada3f9
Commit
aaada3f9
authored
Aug 20, 2010
by
Pieter Noordhuis
Browse files
Merge branch 'master' into intset-split
Conflicts: src/Makefile src/t_set.c
parents
2767f1c0
cbce5171
Changes
37
Hide whitespace changes
Inline
Side-by-side
src/t_set.c
View file @
aaada3f9
...
@@ -188,6 +188,7 @@ void saddCommand(redisClient *c) {
...
@@ -188,6 +188,7 @@ void saddCommand(redisClient *c) {
}
}
}
}
if
(
setTypeAdd
(
set
,
c
->
argv
[
2
]))
{
if
(
setTypeAdd
(
set
,
c
->
argv
[
2
]))
{
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
addReply
(
c
,
shared
.
cone
);
addReply
(
c
,
shared
.
cone
);
}
else
{
}
else
{
...
@@ -203,6 +204,7 @@ void sremCommand(redisClient *c) {
...
@@ -203,6 +204,7 @@ void sremCommand(redisClient *c) {
if
(
setTypeRemove
(
set
,
c
->
argv
[
2
]))
{
if
(
setTypeRemove
(
set
,
c
->
argv
[
2
]))
{
if
(
setTypeSize
(
set
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
if
(
setTypeSize
(
set
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
addReply
(
c
,
shared
.
cone
);
addReply
(
c
,
shared
.
cone
);
}
else
{
}
else
{
...
@@ -241,6 +243,8 @@ void smoveCommand(redisClient *c) {
...
@@ -241,6 +243,8 @@ void smoveCommand(redisClient *c) {
/* Remove the src set from the database when empty */
/* Remove the src set from the database when empty */
if
(
setTypeSize
(
srcset
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
if
(
setTypeSize
(
srcset
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
2
]);
server
.
dirty
++
;
server
.
dirty
++
;
/* Create the destination set when it doesn't exist */
/* Create the destination set when it doesn't exist */
...
@@ -289,6 +293,7 @@ void spopCommand(redisClient *c) {
...
@@ -289,6 +293,7 @@ void spopCommand(redisClient *c) {
addReplyBulk
(
c
,
ele
);
addReplyBulk
(
c
,
ele
);
decrRefCount
(
ele
);
decrRefCount
(
ele
);
if
(
setTypeSize
(
set
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
if
(
setTypeSize
(
set
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
}
}
}
}
...
@@ -325,8 +330,10 @@ void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum,
...
@@ -325,8 +330,10 @@ void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum,
if
(
!
setobj
)
{
if
(
!
setobj
)
{
zfree
(
sets
);
zfree
(
sets
);
if
(
dstkey
)
{
if
(
dstkey
)
{
if
(
dbDelete
(
c
->
db
,
dstkey
))
if
(
dbDelete
(
c
->
db
,
dstkey
))
{
touchWatchedKey
(
c
->
db
,
dstkey
);
server
.
dirty
++
;
server
.
dirty
++
;
}
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
}
else
{
}
else
{
addReply
(
c
,
shared
.
emptymultibulk
);
addReply
(
c
,
shared
.
emptymultibulk
);
...
@@ -390,6 +397,7 @@ void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum,
...
@@ -390,6 +397,7 @@ void sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum,
decrRefCount
(
dstset
);
decrRefCount
(
dstset
);
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
}
}
touchWatchedKey
(
c
->
db
,
dstkey
);
server
.
dirty
++
;
server
.
dirty
++
;
}
else
{
}
else
{
lenobj
->
ptr
=
sdscatprintf
(
sdsempty
(),
"*%lu
\r\n
"
,
cardinality
);
lenobj
->
ptr
=
sdscatprintf
(
sdsempty
(),
"*%lu
\r\n
"
,
cardinality
);
...
@@ -481,6 +489,7 @@ void sunionDiffGenericCommand(redisClient *c, robj **setkeys, int setnum, robj *
...
@@ -481,6 +489,7 @@ void sunionDiffGenericCommand(redisClient *c, robj **setkeys, int setnum, robj *
decrRefCount
(
dstset
);
decrRefCount
(
dstset
);
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
}
}
touchWatchedKey
(
c
->
db
,
dstkey
);
server
.
dirty
++
;
server
.
dirty
++
;
}
}
zfree
(
sets
);
zfree
(
sets
);
...
...
src/t_string.c
View file @
aaada3f9
...
@@ -17,8 +17,6 @@ void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expir
...
@@ -17,8 +17,6 @@ void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expir
}
}
}
}
touchWatchedKey
(
c
->
db
,
key
);
if
(
nx
)
deleteIfVolatile
(
c
->
db
,
key
);
retval
=
dbAdd
(
c
->
db
,
key
,
val
);
retval
=
dbAdd
(
c
->
db
,
key
,
val
);
if
(
retval
==
REDIS_ERR
)
{
if
(
retval
==
REDIS_ERR
)
{
if
(
!
nx
)
{
if
(
!
nx
)
{
...
@@ -31,6 +29,7 @@ void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expir
...
@@ -31,6 +29,7 @@ void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expir
}
else
{
}
else
{
incrRefCount
(
val
);
incrRefCount
(
val
);
}
}
touchWatchedKey
(
c
->
db
,
key
);
server
.
dirty
++
;
server
.
dirty
++
;
removeExpire
(
c
->
db
,
key
);
removeExpire
(
c
->
db
,
key
);
if
(
expire
)
setExpire
(
c
->
db
,
key
,
time
(
NULL
)
+
seconds
);
if
(
expire
)
setExpire
(
c
->
db
,
key
,
time
(
NULL
)
+
seconds
);
...
@@ -72,6 +71,7 @@ void getsetCommand(redisClient *c) {
...
@@ -72,6 +71,7 @@ void getsetCommand(redisClient *c) {
if
(
getGenericCommand
(
c
)
==
REDIS_ERR
)
return
;
if
(
getGenericCommand
(
c
)
==
REDIS_ERR
)
return
;
dbReplace
(
c
->
db
,
c
->
argv
[
1
],
c
->
argv
[
2
]);
dbReplace
(
c
->
db
,
c
->
argv
[
1
],
c
->
argv
[
2
]);
incrRefCount
(
c
->
argv
[
2
]);
incrRefCount
(
c
->
argv
[
2
]);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
removeExpire
(
c
->
db
,
c
->
argv
[
1
]);
removeExpire
(
c
->
db
,
c
->
argv
[
1
]);
}
}
...
@@ -120,6 +120,7 @@ void msetGenericCommand(redisClient *c, int nx) {
...
@@ -120,6 +120,7 @@ void msetGenericCommand(redisClient *c, int nx) {
dbReplace
(
c
->
db
,
c
->
argv
[
j
],
c
->
argv
[
j
+
1
]);
dbReplace
(
c
->
db
,
c
->
argv
[
j
],
c
->
argv
[
j
+
1
]);
incrRefCount
(
c
->
argv
[
j
+
1
]);
incrRefCount
(
c
->
argv
[
j
+
1
]);
removeExpire
(
c
->
db
,
c
->
argv
[
j
]);
removeExpire
(
c
->
db
,
c
->
argv
[
j
]);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
j
]);
}
}
server
.
dirty
+=
(
c
->
argc
-
1
)
/
2
;
server
.
dirty
+=
(
c
->
argc
-
1
)
/
2
;
addReply
(
c
,
nx
?
shared
.
cone
:
shared
.
ok
);
addReply
(
c
,
nx
?
shared
.
cone
:
shared
.
ok
);
...
@@ -144,6 +145,7 @@ void incrDecrCommand(redisClient *c, long long incr) {
...
@@ -144,6 +145,7 @@ void incrDecrCommand(redisClient *c, long long incr) {
value
+=
incr
;
value
+=
incr
;
o
=
createStringObjectFromLongLong
(
value
);
o
=
createStringObjectFromLongLong
(
value
);
dbReplace
(
c
->
db
,
c
->
argv
[
1
],
o
);
dbReplace
(
c
->
db
,
c
->
argv
[
1
],
o
);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
addReply
(
c
,
shared
.
colon
);
addReply
(
c
,
shared
.
colon
);
addReply
(
c
,
o
);
addReply
(
c
,
o
);
...
@@ -207,6 +209,7 @@ void appendCommand(redisClient *c) {
...
@@ -207,6 +209,7 @@ void appendCommand(redisClient *c) {
}
}
totlen
=
sdslen
(
o
->
ptr
);
totlen
=
sdslen
(
o
->
ptr
);
}
}
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
":%lu
\r\n
"
,(
unsigned
long
)
totlen
));
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
":%lu
\r\n
"
,(
unsigned
long
)
totlen
));
}
}
...
@@ -248,4 +251,13 @@ void substrCommand(redisClient *c) {
...
@@ -248,4 +251,13 @@ void substrCommand(redisClient *c) {
decrRefCount
(
o
);
decrRefCount
(
o
);
}
}
void
strlenCommand
(
redisClient
*
c
)
{
robj
*
o
;
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
czero
))
==
NULL
||
checkType
(
c
,
o
,
REDIS_STRING
))
return
;
o
=
getDecodedObject
(
o
);
addReplyLongLong
(
c
,
sdslen
(
o
->
ptr
));
decrRefCount
(
o
);
}
src/t_zset.c
View file @
aaada3f9
...
@@ -327,11 +327,6 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
...
@@ -327,11 +327,6 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
zset
*
zs
;
zset
*
zs
;
double
*
score
;
double
*
score
;
if
(
isnan
(
scoreval
))
{
addReplySds
(
c
,
sdsnew
(
"-ERR provide score is Not A Number (nan)
\r\n
"
));
return
;
}
zsetobj
=
lookupKeyWrite
(
c
->
db
,
key
);
zsetobj
=
lookupKeyWrite
(
c
->
db
,
key
);
if
(
zsetobj
==
NULL
)
{
if
(
zsetobj
==
NULL
)
{
zsetobj
=
createZsetObject
();
zsetobj
=
createZsetObject
();
...
@@ -361,7 +356,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
...
@@ -361,7 +356,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
}
}
if
(
isnan
(
*
score
))
{
if
(
isnan
(
*
score
))
{
addReplySds
(
c
,
addReplySds
(
c
,
sdsnew
(
"-ERR resulting score is
N
ot
A N
umber (
nan
)
\r\n
"
));
sdsnew
(
"-ERR resulting score is
n
ot
a n
umber (
NaN
)
\r\n
"
));
zfree
(
score
);
zfree
(
score
);
/* Note that we don't need to check if the zset may be empty and
/* Note that we don't need to check if the zset may be empty and
* should be removed here, as we can only obtain Nan as score if
* should be removed here, as we can only obtain Nan as score if
...
@@ -379,6 +374,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
...
@@ -379,6 +374,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
incrRefCount
(
ele
);
/* added to hash */
incrRefCount
(
ele
);
/* added to hash */
zslInsert
(
zs
->
zsl
,
*
score
,
ele
);
zslInsert
(
zs
->
zsl
,
*
score
,
ele
);
incrRefCount
(
ele
);
/* added to skiplist */
incrRefCount
(
ele
);
/* added to skiplist */
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
if
(
doincrement
)
if
(
doincrement
)
addReplyDouble
(
c
,
*
score
);
addReplyDouble
(
c
,
*
score
);
...
@@ -402,6 +398,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
...
@@ -402,6 +398,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
incrRefCount
(
ele
);
incrRefCount
(
ele
);
/* Update the score in the hash table */
/* Update the score in the hash table */
dictReplace
(
zs
->
dict
,
ele
,
score
);
dictReplace
(
zs
->
dict
,
ele
,
score
);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
}
else
{
}
else
{
zfree
(
score
);
zfree
(
score
);
...
@@ -415,15 +412,13 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
...
@@ -415,15 +412,13 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
void
zaddCommand
(
redisClient
*
c
)
{
void
zaddCommand
(
redisClient
*
c
)
{
double
scoreval
;
double
scoreval
;
if
(
getDoubleFromObjectOrReply
(
c
,
c
->
argv
[
2
],
&
scoreval
,
NULL
)
!=
REDIS_OK
)
return
;
if
(
getDoubleFromObjectOrReply
(
c
,
c
->
argv
[
2
],
&
scoreval
,
NULL
)
!=
REDIS_OK
)
return
;
zaddGenericCommand
(
c
,
c
->
argv
[
1
],
c
->
argv
[
3
],
scoreval
,
0
);
zaddGenericCommand
(
c
,
c
->
argv
[
1
],
c
->
argv
[
3
],
scoreval
,
0
);
}
}
void
zincrbyCommand
(
redisClient
*
c
)
{
void
zincrbyCommand
(
redisClient
*
c
)
{
double
scoreval
;
double
scoreval
;
if
(
getDoubleFromObjectOrReply
(
c
,
c
->
argv
[
2
],
&
scoreval
,
NULL
)
!=
REDIS_OK
)
return
;
if
(
getDoubleFromObjectOrReply
(
c
,
c
->
argv
[
2
],
&
scoreval
,
NULL
)
!=
REDIS_OK
)
return
;
zaddGenericCommand
(
c
,
c
->
argv
[
1
],
c
->
argv
[
3
],
scoreval
,
1
);
zaddGenericCommand
(
c
,
c
->
argv
[
1
],
c
->
argv
[
3
],
scoreval
,
1
);
}
}
...
@@ -452,6 +447,7 @@ void zremCommand(redisClient *c) {
...
@@ -452,6 +447,7 @@ void zremCommand(redisClient *c) {
dictDelete
(
zs
->
dict
,
c
->
argv
[
2
]);
dictDelete
(
zs
->
dict
,
c
->
argv
[
2
]);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
dictSize
(
zs
->
dict
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
if
(
dictSize
(
zs
->
dict
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
++
;
server
.
dirty
++
;
addReply
(
c
,
shared
.
cone
);
addReply
(
c
,
shared
.
cone
);
}
}
...
@@ -473,6 +469,7 @@ void zremrangebyscoreCommand(redisClient *c) {
...
@@ -473,6 +469,7 @@ void zremrangebyscoreCommand(redisClient *c) {
deleted
=
zslDeleteRangeByScore
(
zs
->
zsl
,
min
,
max
,
zs
->
dict
);
deleted
=
zslDeleteRangeByScore
(
zs
->
zsl
,
min
,
max
,
zs
->
dict
);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
dictSize
(
zs
->
dict
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
if
(
dictSize
(
zs
->
dict
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
if
(
deleted
)
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
+=
deleted
;
server
.
dirty
+=
deleted
;
addReplyLongLong
(
c
,
deleted
);
addReplyLongLong
(
c
,
deleted
);
}
}
...
@@ -497,9 +494,9 @@ void zremrangebyrankCommand(redisClient *c) {
...
@@ -497,9 +494,9 @@ void zremrangebyrankCommand(redisClient *c) {
if
(
start
<
0
)
start
=
llen
+
start
;
if
(
start
<
0
)
start
=
llen
+
start
;
if
(
end
<
0
)
end
=
llen
+
end
;
if
(
end
<
0
)
end
=
llen
+
end
;
if
(
start
<
0
)
start
=
0
;
if
(
start
<
0
)
start
=
0
;
if
(
end
<
0
)
end
=
0
;
/* indexes sanity checks */
/* Invariant: start >= 0, so this test will be true when end < 0.
* The range is empty when start > end or start >= length. */
if
(
start
>
end
||
start
>=
llen
)
{
if
(
start
>
end
||
start
>=
llen
)
{
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
return
;
return
;
...
@@ -511,6 +508,7 @@ void zremrangebyrankCommand(redisClient *c) {
...
@@ -511,6 +508,7 @@ void zremrangebyrankCommand(redisClient *c) {
deleted
=
zslDeleteRangeByRank
(
zs
->
zsl
,
start
+
1
,
end
+
1
,
zs
->
dict
);
deleted
=
zslDeleteRangeByRank
(
zs
->
zsl
,
start
+
1
,
end
+
1
,
zs
->
dict
);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
dictSize
(
zs
->
dict
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
if
(
dictSize
(
zs
->
dict
)
==
0
)
dbDelete
(
c
->
db
,
c
->
argv
[
1
]);
if
(
deleted
)
touchWatchedKey
(
c
->
db
,
c
->
argv
[
1
]);
server
.
dirty
+=
deleted
;
server
.
dirty
+=
deleted
;
addReplyLongLong
(
c
,
deleted
);
addReplyLongLong
(
c
,
deleted
);
}
}
...
@@ -536,6 +534,10 @@ int qsortCompareZsetopsrcByCardinality(const void *s1, const void *s2) {
...
@@ -536,6 +534,10 @@ int qsortCompareZsetopsrcByCardinality(const void *s1, const void *s2) {
inline
static
void
zunionInterAggregate
(
double
*
target
,
double
val
,
int
aggregate
)
{
inline
static
void
zunionInterAggregate
(
double
*
target
,
double
val
,
int
aggregate
)
{
if
(
aggregate
==
REDIS_AGGR_SUM
)
{
if
(
aggregate
==
REDIS_AGGR_SUM
)
{
*
target
=
*
target
+
val
;
*
target
=
*
target
+
val
;
/* The result of adding two doubles is NaN when one variable
* is +inf and the other is -inf. When these numbers are added,
* we maintain the convention of the result being 0.0. */
if
(
isnan
(
*
target
))
*
target
=
0
.
0
;
}
else
if
(
aggregate
==
REDIS_AGGR_MIN
)
{
}
else
if
(
aggregate
==
REDIS_AGGR_MIN
)
{
*
target
=
val
<
*
target
?
val
:
*
target
;
*
target
=
val
<
*
target
?
val
:
*
target
;
}
else
if
(
aggregate
==
REDIS_AGGR_MAX
)
{
}
else
if
(
aggregate
==
REDIS_AGGR_MAX
)
{
...
@@ -554,6 +556,7 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
...
@@ -554,6 +556,7 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
zset
*
dstzset
;
zset
*
dstzset
;
dictIterator
*
di
;
dictIterator
*
di
;
dictEntry
*
de
;
dictEntry
*
de
;
int
touched
=
0
;
/* expect setnum input keys to be given */
/* expect setnum input keys to be given */
setnum
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
setnum
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
...
@@ -598,8 +601,12 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
...
@@ -598,8 +601,12 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
if
(
remaining
>=
(
setnum
+
1
)
&&
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"weights"
))
{
if
(
remaining
>=
(
setnum
+
1
)
&&
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"weights"
))
{
j
++
;
remaining
--
;
j
++
;
remaining
--
;
for
(
i
=
0
;
i
<
setnum
;
i
++
,
j
++
,
remaining
--
)
{
for
(
i
=
0
;
i
<
setnum
;
i
++
,
j
++
,
remaining
--
)
{
if
(
getDoubleFromObjectOrReply
(
c
,
c
->
argv
[
j
],
&
src
[
i
].
weight
,
NULL
)
!=
REDIS_OK
)
if
(
getDoubleFromObjectOrReply
(
c
,
c
->
argv
[
j
],
&
src
[
i
].
weight
,
"weight value is not a double"
)
!=
REDIS_OK
)
{
zfree
(
src
);
return
;
return
;
}
}
}
}
else
if
(
remaining
>=
2
&&
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"aggregate"
))
{
}
else
if
(
remaining
>=
2
&&
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"aggregate"
))
{
j
++
;
remaining
--
;
j
++
;
remaining
--
;
...
@@ -698,10 +705,15 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
...
@@ -698,10 +705,15 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
redisAssert
(
op
==
REDIS_OP_INTER
||
op
==
REDIS_OP_UNION
);
redisAssert
(
op
==
REDIS_OP_INTER
||
op
==
REDIS_OP_UNION
);
}
}
dbDelete
(
c
->
db
,
dstkey
);
if
(
dbDelete
(
c
->
db
,
dstkey
))
{
touchWatchedKey
(
c
->
db
,
dstkey
);
touched
=
1
;
server
.
dirty
++
;
}
if
(
dstzset
->
zsl
->
length
)
{
if
(
dstzset
->
zsl
->
length
)
{
dbAdd
(
c
->
db
,
dstkey
,
dstobj
);
dbAdd
(
c
->
db
,
dstkey
,
dstobj
);
addReplyLongLong
(
c
,
dstzset
->
zsl
->
length
);
addReplyLongLong
(
c
,
dstzset
->
zsl
->
length
);
if
(
!
touched
)
touchWatchedKey
(
c
->
db
,
dstkey
);
server
.
dirty
++
;
server
.
dirty
++
;
}
else
{
}
else
{
decrRefCount
(
dstobj
);
decrRefCount
(
dstobj
);
...
@@ -750,11 +762,10 @@ void zrangeGenericCommand(redisClient *c, int reverse) {
...
@@ -750,11 +762,10 @@ void zrangeGenericCommand(redisClient *c, int reverse) {
if
(
start
<
0
)
start
=
llen
+
start
;
if
(
start
<
0
)
start
=
llen
+
start
;
if
(
end
<
0
)
end
=
llen
+
end
;
if
(
end
<
0
)
end
=
llen
+
end
;
if
(
start
<
0
)
start
=
0
;
if
(
start
<
0
)
start
=
0
;
if
(
end
<
0
)
end
=
0
;
/* indexes sanity checks */
/* Invariant: start >= 0, so this test will be true when end < 0.
* The range is empty when start > end or start >= length. */
if
(
start
>
end
||
start
>=
llen
)
{
if
(
start
>
end
||
start
>=
llen
)
{
/* Out of range start or start > end result in empty list */
addReply
(
c
,
shared
.
emptymultibulk
);
addReply
(
c
,
shared
.
emptymultibulk
);
return
;
return
;
}
}
...
...
src/vm.c
View file @
aaada3f9
...
@@ -86,10 +86,9 @@ void vmInit(void) {
...
@@ -86,10 +86,9 @@ void vmInit(void) {
}
else
{
}
else
{
redisLog
(
REDIS_NOTICE
,
"Swap file allocated with success"
);
redisLog
(
REDIS_NOTICE
,
"Swap file allocated with success"
);
}
}
server
.
vm_bitmap
=
z
m
alloc
((
server
.
vm_pages
+
7
)
/
8
);
server
.
vm_bitmap
=
z
c
alloc
((
server
.
vm_pages
+
7
)
/
8
);
redisLog
(
REDIS_VERBOSE
,
"Allocated %lld bytes page table for %lld pages"
,
redisLog
(
REDIS_VERBOSE
,
"Allocated %lld bytes page table for %lld pages"
,
(
long
long
)
(
server
.
vm_pages
+
7
)
/
8
,
server
.
vm_pages
);
(
long
long
)
(
server
.
vm_pages
+
7
)
/
8
,
server
.
vm_pages
);
memset
(
server
.
vm_bitmap
,
0
,(
server
.
vm_pages
+
7
)
/
8
);
/* Initialize threaded I/O (used by Virtual Memory) */
/* Initialize threaded I/O (used by Virtual Memory) */
server
.
io_newjobs
=
listCreate
();
server
.
io_newjobs
=
listCreate
();
...
@@ -1075,6 +1074,11 @@ int dontWaitForSwappedKey(redisClient *c, robj *key) {
...
@@ -1075,6 +1074,11 @@ int dontWaitForSwappedKey(redisClient *c, robj *key) {
listIter
li
;
listIter
li
;
struct
dictEntry
*
de
;
struct
dictEntry
*
de
;
/* The key object might be destroyed when deleted from the c->io_keys
* list (and the "key" argument is physically the same object as the
* object inside the list), so we need to protect it. */
incrRefCount
(
key
);
/* Remove the key from the list of keys this client is waiting for. */
/* Remove the key from the list of keys this client is waiting for. */
listRewind
(
c
->
io_keys
,
&
li
);
listRewind
(
c
->
io_keys
,
&
li
);
while
((
ln
=
listNext
(
&
li
))
!=
NULL
)
{
while
((
ln
=
listNext
(
&
li
))
!=
NULL
)
{
...
@@ -1095,6 +1099,7 @@ int dontWaitForSwappedKey(redisClient *c, robj *key) {
...
@@ -1095,6 +1099,7 @@ int dontWaitForSwappedKey(redisClient *c, robj *key) {
if
(
listLength
(
l
)
==
0
)
if
(
listLength
(
l
)
==
0
)
dictDelete
(
c
->
db
->
io_keys
,
key
);
dictDelete
(
c
->
db
->
io_keys
,
key
);
decrRefCount
(
key
);
return
listLength
(
c
->
io_keys
)
==
0
;
return
listLength
(
c
->
io_keys
)
==
0
;
}
}
...
...
src/ziplist.c
View file @
aaada3f9
...
@@ -23,6 +23,8 @@
...
@@ -23,6 +23,8 @@
#include "zmalloc.h"
#include "zmalloc.h"
#include "ziplist.h"
#include "ziplist.h"
int
ll2string
(
char
*
s
,
size_t
len
,
long
long
value
);
/* Important note: the ZIP_END value is used to depict the end of the
/* Important note: the ZIP_END value is used to depict the end of the
* ziplist structure. When a pointer contains an entry, the first couple
* ziplist structure. When a pointer contains an entry, the first couple
* of bytes contain the encoded length of the previous entry. This length
* of bytes contain the encoded length of the previous entry. This length
...
@@ -174,15 +176,27 @@ static int zipPrevLenByteDiff(unsigned char *p, unsigned int len) {
...
@@ -174,15 +176,27 @@ static int zipPrevLenByteDiff(unsigned char *p, unsigned int len) {
}
}
/* Check if string pointed to by 'entry' can be encoded as an integer.
/* Check if string pointed to by 'entry' can be encoded as an integer.
* Stores the integer value in 'v' and its encoding in 'encoding'.
* Stores the integer value in 'v' and its encoding in 'encoding'. */
* Warning: this function requires a NULL-terminated string! */
static
int
zipTryEncoding
(
unsigned
char
*
entry
,
unsigned
int
entrylen
,
long
long
*
v
,
unsigned
char
*
encoding
)
{
static
int
zipTryEncoding
(
unsigned
char
*
entry
,
long
long
*
v
,
unsigned
char
*
encoding
)
{
long
long
value
;
long
long
value
;
char
*
eptr
;
char
*
eptr
;
char
buf
[
32
];
if
(
entrylen
>=
32
||
entrylen
==
0
)
return
0
;
if
(
entry
[
0
]
==
'-'
||
(
entry
[
0
]
>=
'0'
&&
entry
[
0
]
<=
'9'
))
{
if
(
entry
[
0
]
==
'-'
||
(
entry
[
0
]
>=
'0'
&&
entry
[
0
]
<=
'9'
))
{
value
=
strtoll
((
char
*
)
entry
,
&
eptr
,
10
);
int
slen
;
/* Perform a back-and-forth conversion to make sure that
* the string turned into an integer is not losing any info. */
memcpy
(
buf
,
entry
,
entrylen
);
buf
[
entrylen
]
=
'\0'
;
value
=
strtoll
(
buf
,
&
eptr
,
10
);
if
(
eptr
[
0
]
!=
'\0'
)
return
0
;
if
(
eptr
[
0
]
!=
'\0'
)
return
0
;
slen
=
ll2string
(
buf
,
32
,
value
);
if
(
entrylen
!=
(
unsigned
)
slen
||
memcmp
(
buf
,
entry
,
slen
))
return
0
;
/* Great, the string can be encoded. Check what's the smallest
* of our encoding types that can hold this value. */
if
(
value
>=
INT16_MIN
&&
value
<=
INT16_MAX
)
{
if
(
value
>=
INT16_MIN
&&
value
<=
INT16_MAX
)
{
*
encoding
=
ZIP_ENC_INT16
;
*
encoding
=
ZIP_ENC_INT16
;
}
else
if
(
value
>=
INT32_MIN
&&
value
<=
INT32_MAX
)
{
}
else
if
(
value
>=
INT32_MIN
&&
value
<=
INT32_MAX
)
{
...
@@ -329,7 +343,7 @@ static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsig
...
@@ -329,7 +343,7 @@ static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsig
}
}
/* See if the entry can be encoded */
/* See if the entry can be encoded */
if
(
zipTryEncoding
(
s
,
&
value
,
&
encoding
))
{
if
(
zipTryEncoding
(
s
,
slen
,
&
value
,
&
encoding
))
{
reqlen
=
zipEncodingSize
(
encoding
);
reqlen
=
zipEncodingSize
(
encoding
);
}
else
{
}
else
{
reqlen
=
slen
;
reqlen
=
slen
;
...
@@ -505,7 +519,7 @@ unsigned int ziplistCompare(unsigned char *p, unsigned char *sstr, unsigned int
...
@@ -505,7 +519,7 @@ unsigned int ziplistCompare(unsigned char *p, unsigned char *sstr, unsigned int
}
}
}
else
{
}
else
{
/* Try to compare encoded values */
/* Try to compare encoded values */
if
(
zipTryEncoding
(
sstr
,
&
sval
,
&
sencoding
))
{
if
(
zipTryEncoding
(
sstr
,
slen
,
&
sval
,
&
sencoding
))
{
if
(
entry
.
encoding
==
sencoding
)
{
if
(
entry
.
encoding
==
sencoding
)
{
zval
=
zipLoadInteger
(
p
+
entry
.
headersize
,
entry
.
encoding
);
zval
=
zipLoadInteger
(
p
+
entry
.
headersize
,
entry
.
encoding
);
return
zval
==
sval
;
return
zval
==
sval
;
...
...
src/zmalloc.c
View file @
aaada3f9
...
@@ -89,6 +89,20 @@ void *zmalloc(size_t size) {
...
@@ -89,6 +89,20 @@ void *zmalloc(size_t size) {
#endif
#endif
}
}
void
*
zcalloc
(
size_t
size
)
{
void
*
ptr
=
calloc
(
1
,
size
+
PREFIX_SIZE
);
if
(
!
ptr
)
zmalloc_oom
(
size
);
#ifdef HAVE_MALLOC_SIZE
increment_used_memory
(
redis_malloc_size
(
ptr
));
return
ptr
;
#else
*
((
size_t
*
)
ptr
)
=
size
;
increment_used_memory
(
size
+
PREFIX_SIZE
);
return
(
char
*
)
ptr
+
PREFIX_SIZE
;
#endif
}
void
*
zrealloc
(
void
*
ptr
,
size_t
size
)
{
void
*
zrealloc
(
void
*
ptr
,
size_t
size
)
{
#ifndef HAVE_MALLOC_SIZE
#ifndef HAVE_MALLOC_SIZE
void
*
realptr
;
void
*
realptr
;
...
...
src/zmalloc.h
View file @
aaada3f9
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
#define _ZMALLOC_H
#define _ZMALLOC_H
void
*
zmalloc
(
size_t
size
);
void
*
zmalloc
(
size_t
size
);
void
*
zcalloc
(
size_t
size
);
void
*
zrealloc
(
void
*
ptr
,
size_t
size
);
void
*
zrealloc
(
void
*
ptr
,
size_t
size
);
void
zfree
(
void
*
ptr
);
void
zfree
(
void
*
ptr
);
char
*
zstrdup
(
const
char
*
s
);
char
*
zstrdup
(
const
char
*
s
);
...
...
tests/integration/replication.tcl
View file @
aaada3f9
start_server
{
tags
{
"repl"
}}
{
start_server
{}
{
test
{
First server should have role slave after SLAVEOF
}
{
r -1 slaveof
[
srv 0 host
]
[
srv 0 port
]
after 1000
s -1 role
}
{
slave
}
test
{
MASTER and SLAVE dataset should be identical after complex ops
}
{
createComplexDataset r 10000
after 500
if
{[
r debug digest
]
ne
[
r -1 debug digest
]}
{
set csv1
[
csvdump r
]
set csv2
[
csvdump
{
r -1
}]
set fd
[
open /tmp/repldump1.txt w
]
puts -nonewline $fd $csv1
close $fd
set fd
[
open /tmp/repldump2.txt w
]
puts -nonewline $fd $csv2
close $fd
puts
"Master - Slave inconsistency"
puts
"Run diff -u against /tmp/repldump*.txt for more info"
}
assert_equal
[
r debug digest
]
[
r -1 debug digest
]
}
test
{
MASTER and SLAVE consistency with expire
}
{
createComplexDataset r 50000 useexpire
after 4000
;
# Make sure everything expired before taking the digest
if
{[
r debug digest
]
ne
[
r -1 debug digest
]}
{
set csv1
[
csvdump r
]
set csv2
[
csvdump
{
r -1
}]
set fd
[
open /tmp/repldump1.txt w
]
puts -nonewline $fd $csv1
close $fd
set fd
[
open /tmp/repldump2.txt w
]
puts -nonewline $fd $csv2
close $fd
puts
"Master - Slave inconsistency"
puts
"Run diff -u against /tmp/repldump*.txt for more info"
}
assert_equal
[
r debug digest
]
[
r -1 debug digest
]
}
}
}
start_server
{
tags
{
"repl"
}}
{
start_server
{
tags
{
"repl"
}}
{
r set mykey foo
r set mykey foo
...
...
tests/support/test.tcl
View file @
aaada3f9
...
@@ -33,9 +33,14 @@ proc assert_error {pattern code} {
...
@@ -33,9 +33,14 @@ proc assert_error {pattern code} {
}
}
proc assert_encoding
{
enc key
}
{
proc assert_encoding
{
enc key
}
{
# swapped out value doesn't have encoding, so swap in first
# Swapped out values don't have an encoding, so make sure that
r debug swapin $key
# the value is swapped in before checking the encoding.
assert_match
"* encoding:
$enc
*"
[
r debug object $key
]
set dbg
[
r debug object $key
]
while
{[
string match
"* swapped at:*"
$dbg
]}
{
r debug swapin $key
set dbg
[
r debug object $key
]
}
assert_match
"* encoding:
$enc
*"
$dbg
}
}
proc assert_type
{
type key
}
{
proc assert_type
{
type key
}
{
...
...
tests/support/util.tcl
View file @
aaada3f9
...
@@ -44,7 +44,7 @@ proc warnings_from_file {filename} {
...
@@ -44,7 +44,7 @@ proc warnings_from_file {filename} {
# Return value for INFO property
# Return value for INFO property
proc status
{
r property
}
{
proc status
{
r property
}
{
if
{[
regexp
"
\r\n
$property:
(.*?)
\r\n
"
[
$r
info
]
_ value
]}
{
if
{[
regexp
"
\r\n
$property:
(.*?)
\r\n
"
[
{*}
$r
info
]
_ value
]}
{
set _ $value
set _ $value
}
}
}
}
...
@@ -127,11 +127,32 @@ proc randomKey {} {
...
@@ -127,11 +127,32 @@ proc randomKey {} {
}
}
}
}
proc createComplexDataset
{
r ops
}
{
proc findKeyWithType
{
r type
}
{
for
{
set j 0
}
{
$j
< 20
}
{
incr j
}
{
set k
[
{*}
$r
randomkey
]
if
{
$k
eq
{}}
{
return
{}
}
if
{[
{*}
$r
type $k
]
eq $type
}
{
return $k
}
}
return
{}
}
proc createComplexDataset
{
r ops
{
opt
{}}}
{
for
{
set j 0
}
{
$j
< $ops
}
{
incr j
}
{
for
{
set j 0
}
{
$j
< $ops
}
{
incr j
}
{
set k
[
randomKey
]
set k
[
randomKey
]
set k2
[
randomKey
]
set f
[
randomValue
]
set f
[
randomValue
]
set v
[
randomValue
]
set v
[
randomValue
]
if
{[
lsearch -exact $opt useexpire
]
!= -1
}
{
if
{
rand
()
< 0.1
}
{
{*}
$r
expire
[
randomKey
]
[
randomInt 2
]
}
}
randpath
{
randpath
{
set d
[
expr
{
rand
()}]
set d
[
expr
{
rand
()}]
}
{
}
{
...
@@ -145,21 +166,23 @@ proc createComplexDataset {r ops} {
...
@@ -145,21 +166,23 @@ proc createComplexDataset {r ops} {
}
{
}
{
randpath
{
set d +inf
}
{
set d -inf
}
randpath
{
set d +inf
}
{
set d -inf
}
}
}
set t
[
$r
type $k
]
set t
[
{*}
$r
type $k
]
if
{
$t
eq
{
none
}}
{
if
{
$t
eq
{
none
}}
{
randpath
{
randpath
{
$r set $k $v
{*}
$r
set $k $v
}
{
}
{
$r lpush $k $v
{*}
$r
lpush $k $v
}
{
}
{
$r sadd $k $v
{*}
$r
sadd $k $v
}
{
}
{
$r zadd $k $d $v
{*}
$r
zadd $k $d $v
}
{
}
{
$r hset $k $f $v
{*}
$r
hset $k $f $v
}
{
{*}
$r
del $k
}
}
set t
[
$r
type $k
]
set t
[
{*}
$r
type $k
]
}
}
switch $t
{
switch $t
{
...
@@ -167,23 +190,45 @@ proc createComplexDataset {r ops} {
...
@@ -167,23 +190,45 @@ proc createComplexDataset {r ops} {
# Nothing to do
# Nothing to do
}
}
{
list
}
{
{
list
}
{
randpath
{
$r
lpush $k $v
}
\
randpath
{
{*}
$r
lpush $k $v
}
\
{
$r
rpush $k $v
}
\
{
{*}
$r
rpush $k $v
}
\
{
$r
lrem $k 0 $v
}
\
{
{*}
$r
lrem $k 0 $v
}
\
{
$r
rpop $k
}
\
{
{*}
$r
rpop $k
}
\
{
$r
lpop $k
}
{
{*}
$r
lpop $k
}
}
}
{
set
}
{
{
set
}
{
randpath
{
$r
sadd $k $v
}
\
randpath
{
{*}
$r
sadd $k $v
}
\
{
$r
srem $k $v
}
{
{*}
$r
srem $k $v
}
\
{
set otherset
[
findKeyWithType r set
]
if
{
$otherset
ne
{}}
{
randpath
{
{*}
$r
sunionstore $k2 $k $otherset
}
{
{*}
$r
sinterstore $k2 $k $otherset
}
{
{*}
$r
sdiffstore $k2 $k $otherset
}
}
}
}
}
{
zset
}
{
{
zset
}
{
randpath
{
$r
zadd $k $d $v
}
\
randpath
{
{*}
$r
zadd $k $d $v
}
\
{
$r
zrem $k $v
}
{
{*}
$r
zrem $k $v
}
\
{
set otherzset
[
findKeyWithType r zset
]
if
{
$otherzset
ne
{}}
{
randpath
{
{*}
$r
zunionstore $k2 2 $k $otherzset
}
{
{*}
$r
zinterstore $k2 2 $k $otherzset
}
}
}
}
}
{
hash
}
{
{
hash
}
{
randpath
{
$r
hset $k $f $v
}
\
randpath
{
{*}
$r
hset $k $f $v
}
\
{
$r
hdel $k $f
}
{
{*}
$r
hdel $k $f
}
}
}
}
}
}
}
...
@@ -196,3 +241,52 @@ proc formatCommand {args} {
...
@@ -196,3 +241,52 @@ proc formatCommand {args} {
}
}
set _ $cmd
set _ $cmd
}
}
proc csvdump r
{
set o
{}
foreach k
[
lsort
[
{*}
$r
keys *
]]
{
set type
[
{*}
$r
type $k
]
append o
[
csvstring $k
]
,
[
csvstring $type
]
,
switch $type
{
string
{
append o
[
csvstring
[
{*}
$r
get $k
]]
"
\n
"
}
list
{
foreach e
[
{*}
$r
lrange $k 0 -1
]
{
append o
[
csvstring $e
]
,
}
append o
"
\n
"
}
set
{
foreach e
[
lsort
[
{*}
$r
smembers $k
]]
{
append o
[
csvstring $e
]
,
}
append o
"
\n
"
}
zset
{
foreach e
[
{*}
$r
zrange $k 0 -1 withscores
]
{
append o
[
csvstring $e
]
,
}
append o
"
\n
"
}
hash
{
set fields
[
{*}
$r
hgetall $k
]
set newfields
{}
foreach
{
k v
}
$fields
{
lappend newfields
[
list $k $v
]
}
set fields
[
lsort -index 0 $newfields
]
foreach kv $fields
{
append o
[
csvstring
[
lindex $kv 0
]]
,
append o
[
csvstring
[
lindex $kv 1
]]
,
}
append o
"
\n
"
}
}
}
return $o
}
proc csvstring s
{
return
"
\"
$s
\"
"
}
tests/test_helper.tcl
View file @
aaada3f9
...
@@ -102,13 +102,13 @@ proc main {} {
...
@@ -102,13 +102,13 @@ proc main {} {
execute_tests
"unit/expire"
execute_tests
"unit/expire"
execute_tests
"unit/other"
execute_tests
"unit/other"
execute_tests
"unit/cas"
execute_tests
"unit/cas"
cleanup
puts
"
\n
[
expr $::passed+$::failed
]
tests,
$::passed
passed,
$::failed
failed"
puts
"
\n
[
expr $::passed+$::failed
]
tests,
$::passed
passed,
$::failed
failed"
if
{
$::failed
> 0
}
{
if
{
$::failed
> 0
}
{
puts
"
\n
*** WARNING!!!
$::failed
FAILED TESTS ***
\n
"
puts
"
\n
*** WARNING!!!
$::failed
FAILED TESTS ***
\n
"
exit 1
}
}
cleanup
}
}
# parse arguments
# parse arguments
...
...
tests/unit/basic.tcl
View file @
aaada3f9
...
@@ -148,12 +148,11 @@ start_server {tags {"basic"}} {
...
@@ -148,12 +148,11 @@ start_server {tags {"basic"}} {
r get novar2
r get novar2
}
{
foobared
}
}
{
foobared
}
test
{
SETNX
will overwrite EXPIREing
key
}
{
test
{
SETNX
against volatile
key
}
{
r set x 10
r set x 10
r expire x 10000
r expire x 10000
r setnx x 20
list
[
r setnx x 20
]
[
r get x
]
r get x
}
{
0 10
}
}
{
20
}
test
{
EXISTS
}
{
test
{
EXISTS
}
{
set res
{}
set res
{}
...
@@ -362,10 +361,17 @@ start_server {tags {"basic"}} {
...
@@ -362,10 +361,17 @@ start_server {tags {"basic"}} {
list
[
r msetnx x1 xxx y2 yyy
]
[
r get x1
]
[
r get y2
]
list
[
r msetnx x1 xxx y2 yyy
]
[
r get x1
]
[
r get y2
]
}
{
1 xxx yyy
}
}
{
1 xxx yyy
}
test
{
MSETNX should remove all the volatile keys even on failure
}
{
test
{
STRLEN against non existing key
}
{
r mset x 1 y 2 z 3
r strlen notakey
r expire y 10000
}
{
0
}
r expire z 10000
list
[
r msetnx x A y B z C
]
[
r mget x y z
]
test
{
STRLEN against integer
}
{
}
{
0
{
1
{}
{}}}
r set myinteger -555
r strlen myinteger
}
{
4
}
test
{
STRLEN against plain string
}
{
r set mystring
"foozzz0123456789 baz"
r strlen mystring
}
}
}
tests/unit/cas.tcl
View file @
aaada3f9
...
@@ -111,4 +111,25 @@ start_server {tags {"cas"}} {
...
@@ -111,4 +111,25 @@ start_server {tags {"cas"}} {
r ping
r ping
r exec
r exec
}
{
PONG
}
}
{
PONG
}
test
{
WATCH will consider touched keys target of EXPIRE
}
{
r del x
r set x foo
r watch x
r expire x 10
r multi
r ping
r exec
}
{}
test
{
WATCH will not consider touched expired keys
}
{
r del x
r set x foo
r expire x 2
r watch x
after 3000
r multi
r ping
r exec
}
{
PONG
}
}
}
tests/unit/expire.tcl
View file @
aaada3f9
start_server
{
tags
{
"expire"
}}
{
start_server
{
tags
{
"expire"
}}
{
test
{
EXPIRE -
don't
set timeouts multiple times
}
{
test
{
EXPIRE - set timeouts multiple times
}
{
r set x foobar
r set x foobar
set v1
[
r expire x 5
]
set v1
[
r expire x 5
]
set v2
[
r ttl x
]
set v2
[
r ttl x
]
set v3
[
r expire x 10
]
set v3
[
r expire x 10
]
set v4
[
r ttl x
]
set v4
[
r ttl x
]
r expire x 4
list $v1 $v2 $v3 $v4
list $v1 $v2 $v3 $v4
}
{
1 5
0 5
}
}
{
1 5
1 10
}
test
{
EXPIRE - It should be still possible to read 'x'
}
{
test
{
EXPIRE - It should be still possible to read 'x'
}
{
r get x
r get x
...
@@ -19,13 +20,13 @@ start_server {tags {"expire"}} {
...
@@ -19,13 +20,13 @@ start_server {tags {"expire"}} {
}
{{}
0
}
}
{{}
0
}
}
}
test
{
EXPIRE -
Dele
te on
write policy
}
{
test
{
EXPIRE -
wri
te on
expire should work
}
{
r del x
r del x
r lpush x foo
r lpush x foo
r expire x 1000
r expire x 1000
r lpush x bar
r lpush x bar
r lrange x 0 -1
r lrange x 0 -1
}
{
bar
}
}
{
bar
foo
}
test
{
EXPIREAT - Check for EXPIRE alike behavior
}
{
test
{
EXPIREAT - Check for EXPIRE alike behavior
}
{
r del x
r del x
...
@@ -59,4 +60,15 @@ start_server {tags {"expire"}} {
...
@@ -59,4 +60,15 @@ start_server {tags {"expire"}} {
catch
{
r setex z -10 foo
}
e
catch
{
r setex z -10 foo
}
e
set _ $e
set _ $e
}
{
*invalid expire*
}
}
{
*invalid expire*
}
test
{
PERSIST can undo an EXPIRE
}
{
r set x foo
r expire x 50
list
[
r ttl x
]
[
r persist x
]
[
r ttl x
]
[
r get x
]
}
{
50 1 -1 foo
}
test
{
PERSIST returns 0 against non existing or non volatile keys
}
{
r set x foo
list
[
r persist foo
]
[
r persist nokeyatall
]
}
{
0 0
}
}
}
tests/unit/other.tcl
View file @
aaada3f9
...
@@ -46,23 +46,56 @@ start_server {} {
...
@@ -46,23 +46,56 @@ start_server {} {
set _ $err
set _ $err
}
{
*invalid*
}
}
{
*invalid*
}
if
{
!
[
catch
{
package require sha1
}]}
{
tags
{
consistency
}
{
test
{
Check consistency of different data types after a reload
}
{
if
{
!
[
catch
{
package require sha1
}]}
{
r flushdb
test
{
Check consistency of different data types after a reload
}
{
createComplexDataset r 10000
r flushdb
set sha1
[
r debug digest
]
createComplexDataset r 10000
r debug reload
set dump
[
csvdump r
]
set sha1_after
[
r debug digest
]
set sha1
[
r debug digest
]
expr
{
$sha1
eq $sha1_after
}
r debug reload
}
{
1
}
set sha1_after
[
r debug digest
]
if
{
$sha1
eq $sha1_after
}
{
test
{
Same dataset digest if saving/reloading as AOF?
}
{
set _ 1
r bgrewriteaof
}
else
{
waitForBgrewriteaof r
set newdump
[
csvdump r
]
r debug loadaof
puts
"Consistency test failed!"
set sha1_after
[
r debug digest
]
puts
"You can inspect the two dumps in /tmp/repldump*.txt"
expr
{
$sha1
eq $sha1_after
}
}
{
1
}
set fd
[
open /tmp/repldump1.txt w
]
puts $fd $dump
close $fd
set fd
[
open /tmp/repldump2.txt w
]
puts $fd $newdump
close $fd
set _ 0
}
}
{
1
}
test
{
Same dataset digest if saving/reloading as AOF?
}
{
r bgrewriteaof
waitForBgrewriteaof r
r debug loadaof
set sha1_after
[
r debug digest
]
if
{
$sha1
eq $sha1_after
}
{
set _ 1
}
else
{
set newdump
[
csvdump r
]
puts
"Consistency test failed!"
puts
"You can inspect the two dumps in /tmp/aofdump*.txt"
set fd
[
open /tmp/aofdump1.txt w
]
puts $fd $dump
close $fd
set fd
[
open /tmp/aofdump2.txt w
]
puts $fd $newdump
close $fd
set _ 0
}
}
{
1
}
}
}
}
test
{
EXPIRES after a reload
(
snapshot + append only file
)}
{
test
{
EXPIRES after a reload
(
snapshot + append only file
)}
{
...
...
tests/unit/type/list.tcl
View file @
aaada3f9
...
@@ -5,6 +5,12 @@ start_server {
...
@@ -5,6 +5,12 @@ start_server {
"list-max-ziplist-entries"
256
"list-max-ziplist-entries"
256
}
}
}
{
}
{
# We need a value larger than list-max-ziplist-value to make sure
# the list has the right encoding when it is swapped in again.
array set largevalue
{}
set largevalue
(
ziplist
)
"hello"
set largevalue
(
linkedlist
)
[
string repeat
"hello"
4
]
test
{
LPUSH, RPUSH, LLENGTH, LINDEX - ziplist
}
{
test
{
LPUSH, RPUSH, LLENGTH, LINDEX - ziplist
}
{
# first lpush then rpush
# first lpush then rpush
assert_equal 1
[
r lpush myziplist1 a
]
assert_equal 1
[
r lpush myziplist1 a
]
...
@@ -28,28 +34,25 @@ start_server {
...
@@ -28,28 +34,25 @@ start_server {
}
}
test
{
LPUSH, RPUSH, LLENGTH, LINDEX - regular list
}
{
test
{
LPUSH, RPUSH, LLENGTH, LINDEX - regular list
}
{
# use a string of length 17 to ensure a regular list is used
set large_value
"aaaaaaaaaaaaaaaaa"
# first lpush then rpush
# first lpush then rpush
assert_equal 1
[
r lpush mylist1 $large
_
value
]
assert_equal 1
[
r lpush mylist1 $largevalue
(
linkedlist
)
]
assert_encoding linkedlist mylist1
assert_encoding linkedlist mylist1
assert_equal 2
[
r rpush mylist1 b
]
assert_equal 2
[
r rpush mylist1 b
]
assert_equal 3
[
r rpush mylist1 c
]
assert_equal 3
[
r rpush mylist1 c
]
assert_equal 3
[
r llen mylist1
]
assert_equal 3
[
r llen mylist1
]
assert_equal $large
_
value
[
r lindex mylist1 0
]
assert_equal $largevalue
(
linkedlist
)
[
r lindex mylist1 0
]
assert_equal b
[
r lindex mylist1 1
]
assert_equal b
[
r lindex mylist1 1
]
assert_equal c
[
r lindex mylist1 2
]
assert_equal c
[
r lindex mylist1 2
]
# first rpush then lpush
# first rpush then lpush
assert_equal 1
[
r rpush mylist2 $large
_
value
]
assert_equal 1
[
r rpush mylist2 $largevalue
(
linkedlist
)
]
assert_encoding linkedlist mylist2
assert_encoding linkedlist mylist2
assert_equal 2
[
r lpush mylist2 b
]
assert_equal 2
[
r lpush mylist2 b
]
assert_equal 3
[
r lpush mylist2 c
]
assert_equal 3
[
r lpush mylist2 c
]
assert_equal 3
[
r llen mylist2
]
assert_equal 3
[
r llen mylist2
]
assert_equal c
[
r lindex mylist2 0
]
assert_equal c
[
r lindex mylist2 0
]
assert_equal b
[
r lindex mylist2 1
]
assert_equal b
[
r lindex mylist2 1
]
assert_equal $large
_
value
[
r lindex mylist2 2
]
assert_equal $largevalue
(
linkedlist
)
[
r lindex mylist2 2
]
}
}
test
{
DEL a list - ziplist
}
{
test
{
DEL a list - ziplist
}
{
...
@@ -72,16 +75,14 @@ start_server {
...
@@ -72,16 +75,14 @@ start_server {
proc create_linkedlist
{
key entries
}
{
proc create_linkedlist
{
key entries
}
{
r del $key
r del $key
r rpush $key
"aaaaaaaaaaaaaaaaa"
foreach entry $entries
{
r rpush $key $entry
}
foreach entry $entries
{
r rpush $key $entry
}
assert_equal
"aaaaaaaaaaaaaaaaa"
[
r lpop $key
]
assert_encoding linkedlist $key
assert_encoding linkedlist $key
}
}
foreach type
{
ziplist linkedlist
}
{
foreach
{
type
large
}
[
array get largevalue
]
{
test
"BLPOP, BRPOP: single existing list -
$type
"
{
test
"BLPOP, BRPOP: single existing list -
$type
"
{
set rd
[
redis_deferring_client
]
set rd
[
redis_deferring_client
]
create_$type blist
{
a b c d
}
create_$type blist
"
a b
$large
c d
"
$rd blpop blist 1
$rd blpop blist 1
assert_equal
{
blist a
}
[
$rd
read
]
assert_equal
{
blist a
}
[
$rd
read
]
...
@@ -96,8 +97,8 @@ start_server {
...
@@ -96,8 +97,8 @@ start_server {
test
"BLPOP, BRPOP: multiple existing lists -
$type
"
{
test
"BLPOP, BRPOP: multiple existing lists -
$type
"
{
set rd
[
redis_deferring_client
]
set rd
[
redis_deferring_client
]
create_$type blist1
{
a
b
c
}
create_$type blist1
"
a
$large
c
"
create_$type blist2
{
d e f
}
create_$type blist2
"
d
$larg
e
f
"
$rd blpop blist1 blist2 1
$rd blpop blist1 blist2 1
assert_equal
{
blist1 a
}
[
$rd
read
]
assert_equal
{
blist1 a
}
[
$rd
read
]
...
@@ -117,7 +118,7 @@ start_server {
...
@@ -117,7 +118,7 @@ start_server {
test
"BLPOP, BRPOP: second list has an entry -
$type
"
{
test
"BLPOP, BRPOP: second list has an entry -
$type
"
{
set rd
[
redis_deferring_client
]
set rd
[
redis_deferring_client
]
r del blist1
r del blist1
create_$type blist2
{
d e f
}
create_$type blist2
"
d
$larg
e
f
"
$rd blpop blist1 blist2 1
$rd blpop blist1 blist2 1
assert_equal
{
blist2 d
}
[
$rd
read
]
assert_equal
{
blist2 d
}
[
$rd
read
]
...
@@ -179,26 +180,26 @@ start_server {
...
@@ -179,26 +180,26 @@ start_server {
assert_equal 0
[
r llen xlist
]
assert_equal 0
[
r llen xlist
]
}
}
foreach type
{
ziplist linkedlist
}
{
foreach
{
type
large
}
[
array get largevalue
]
{
test
"LPUSHX, RPUSHX -
$type
"
{
test
"LPUSHX, RPUSHX -
$type
"
{
create_$type xlist
{
b
c
}
create_$type xlist
"
$large
c
"
assert_equal 3
[
r rpushx xlist d
]
assert_equal 3
[
r rpushx xlist d
]
assert_equal 4
[
r lpushx xlist a
]
assert_equal 4
[
r lpushx xlist a
]
assert_equal
{
a
b
c d
}
[
r lrange xlist 0 -1
]
assert_equal
"
a
$large
c d
"
[
r lrange xlist 0 -1
]
}
}
test
"LINSERT -
$type
"
{
test
"LINSERT -
$type
"
{
create_$type xlist
{
a
b
c d
}
create_$type xlist
"
a
$large
c d
"
assert_equal 5
[
r linsert xlist before c zz
]
assert_equal 5
[
r linsert xlist before c zz
]
assert_equal
{
a
b
zz c d
}
[
r lrange xlist 0 10
]
assert_equal
"
a
$large
zz c d
"
[
r lrange xlist 0 10
]
assert_equal 6
[
r linsert xlist after c yy
]
assert_equal 6
[
r linsert xlist after c yy
]
assert_equal
{
a
b
zz c yy d
}
[
r lrange xlist 0 10
]
assert_equal
"
a
$large
zz c yy d
"
[
r lrange xlist 0 10
]
assert_equal 7
[
r linsert xlist after d dd
]
assert_equal 7
[
r linsert xlist after d dd
]
assert_equal -1
[
r linsert xlist after bad ddd
]
assert_equal -1
[
r linsert xlist after bad ddd
]
assert_equal
{
a
b
zz c yy d dd
}
[
r lrange xlist 0 10
]
assert_equal
"
a
$large
zz c yy d dd
"
[
r lrange xlist 0 10
]
assert_equal 8
[
r linsert xlist before a aa
]
assert_equal 8
[
r linsert xlist before a aa
]
assert_equal -1
[
r linsert xlist before bad aaa
]
assert_equal -1
[
r linsert xlist before bad aaa
]
assert_equal
{
aa a
b
zz c yy d dd
}
[
r lrange xlist 0 10
]
assert_equal
"
aa a
$large
zz c yy d dd
"
[
r lrange xlist 0 10
]
# check inserting integer encoded value
# check inserting integer encoded value
assert_equal 9
[
r linsert xlist before aa 42
]
assert_equal 9
[
r linsert xlist before aa 42
]
...
@@ -207,14 +208,14 @@ start_server {
...
@@ -207,14 +208,14 @@ start_server {
}
}
test
{
LPUSHX, RPUSHX convert from ziplist to list
}
{
test
{
LPUSHX, RPUSHX convert from ziplist to list
}
{
set large
_value
"aaaaaaaaaaaaaaaaa"
set large
$largevalue
(
linkedlist
)
# convert when a large value is pushed
# convert when a large value is pushed
create_ziplist xlist a
create_ziplist xlist a
assert_equal 2
[
r rpushx xlist $large
_value
]
assert_equal 2
[
r rpushx xlist $large
]
assert_encoding linkedlist xlist
assert_encoding linkedlist xlist
create_ziplist xlist a
create_ziplist xlist a
assert_equal 2
[
r lpushx xlist $large
_value
]
assert_equal 2
[
r lpushx xlist $large
]
assert_encoding linkedlist xlist
assert_encoding linkedlist xlist
# convert when the length threshold is exceeded
# convert when the length threshold is exceeded
...
@@ -227,14 +228,14 @@ start_server {
...
@@ -227,14 +228,14 @@ start_server {
}
}
test
{
LINSERT convert from ziplist to list
}
{
test
{
LINSERT convert from ziplist to list
}
{
set large
_value
"aaaaaaaaaaaaaaaaa"
set large
$largevalue
(
linkedlist
)
# convert when a large value is inserted
# convert when a large value is inserted
create_ziplist xlist a
create_ziplist xlist a
assert_equal 2
[
r linsert xlist before a $large
_value
]
assert_equal 2
[
r linsert xlist before a $large
]
assert_encoding linkedlist xlist
assert_encoding linkedlist xlist
create_ziplist xlist a
create_ziplist xlist a
assert_equal 2
[
r linsert xlist after a $large
_value
]
assert_equal 2
[
r linsert xlist after a $large
]
assert_encoding linkedlist xlist
assert_encoding linkedlist xlist
# convert when the length threshold is exceeded
# convert when the length threshold is exceeded
...
@@ -320,32 +321,38 @@ start_server {
...
@@ -320,32 +321,38 @@ start_server {
assert_error ERR*
{
r rpush mylist 0
}
assert_error ERR*
{
r rpush mylist 0
}
}
}
foreach type
{
ziplist linkedlist
}
{
foreach
{
type
large
}
[
array get largevalue
]
{
test
"RPOPLPUSH base case -
$type
"
{
test
"RPOPLPUSH base case -
$type
"
{
r del mylist1 mylist2
r del mylist1 mylist2
create_$type mylist1
{
a
b
c d
}
create_$type mylist1
"
a
$large
c d
"
assert_equal d
[
r rpoplpush mylist1 mylist2
]
assert_equal d
[
r rpoplpush mylist1 mylist2
]
assert_equal c
[
r rpoplpush mylist1 mylist2
]
assert_equal c
[
r rpoplpush mylist1 mylist2
]
assert_equal
{
a
b
}
[
r lrange mylist1 0 -1
]
assert_equal
"
a
$large
"
[
r lrange mylist1 0 -1
]
assert_equal
{
c d
}
[
r lrange mylist2 0 -1
]
assert_equal
"
c d
"
[
r lrange mylist2 0 -1
]
assert_encoding ziplist mylist2
assert_encoding ziplist mylist2
}
}
test
"RPOPLPUSH with the same list as src and dst -
$type
"
{
test
"RPOPLPUSH with the same list as src and dst -
$type
"
{
create_$type mylist
{
a
b
c
}
create_$type mylist
"
a
$large
c
"
assert_equal
{
a
b
c
}
[
r lrange mylist 0 -1
]
assert_equal
"
a
$large
c
"
[
r lrange mylist 0 -1
]
assert_equal c
[
r rpoplpush mylist mylist
]
assert_equal c
[
r rpoplpush mylist mylist
]
assert_equal
{
c a
b
}
[
r lrange mylist 0 -1
]
assert_equal
"
c a
$large
"
[
r lrange mylist 0 -1
]
}
}
foreach othertype
{
ziplist linkedlist
}
{
foreach
{
othertype
otherlarge
}
[
array get largevalue
]
{
test
"RPOPLPUSH with
$type
source and existing target
$othertype
"
{
test
"RPOPLPUSH with
$type
source and existing target
$othertype
"
{
create_$type srclist
{
a b c
d
}
create_$type srclist
"
a b c
$large
"
create_$othertype dstlist
{
x
}
create_$othertype dstlist
"
$otherlarge
"
assert_equal
d
[
r rpoplpush srclist dstlist
]
assert_equal
$large
[
r rpoplpush srclist dstlist
]
assert_equal c
[
r rpoplpush srclist dstlist
]
assert_equal c
[
r rpoplpush srclist dstlist
]
assert_equal
{
a b
}
[
r lrange srclist 0 -1
]
assert_equal
"a b"
[
r lrange srclist 0 -1
]
assert_equal
{
c d x
}
[
r lrange dstlist 0 -1
]
assert_equal
"c
$large
$otherlarge
"
[
r lrange dstlist 0 -1
]
# When we rpoplpush'ed a large value, dstlist should be
# converted to the same encoding as srclist.
if
{
$type
eq
"linkedlist"
}
{
assert_encoding linkedlist dstlist
}
}
}
}
}
}
}
...
@@ -378,10 +385,10 @@ start_server {
...
@@ -378,10 +385,10 @@ start_server {
assert_equal
{}
[
r rpoplpush srclist dstlist
]
assert_equal
{}
[
r rpoplpush srclist dstlist
]
}
{}
}
{}
foreach type
{
ziplist linkedlist
}
{
foreach
{
type
large
}
[
array get largevalue
]
{
test
"Basic LPOP/RPOP -
$type
"
{
test
"Basic LPOP/RPOP -
$type
"
{
create_$type mylist
{
0
1 2
}
create_$type mylist
"
$large
1 2
"
assert_equal
0
[
r lpop mylist
]
assert_equal
$large
[
r lpop mylist
]
assert_equal 2
[
r rpop mylist
]
assert_equal 2
[
r rpop mylist
]
assert_equal 1
[
r lpop mylist
]
assert_equal 1
[
r lpop mylist
]
assert_equal 0
[
r llen mylist
]
assert_equal 0
[
r llen mylist
]
...
@@ -416,28 +423,28 @@ start_server {
...
@@ -416,28 +423,28 @@ start_server {
}
}
}
}
foreach type
{
ziplist linkedlist
}
{
foreach
{
type
large
}
[
array get largevalue
]
{
test
"LRANGE basics -
$type
"
{
test
"LRANGE basics -
$type
"
{
create_$type mylist
{
0
1 2 3 4 5 6 7 8 9
}
create_$type mylist
"
$large
1 2 3 4 5 6 7 8 9
"
assert_equal
{
1 2 3 4 5 6 7 8
}
[
r lrange mylist 1 -2
]
assert_equal
{
1 2 3 4 5 6 7 8
}
[
r lrange mylist 1 -2
]
assert_equal
{
7 8 9
}
[
r lrange mylist -3 -1
]
assert_equal
{
7 8 9
}
[
r lrange mylist -3 -1
]
assert_equal
{
4
}
[
r lrange mylist 4 4
]
assert_equal
{
4
}
[
r lrange mylist 4 4
]
}
}
test
"LRANGE inverted indexes -
$type
"
{
test
"LRANGE inverted indexes -
$type
"
{
create_$type mylist
{
0
1 2 3 4 5 6 7 8 9
}
create_$type mylist
"
$large
1 2 3 4 5 6 7 8 9
"
assert_equal
{}
[
r lrange mylist 6 2
]
assert_equal
{}
[
r lrange mylist 6 2
]
}
}
test
"LRANGE out of range indexes including the full list -
$type
"
{
test
"LRANGE out of range indexes including the full list -
$type
"
{
create_$type mylist
{
1 2 3
}
create_$type mylist
"
$large
1 2 3
"
assert_equal
{
1 2 3
}
[
r lrange mylist -1000 1000
]
assert_equal
"
$large
1 2 3
"
[
r lrange mylist -1000 1000
]
}
}
test
"LRANGE out of range negative end index -
$type
"
{
test
"LRANGE out of range negative end index -
$type
"
{
create_$type mylist
{
1 2 3
}
create_$type mylist
"
$large
1 2 3
"
assert_equal
{
1
}
[
r lrange mylist 0 -
3
]
assert_equal
$large
[
r lrange mylist 0 -
4
]
assert_equal
{}
[
r lrange mylist 0 -
4
]
assert_equal
{}
[
r lrange mylist 0 -
5
]
}
}
}
}
...
@@ -445,27 +452,28 @@ start_server {
...
@@ -445,27 +452,28 @@ start_server {
assert_equal
{}
[
r lrange nosuchkey 0 1
]
assert_equal
{}
[
r lrange nosuchkey 0 1
]
}
}
foreach type
{
ziplist linkedlist
}
{
foreach
{
type
large
}
[
array get largevalue
]
{
proc trim_list
{
type min max
}
{
proc trim_list
{
type min max
}
{
upvar 1 large large
r del mylist
r del mylist
create_$type mylist
{
1 2 3 4
5
}
create_$type mylist
"
1 2 3 4
$large
"
r ltrim mylist $min $max
r ltrim mylist $min $max
r lrange mylist 0 -1
r lrange mylist 0 -1
}
}
test
"LTRIM basics -
$type
"
{
test
"LTRIM basics -
$type
"
{
assert_equal
{
1
}
[
trim_list $type 0 0
]
assert_equal
"1"
[
trim_list $type 0 0
]
assert_equal
{
1 2
}
[
trim_list $type 0 1
]
assert_equal
"
1 2
"
[
trim_list $type 0 1
]
assert_equal
{
1 2 3
}
[
trim_list $type 0 2
]
assert_equal
"
1 2 3
"
[
trim_list $type 0 2
]
assert_equal
{
2 3
}
[
trim_list $type 1 2
]
assert_equal
"
2 3
"
[
trim_list $type 1 2
]
assert_equal
{
2 3 4
5
}
[
trim_list $type 1 -1
]
assert_equal
"
2 3 4
$large
"
[
trim_list $type 1 -1
]
assert_equal
{
2 3 4
}
[
trim_list $type 1 -2
]
assert_equal
"
2 3 4
"
[
trim_list $type 1 -2
]
assert_equal
{
4
5
}
[
trim_list $type -2 -1
]
assert_equal
"
4
$large
"
[
trim_list $type -2 -1
]
assert_equal
{
5
}
[
trim_list $type -1 -1
]
assert_equal
"
$large
"
[
trim_list $type -1 -1
]
assert_equal
{
1 2 3 4
5
}
[
trim_list $type -5 -1
]
assert_equal
"
1 2 3 4
$large
"
[
trim_list $type -5 -1
]
assert_equal
{
1 2 3 4
5
}
[
trim_list $type -10 10
]
assert_equal
"
1 2 3 4
$large
"
[
trim_list $type -10 10
]
assert_equal
{
1 2 3 4
5
}
[
trim_list $type 0 5
]
assert_equal
"
1 2 3 4
$large
"
[
trim_list $type 0 5
]
assert_equal
{
1 2 3 4
5
}
[
trim_list $type 0 10
]
assert_equal
"
1 2 3 4
$large
"
[
trim_list $type 0 10
]
}
}
test
"LTRIM out of range negative end index -
$type
"
{
test
"LTRIM out of range negative end index -
$type
"
{
...
@@ -478,20 +486,19 @@ start_server {
...
@@ -478,20 +486,19 @@ start_server {
set mylist
{}
set mylist
{}
set startlen 32
set startlen 32
r del mylist
r del mylist
# Start with the large value to ensure the
# right encoding is used.
r rpush mylist $large
lappend mylist $large
for
{
set i 0
}
{
$i
< $startlen
}
{
incr i
}
{
for
{
set i 0
}
{
$i
< $startlen
}
{
incr i
}
{
set str
[
randomInt 9223372036854775807
]
set str
[
randomInt 9223372036854775807
]
r rpush mylist $str
r rpush mylist $str
lappend mylist $str
lappend mylist $str
}
}
# do a push/pop of a large value to convert to a real list
for
{
set i 0
}
{
$i
< 1000
}
{
incr i
}
{
if
{
$type
eq
"list"
}
{
r rpush mylist
"aaaaaaaaaaaaaaaaa"
r rpop mylist
assert_encoding linkedlist mylist
}
for
{
set i 0
}
{
$i
< 10000
}
{
incr i
}
{
set min
[
expr
{
int
(
rand
()
*$startlen
)}]
set min
[
expr
{
int
(
rand
()
*$startlen
)}]
set max
[
expr
{
$min
+int
(
rand
()
*$startlen
)}]
set max
[
expr
{
$min
+int
(
rand
()
*$startlen
)}]
set mylist
[
lrange $mylist $min $max
]
set mylist
[
lrange $mylist $min $max
]
...
@@ -508,12 +515,12 @@ start_server {
...
@@ -508,12 +515,12 @@ start_server {
}
}
}
}
foreach type
{
ziplist linkedlist
}
{
foreach
{
type
large
}
[
array get largevalue
]
{
test
"LSET -
$type
"
{
test
"LSET -
$type
"
{
create_$type mylist
{
99 98
97
96 95
}
create_$type mylist
"
99 98
$large
96 95
"
r lset mylist 1 foo
r lset mylist 1 foo
r lset mylist -1 bar
r lset mylist -1 bar
assert_equal
{
99 foo
97
96 bar
}
[
r lrange mylist 0 -1
]
assert_equal
"
99 foo
$large
96 bar
"
[
r lrange mylist 0 -1
]
}
}
test
"LSET out of range index -
$type
"
{
test
"LSET out of range index -
$type
"
{
...
@@ -530,38 +537,38 @@ start_server {
...
@@ -530,38 +537,38 @@ start_server {
assert_error ERR*value*
{
r lset nolist 0 foo
}
assert_error ERR*value*
{
r lset nolist 0 foo
}
}
}
foreach type
{
ziplist linkedlist
}
{
foreach
{
type
e
}
[
array get largevalue
]
{
test
"LREM remove all the occurrences -
$type
"
{
test
"LREM remove all the occurrences -
$type
"
{
create_$type mylist
{
foo bar foobar foobared zap bar test foo
}
create_$type mylist
"
$e
foo bar foobar foobared zap bar test foo
"
assert_equal 2
[
r lrem mylist 0 bar
]
assert_equal 2
[
r lrem mylist 0 bar
]
assert_equal
{
foo foobar foobared zap test foo
}
[
r lrange mylist 0 -1
]
assert_equal
"
$e
foo foobar foobared zap test foo
"
[
r lrange mylist 0 -1
]
}
}
test
"LREM remove the first occurrence -
$type
"
{
test
"LREM remove the first occurrence -
$type
"
{
assert_equal 1
[
r lrem mylist 1 foo
]
assert_equal 1
[
r lrem mylist 1 foo
]
assert_equal
{
foobar foobared zap test foo
}
[
r lrange mylist 0 -1
]
assert_equal
"
$e
foobar foobared zap test foo
"
[
r lrange mylist 0 -1
]
}
}
test
"LREM remove non existing element -
$type
"
{
test
"LREM remove non existing element -
$type
"
{
assert_equal 0
[
r lrem mylist 1 nosuchelement
]
assert_equal 0
[
r lrem mylist 1 nosuchelement
]
assert_equal
{
foobar foobared zap test foo
}
[
r lrange mylist 0 -1
]
assert_equal
"
$e
foobar foobared zap test foo
"
[
r lrange mylist 0 -1
]
}
}
test
"LREM starting from tail with negative count -
$type
"
{
test
"LREM starting from tail with negative count -
$type
"
{
create_$type mylist
{
foo bar foobar foobared zap bar test foo foo
}
create_$type mylist
"
$e
foo bar foobar foobared zap bar test foo foo
"
assert_equal 1
[
r lrem mylist -1 bar
]
assert_equal 1
[
r lrem mylist -1 bar
]
assert_equal
{
foo bar foobar foobared zap test foo foo
}
[
r lrange mylist 0 -1
]
assert_equal
"
$e
foo bar foobar foobared zap test foo foo
"
[
r lrange mylist 0 -1
]
}
}
test
"LREM starting from tail with negative count (2) -
$type
"
{
test
"LREM starting from tail with negative count (2) -
$type
"
{
assert_equal 2
[
r lrem mylist -2 foo
]
assert_equal 2
[
r lrem mylist -2 foo
]
assert_equal
{
foo bar foobar foobared zap test
}
[
r lrange mylist 0 -1
]
assert_equal
"
$e
foo bar foobar foobared zap test
"
[
r lrange mylist 0 -1
]
}
}
test
"LREM deleting objects that may be int encoded -
$type
"
{
test
"LREM deleting objects that may be int encoded -
$type
"
{
create_$type myotherlist
{
1 2 3
}
create_$type myotherlist
"
$e
1 2 3
"
assert_equal 1
[
r lrem myotherlist 1 2
]
assert_equal 1
[
r lrem myotherlist 1 2
]
assert_equal
2
[
r llen myotherlist
]
assert_equal
3
[
r llen myotherlist
]
}
}
}
}
}
}
tests/unit/type/zset.tcl
View file @
aaada3f9
...
@@ -433,6 +433,42 @@ start_server {tags {"zset"}} {
...
@@ -433,6 +433,42 @@ start_server {tags {"zset"}} {
list
[
r zinterstore zsetc 2 zseta zsetb aggregate max
]
[
r zrange zsetc 0 -1 withscores
]
list
[
r zinterstore zsetc 2 zseta zsetb aggregate max
]
[
r zrange zsetc 0 -1 withscores
]
}
{
2
{
b 2 c 3
}}
}
{
2
{
b 2 c 3
}}
foreach cmd
{
ZUNIONSTORE ZINTERSTORE
}
{
test
"
$cmd
with +inf/-inf scores"
{
r del zsetinf1 zsetinf2
r zadd zsetinf1 +inf key
r zadd zsetinf2 +inf key
r $cmd zsetinf3 2 zsetinf1 zsetinf2
assert_equal inf
[
r zscore zsetinf3 key
]
r zadd zsetinf1 -inf key
r zadd zsetinf2 +inf key
r $cmd zsetinf3 2 zsetinf1 zsetinf2
assert_equal 0
[
r zscore zsetinf3 key
]
r zadd zsetinf1 +inf key
r zadd zsetinf2 -inf key
r $cmd zsetinf3 2 zsetinf1 zsetinf2
assert_equal 0
[
r zscore zsetinf3 key
]
r zadd zsetinf1 -inf key
r zadd zsetinf2 -inf key
r $cmd zsetinf3 2 zsetinf1 zsetinf2
assert_equal -inf
[
r zscore zsetinf3 key
]
}
test
"
$cmd
with NaN weights"
{
r del zsetinf1 zsetinf2
r zadd zsetinf1 1.0 key
r zadd zsetinf2 1.0 key
assert_error
"*weight value is not a double*"
{
r $cmd zsetinf3 2 zsetinf1 zsetinf2 weights nan nan
}
}
}
tags
{
"slow"
}
{
tags
{
"slow"
}
{
test
{
ZSETs skiplist implementation backlink consistency test
}
{
test
{
ZSETs skiplist implementation backlink consistency test
}
{
set diff 0
set diff 0
...
@@ -477,22 +513,16 @@ start_server {tags {"zset"}} {
...
@@ -477,22 +513,16 @@ start_server {tags {"zset"}} {
}
{}
}
{}
}
}
test
{
ZSET element can't be set to nan with ZADD
}
{
test
{
ZSET element can't be set to NaN with ZADD
}
{
set e
{}
assert_error
"*not a double*"
{
r zadd myzset nan abc
}
catch
{
r zadd myzset nan abc
}
e
}
set _ $e
}
{
*Not A Number*
}
test
{
ZSET element can't be set to nan with ZINCRBY
}
{
test
{
ZSET element can't be set to NaN with ZINCRBY
}
{
set e
{}
assert_error
"*not a double*"
{
r zadd myzset nan abc
}
catch
{
r zincrby myzset nan abc
}
e
}
set _ $e
}
{
*Not A Number*
}
test
{
ZINCRBY calls leading to Nan are refused
}
{
test
{
ZINCRBY calls leading to NaN result in error
}
{
set e
{}
r zincrby myzset +inf abc
r zincrby myzset +inf abc
catch
{
r zincrby myzset -inf abc
}
e
assert_error
"*NaN*"
{
r zincrby myzset -inf abc
}
set _ $e
}
}
{
*Not A Number*
}
}
}
Prev
1
2
Next
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