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
fdaab023
Commit
fdaab023
authored
Apr 22, 2014
by
yoav
Browse files
Merge remote-tracking branch 'upstream/unstable' into unstable
parents
4930d903
9caa1ae9
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
redis.conf
View file @
fdaab023
...
...
@@ -682,6 +682,20 @@ set-max-intset-entries 512
zset
-
max
-
ziplist
-
entries
128
zset
-
max
-
ziplist
-
value
64
# HyperLogLog sparse representation bytes limit. The limit includes the
# 16 bytes header. When an HyperLogLog using the sparse representation crosses
# this limit, it is convereted into the dense representation.
#
# A value greater than 16000 is totally useless, since at that point the
# dense representation is more memory efficient.
#
# The suggested value is ~ 3000 in order to have the benefits of
# the space efficient encoding without slowing down too much PFADD,
# which is O(N) with the sparse encoding. Thev value can be raised to
# ~ 10000 when CPU is not a concern, but space is, and the data set is
# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.
hll
-
sparse
-
max
-
bytes
3000
# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
# order to help rehashing the main Redis hash table (the one mapping top-level
# keys to values). The hash table implementation Redis uses (see dict.c)
...
...
src/cluster.c
View file @
fdaab023
...
...
@@ -1178,8 +1178,9 @@ void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoc
"I've still keys about this slot! "
"Putting the slot in IMPORTING state. "
"Please run the 'redis-trib fix' command."
,
j
,
sender
->
name
,
senderConfigEpoch
,
myself
->
configEpoch
);
j
,
sender
->
name
,
(
unsigned
long
long
)
senderConfigEpoch
,
(
unsigned
long
long
)
myself
->
configEpoch
);
server
.
cluster
->
importing_slots_from
[
j
]
=
sender
;
}
...
...
src/config.c
View file @
fdaab023
...
...
@@ -391,6 +391,8 @@ void loadServerConfigFromString(char *config) {
server
.
zset_max_ziplist_entries
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"zset-max-ziplist-value"
)
&&
argc
==
2
)
{
server
.
zset_max_ziplist_value
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hll-sparse-max-bytes"
)
&&
argc
==
2
)
{
server
.
hll_sparse_max_bytes
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"rename-command"
)
&&
argc
==
3
)
{
struct
redisCommand
*
cmd
=
lookupCommand
(
argv
[
1
]);
int
retval
;
...
...
@@ -765,6 +767,9 @@ void configSetCommand(redisClient *c) {
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"zset-max-ziplist-value"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
server
.
zset_max_ziplist_value
=
ll
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"hll-sparse-max-bytes"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
server
.
hll_sparse_max_bytes
=
ll
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"lua-time-limit"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
server
.
lua_time_limit
=
ll
;
...
...
@@ -974,6 +979,8 @@ void configGetCommand(redisClient *c) {
server
.
zset_max_ziplist_entries
);
config_get_numerical_field
(
"zset-max-ziplist-value"
,
server
.
zset_max_ziplist_value
);
config_get_numerical_field
(
"hll-sparse-max-bytes"
,
server
.
hll_sparse_max_bytes
);
config_get_numerical_field
(
"lua-time-limit"
,
server
.
lua_time_limit
);
config_get_numerical_field
(
"slowlog-log-slower-than"
,
server
.
slowlog_log_slower_than
);
...
...
@@ -1773,6 +1780,7 @@ int rewriteConfig(char *path) {
rewriteConfigNumericalOption
(
state
,
"set-max-intset-entries"
,
server
.
set_max_intset_entries
,
REDIS_SET_MAX_INTSET_ENTRIES
);
rewriteConfigNumericalOption
(
state
,
"zset-max-ziplist-entries"
,
server
.
zset_max_ziplist_entries
,
REDIS_ZSET_MAX_ZIPLIST_ENTRIES
);
rewriteConfigNumericalOption
(
state
,
"zset-max-ziplist-value"
,
server
.
zset_max_ziplist_value
,
REDIS_ZSET_MAX_ZIPLIST_VALUE
);
rewriteConfigNumericalOption
(
state
,
"hll-sparse-max-bytes"
,
server
.
hll_sparse_max_bytes
,
REDIS_DEFAULT_HLL_SPARSE_MAX_BYTES
);
rewriteConfigYesNoOption
(
state
,
"activerehashing"
,
server
.
activerehashing
,
REDIS_DEFAULT_ACTIVE_REHASHING
);
rewriteConfigClientoutputbufferlimitOption
(
state
);
rewriteConfigNumericalOption
(
state
,
"hz"
,
server
.
hz
,
REDIS_DEFAULT_HZ
);
...
...
src/db.c
View file @
fdaab023
...
...
@@ -1143,7 +1143,7 @@ unsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int coun
range
.
min
=
range
.
max
=
hashslot
;
range
.
minex
=
range
.
maxex
=
0
;
n
=
zslFirstInRange
(
server
.
cluster
->
slots_to_keys
,
range
);
n
=
zslFirstInRange
(
server
.
cluster
->
slots_to_keys
,
&
range
);
while
(
n
&&
n
->
score
==
hashslot
&&
count
--
)
{
keys
[
j
++
]
=
n
->
obj
;
n
=
n
->
level
[
0
].
forward
;
...
...
@@ -1161,7 +1161,7 @@ unsigned int countKeysInSlot(unsigned int hashslot) {
range
.
minex
=
range
.
maxex
=
0
;
/* Find first element in range */
zn
=
zslFirstInRange
(
zsl
,
range
);
zn
=
zslFirstInRange
(
zsl
,
&
range
);
/* Use rank of first element, if any, to determine preliminary count */
if
(
zn
!=
NULL
)
{
...
...
@@ -1169,7 +1169,7 @@ unsigned int countKeysInSlot(unsigned int hashslot) {
count
=
(
zsl
->
length
-
(
rank
-
1
));
/* Find last element in range */
zn
=
zslLastInRange
(
zsl
,
range
);
zn
=
zslLastInRange
(
zsl
,
&
range
);
/* Use rank of last element, if any, to determine the actual count */
if
(
zn
!=
NULL
)
{
...
...
src/hyperloglog.c
View file @
fdaab023
This diff is collapsed.
Click to expand it.
src/redis.c
View file @
fdaab023
...
...
@@ -171,6 +171,7 @@ struct redisCommand redisCommandTable[] = {
{
"zrem"
,
zremCommand
,
-
3
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zremrangebyscore"
,
zremrangebyscoreCommand
,
4
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zremrangebyrank"
,
zremrangebyrankCommand
,
4
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zremrangebylex"
,
zremrangebylexCommand
,
4
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zunionstore"
,
zunionstoreCommand
,
-
4
,
"wm"
,
0
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
},
{
"zinterstore"
,
zinterstoreCommand
,
-
4
,
"wm"
,
0
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
},
{
"zrange"
,
zrangeCommand
,
-
4
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
...
...
@@ -179,6 +180,7 @@ struct redisCommand redisCommandTable[] = {
{
"zrangebylex"
,
zrangebylexCommand
,
-
4
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zrevrangebylex"
,
zrevrangebylexCommand
,
-
4
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zcount"
,
zcountCommand
,
4
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zlexcount"
,
zlexcountCommand
,
4
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zrevrange"
,
zrevrangeCommand
,
-
4
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zcard"
,
zcardCommand
,
2
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zscore"
,
zscoreCommand
,
3
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
...
...
@@ -272,9 +274,9 @@ struct redisCommand redisCommandTable[] = {
{
"wait"
,
waitCommand
,
3
,
"rs"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"pfselftest"
,
pfselftestCommand
,
1
,
"r"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"pfadd"
,
pfaddCommand
,
-
2
,
"wm"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"pfcount"
,
pfcountCommand
,
2
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"pfcount"
,
pfcountCommand
,
-
2
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"pfmerge"
,
pfmergeCommand
,
-
2
,
"wm"
,
0
,
NULL
,
1
,
-
1
,
1
,
0
,
0
},
{
"pf
getreg"
,
pfgetre
gCommand
,
2
,
"
r
"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
}
{
"pf
debug"
,
pfdebu
gCommand
,
-
3
,
"
w
"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
}
};
struct
evictionPoolEntry
*
evictionPoolAlloc
(
void
);
...
...
@@ -1421,6 +1423,7 @@ void initServerConfig() {
server
.
set_max_intset_entries
=
REDIS_SET_MAX_INTSET_ENTRIES
;
server
.
zset_max_ziplist_entries
=
REDIS_ZSET_MAX_ZIPLIST_ENTRIES
;
server
.
zset_max_ziplist_value
=
REDIS_ZSET_MAX_ZIPLIST_VALUE
;
server
.
hll_sparse_max_bytes
=
REDIS_DEFAULT_HLL_SPARSE_MAX_BYTES
;
server
.
shutdown_asap
=
0
;
server
.
repl_ping_slave_period
=
REDIS_REPL_PING_SLAVE_PERIOD
;
server
.
repl_timeout
=
REDIS_REPL_TIMEOUT
;
...
...
@@ -1555,24 +1558,28 @@ void adjustOpenFilesLimit(void) {
redisLog
(
REDIS_WARNING
,
"Your current 'ulimit -n' "
"of %llu is not enough for Redis to start. "
"Please increase your open file limit to at least "
"%llu. Exiting."
,
oldlimit
,
maxfiles
);
"%llu. Exiting."
,
(
unsigned
long
long
)
oldlimit
,
(
unsigned
long
long
)
maxfiles
);
exit
(
1
);
}
redisLog
(
REDIS_WARNING
,
"You requested maxclients of %d "
"requiring at least %llu max file descriptors."
,
old_maxclients
,
maxfiles
);
old_maxclients
,
(
unsigned
long
long
)
maxfiles
);
redisLog
(
REDIS_WARNING
,
"Redis can't set maximum open files "
"to %llu because of OS error: %s."
,
maxfiles
,
strerror
(
setrlimit_error
));
(
unsigned
long
long
)
maxfiles
,
strerror
(
setrlimit_error
));
redisLog
(
REDIS_WARNING
,
"Current maximum open files is %llu. "
"maxclients has been reduced to %d to compensate for "
"low ulimit. "
"If you need higher maxclients increase 'ulimit -n'."
,
oldlimit
,
server
.
maxclients
);
(
unsigned
long
long
)
oldlimit
,
server
.
maxclients
);
}
else
{
redisLog
(
REDIS_NOTICE
,
"Increased maximum number of open files "
"to %llu (it was originally set to %llu)."
,
maxfiles
,
oldlimit
);
(
unsigned
long
long
)
maxfiles
,
(
unsigned
long
long
)
oldlimit
);
}
}
}
...
...
src/redis.h
View file @
fdaab023
...
...
@@ -312,6 +312,9 @@
#define REDIS_ZSET_MAX_ZIPLIST_ENTRIES 128
#define REDIS_ZSET_MAX_ZIPLIST_VALUE 64
/* HyperLogLog defines */
#define REDIS_DEFAULT_HLL_SPARSE_MAX_BYTES 3000
/* Sets operations codes */
#define REDIS_OP_UNION 0
#define REDIS_OP_DIFF 1
...
...
@@ -809,6 +812,7 @@ struct redisServer {
size_t
set_max_intset_entries
;
size_t
zset_max_ziplist_entries
;
size_t
zset_max_ziplist_value
;
size_t
hll_sparse_max_bytes
;
time_t
unixtime
;
/* Unix time sampled every cron cycle. */
long
long
mstime
;
/* Like 'unixtime' but with milliseconds resolution. */
/* Pubsub */
...
...
@@ -1147,8 +1151,8 @@ void zslFree(zskiplist *zsl);
zskiplistNode
*
zslInsert
(
zskiplist
*
zsl
,
double
score
,
robj
*
obj
);
unsigned
char
*
zzlInsert
(
unsigned
char
*
zl
,
robj
*
ele
,
double
score
);
int
zslDelete
(
zskiplist
*
zsl
,
double
score
,
robj
*
obj
);
zskiplistNode
*
zslFirstInRange
(
zskiplist
*
zsl
,
zrangespec
range
);
zskiplistNode
*
zslLastInRange
(
zskiplist
*
zsl
,
zrangespec
range
);
zskiplistNode
*
zslFirstInRange
(
zskiplist
*
zsl
,
zrangespec
*
range
);
zskiplistNode
*
zslLastInRange
(
zskiplist
*
zsl
,
zrangespec
*
range
);
double
zzlGetScore
(
unsigned
char
*
sptr
);
void
zzlNext
(
unsigned
char
*
zl
,
unsigned
char
**
eptr
,
unsigned
char
**
sptr
);
void
zzlPrev
(
unsigned
char
*
zl
,
unsigned
char
**
eptr
,
unsigned
char
**
sptr
);
...
...
@@ -1396,11 +1400,13 @@ void zrevrangebyscoreCommand(redisClient *c);
void
zrangebylexCommand
(
redisClient
*
c
);
void
zrevrangebylexCommand
(
redisClient
*
c
);
void
zcountCommand
(
redisClient
*
c
);
void
zlexcountCommand
(
redisClient
*
c
);
void
zrevrangeCommand
(
redisClient
*
c
);
void
zcardCommand
(
redisClient
*
c
);
void
zremCommand
(
redisClient
*
c
);
void
zscoreCommand
(
redisClient
*
c
);
void
zremrangebyscoreCommand
(
redisClient
*
c
);
void
zremrangebylexCommand
(
redisClient
*
c
);
void
multiCommand
(
redisClient
*
c
);
void
execCommand
(
redisClient
*
c
);
void
discardCommand
(
redisClient
*
c
);
...
...
@@ -1460,7 +1466,7 @@ void pfselftestCommand(redisClient *c);
void
pfaddCommand
(
redisClient
*
c
);
void
pfcountCommand
(
redisClient
*
c
);
void
pfmergeCommand
(
redisClient
*
c
);
void
pf
getre
gCommand
(
redisClient
*
c
);
void
pf
debu
gCommand
(
redisClient
*
c
);
#if defined(__GNUC__)
void
*
calloc
(
size_t
count
,
size_t
size
)
__attribute__
((
deprecated
));
...
...
src/t_zset.c
View file @
fdaab023
This diff is collapsed.
Click to expand it.
tests/unit/hyperloglog.tcl
View file @
fdaab023
...
...
@@ -39,6 +39,82 @@ start_server {tags {"hll"}} {
set res
}
{
5 10
}
test
{
HyperLogLogs are promote from sparse to dense
}
{
r del hll
r config set hll-sparse-max-bytes 3000
set n 0
while
{
$n
< 100000
}
{
set elements
{}
for
{
set j 0
}
{
$j
< 100
}
{
incr j
}
{
lappend elements
[
expr rand
()]}
incr n 100
r pfadd hll
{*}
$elements
set card
[
r pfcount hll
]
set err
[
expr
{
abs
(
$card-$n
)}]
assert
{
$err
<
(
double
(
$card
)
/100
)
*5
}
if
{
$n
< 1000
}
{
assert
{[
r pfdebug encoding hll
]
eq
{
sparse
}}
}
elseif
{
$n
> 10000
}
{
assert
{[
r pfdebug encoding hll
]
eq
{
dense
}}
}
}
}
test
{
HyperLogLog sparse encoding stress test
}
{
for
{
set x 0
}
{
$x
< 1000
}
{
incr x
}
{
r del hll1 hll2
set numele
[
randomInt 100
]
set elements
{}
for
{
set j 0
}
{
$j
< $numele
}
{
incr j
}
{
lappend elements
[
expr rand
()]
}
# Force dense representation of hll2
r pfadd hll2
r pfdebug todense hll2
r pfadd hll1
{*}
$elements
r pfadd hll2
{*}
$elements
assert
{[
r pfdebug encoding hll1
]
eq
{
sparse
}}
assert
{[
r pfdebug encoding hll2
]
eq
{
dense
}}
# Cardinality estimated should match exactly.
assert
{[
r pfcount hll1
]
eq
[
r pfcount hll2
]}
}
}
test
{
Corrupted sparse HyperLogLogs are detected: Additionl at tail
}
{
r del hll
r pfadd hll a b c
r append hll
"hello"
set e
{}
catch
{
r pfcount hll
}
e
set e
}
{
*INVALIDOBJ*
}
test
{
Corrupted sparse HyperLogLogs are detected: Broken magic
}
{
r del hll
r pfadd hll a b c
r setrange hll 0
"0123"
set e
{}
catch
{
r pfcount hll
}
e
set e
}
{
*WRONGTYPE*
}
test
{
Corrupted sparse HyperLogLogs are detected: Invalid encoding
}
{
r del hll
r pfadd hll a b c
r setrange hll 4
"x"
set e
{}
catch
{
r pfcount hll
}
e
set e
}
{
*WRONGTYPE*
}
test
{
Corrupted dense HyperLogLogs are detected: Wrong length
}
{
r del hll
r pfadd hll a b c
r setrange hll 4
"
\x00
"
set e
{}
catch
{
r pfcount hll
}
e
set e
}
{
*WRONGTYPE*
}
test
{
PFADD, PFCOUNT, PFMERGE type checking works
}
{
r set foo bar
catch
{
r pfadd foo 1
}
e
...
...
@@ -60,9 +136,24 @@ start_server {tags {"hll"}} {
r pfcount hll
}
{
5
}
test
{
PFGETREG returns the HyperLogLog raw registers
}
{
test
{
PFCOUNT multiple-keys merge returns cardinality of union
}
{
r del hll1 hll2 hll3
for
{
set x 1
}
{
$x
< 10000
}
{
incr x
}
{
# Force dense representation of hll2
r pfadd hll1
"foo-
$x
"
r pfadd hll2
"bar-
$x
"
r pfadd hll3
"zap-
$x
"
set card
[
r pfcount hll1 hll2 hll3
]
set realcard
[
expr
{
$x
*3
}]
set err
[
expr
{
abs
(
$card-$realcard
)}]
assert
{
$err
<
(
double
(
$card
)
/100
)
*5
}
}
}
test
{
PFDEBUG GETREG returns the HyperLogLog raw registers
}
{
r del hll
r pfadd hll 1 2 3
llength
[
r pfgetreg hll
]
llength
[
r pf
debug
getreg hll
]
}
{
16384
}
}
tests/unit/type/zset.tcl
View file @
fdaab023
...
...
@@ -296,6 +296,62 @@ start_server {tags {"zset"}} {
assert_error
"*not*float*"
{
r zrangebyscore fooz 1 NaN
}
}
proc create_default_lex_zset
{}
{
create_zset zset
{
0 alpha 0 bar 0 cool 0 down
0 elephant 0 foo 0 great 0 hill
0 omega
}
}
test
"ZRANGEBYLEX/ZREVRANGEBYLEX/ZCOUNT basics"
{
create_default_lex_zset
# inclusive range
assert_equal
{
alpha bar cool
}
[
r zrangebylex zset -
\[
cool
]
assert_equal
{
bar cool down
}
[
r zrangebylex zset
\[
bar
\[
down
]
assert_equal
{
great hill omega
}
[
r zrangebylex zset
\[
g +
]
assert_equal
{
cool bar alpha
}
[
r zrevrangebylex zset
\[
cool -
]
assert_equal
{
down cool bar
}
[
r zrevrangebylex zset
\[
down
\[
bar
]
assert_equal
{
omega hill great foo elephant down
}
[
r zrevrangebylex zset +
\[
d
]
assert_equal 3
[
r zlexcount zset
\[
ele
\[
h
]
# exclusive range
assert_equal
{
alpha bar
}
[
r zrangebylex zset -
(
cool
]
assert_equal
{
cool
}
[
r zrangebylex zset
(
bar
(
down
]
assert_equal
{
hill omega
}
[
r zrangebylex zset
(
great +
]
assert_equal
{
bar alpha
}
[
r zrevrangebylex zset
(
cool -
]
assert_equal
{
cool
}
[
r zrevrangebylex zset
(
down
(
bar
]
assert_equal
{
omega hill
}
[
r zrevrangebylex zset +
(
great
]
assert_equal 2
[
r zlexcount zset
(
ele
(
great
]
# inclusive and exclusive
assert_equal
{}
[
r zrangebylex zset
(
az
(
b
]
assert_equal
{}
[
r zrangebylex zset
(
z +
]
assert_equal
{}
[
r zrangebylex zset -
\[
aaaa
]
assert_equal
{}
[
r zrevrangebylex zset
\[
elez
\[
elex
]
assert_equal
{}
[
r zrevrangebylex zset
(
hill
(
omega
]
}
test
"ZRANGEBYSLEX with LIMIT"
{
create_default_lex_zset
assert_equal
{
alpha bar
}
[
r zrangebylex zset -
\[
cool LIMIT 0 2
]
assert_equal
{
bar cool
}
[
r zrangebylex zset -
\[
cool LIMIT 1 2
]
assert_equal
{}
[
r zrangebylex zset
\[
bar
\[
down LIMIT 0 0
]
assert_equal
{}
[
r zrangebylex zset
\[
bar
\[
down LIMIT 2 0
]
assert_equal
{
bar
}
[
r zrangebylex zset
\[
bar
\[
down LIMIT 0 1
]
assert_equal
{
cool
}
[
r zrangebylex zset
\[
bar
\[
down LIMIT 1 1
]
assert_equal
{
bar cool down
}
[
r zrangebylex zset
\[
bar
\[
down LIMIT 0 100
]
assert_equal
{
omega hill great foo elephant
}
[
r zrevrangebylex zset +
\[
d LIMIT 0 5
]
assert_equal
{
omega hill great foo
}
[
r zrevrangebylex zset +
\[
d LIMIT 0 4
]
}
test
"ZRANGEBYLEX with invalid lex range specifiers"
{
assert_error
"*not*string*"
{
r zrangebylex fooz foo bar
}
assert_error
"*not*string*"
{
r zrangebylex fooz
\[
foo bar
}
assert_error
"*not*string*"
{
r zrangebylex fooz foo
\[
bar
}
assert_error
"*not*string*"
{
r zrangebylex fooz +x
\[
bar
}
assert_error
"*not*string*"
{
r zrangebylex fooz -x
\[
bar
}
}
test
"ZREMRANGEBYSCORE basics"
{
proc remrangebyscore
{
min max
}
{
create_zset zset
{
1 a 2 b 3 c 4 d 5 e
}
...
...
@@ -708,6 +764,111 @@ start_server {tags {"zset"}} {
assert_equal
{}
$err
}
test
"ZRANGEBYLEX fuzzy test, 100 ranges in
$elements
element sorted set -
$encoding
"
{
set lexset
{}
r del zset
for
{
set j 0
}
{
$j
< $elements
}
{
incr j
}
{
set e
[
randstring 0 30 alpha
]
lappend lexset $e
r zadd zset 0 $e
}
set lexset
[
lsort -unique $lexset
]
for
{
set j 0
}
{
$j
< 100
}
{
incr j
}
{
set min
[
randstring 0 30 alpha
]
set max
[
randstring 0 30 alpha
]
set mininc
[
randomInt 2
]
set maxinc
[
randomInt 2
]
if
{
$mininc
}
{
set cmin
"
\[
$min
"
}
else
{
set cmin
"(
$min
"
}
if
{
$maxinc
}
{
set cmax
"
\[
$max
"
}
else
{
set cmax
"(
$max
"
}
set rev
[
randomInt 2
]
if
{
$rev
}
{
set cmd zrevrangebylex
}
else
{
set cmd zrangebylex
}
# Make sure data is the same in both sides
assert
{[
r zrange zset 0 -1
]
eq $lexset
}
# Get the Redis output
set output
[
r $cmd zset $cmin $cmax
]
if
{
$rev
}
{
set outlen
[
r zlexcount zset $cmax $cmin
]
}
else
{
set outlen
[
r zlexcount zset $cmin $cmax
]
}
# Compute the same output via Tcl
set o
{}
set copy $lexset
if
{(
!$rev &&
[
string compare $min $max
]
> 0
)
||
(
$rev
&&
[
string compare $max $min
]
> 0
)}
{
# Empty output when ranges are inverted.
}
else
{
if
{
$rev
}
{
# Invert the Tcl array using Redis itself.
set copy
[
r zrevrange zset 0 -1
]
# Invert min / max as well
lassign
[
list $min $max $mininc $maxinc
]
\
max min maxinc mininc
}
foreach e $copy
{
set mincmp
[
string compare $e $min
]
set maxcmp
[
string compare $e $max
]
if
{
(
$mininc
&& $mincmp >= 0 || !$mininc && $mincmp > 0
)
&&
(
$maxinc
&& $maxcmp <= 0 || !$maxinc && $maxcmp < 0
)
}
{
lappend o $e
}
}
}
assert
{
$o
eq $output
}
assert
{
$outlen
eq
[
llength $output
]}
}
}
test
"ZREMRANGEBYLEX fuzzy test, 100 ranges in
$elements
element sorted set -
$encoding
"
{
set lexset
{}
r del zset zsetcopy
for
{
set j 0
}
{
$j
< $elements
}
{
incr j
}
{
set e
[
randstring 0 30 alpha
]
lappend lexset $e
r zadd zset 0 $e
}
set lexset
[
lsort -unique $lexset
]
for
{
set j 0
}
{
$j
< 100
}
{
incr j
}
{
# Copy...
r zunionstore zsetcopy 1 zset
set lexsetcopy $lexset
set min
[
randstring 0 30 alpha
]
set max
[
randstring 0 30 alpha
]
set mininc
[
randomInt 2
]
set maxinc
[
randomInt 2
]
if
{
$mininc
}
{
set cmin
"
\[
$min
"
}
else
{
set cmin
"(
$min
"
}
if
{
$maxinc
}
{
set cmax
"
\[
$max
"
}
else
{
set cmax
"(
$max
"
}
# Make sure data is the same in both sides
assert
{[
r zrange zset 0 -1
]
eq $lexset
}
# Get the range we are going to remove
set torem
[
r zrangebylex zset $cmin $cmax
]
set toremlen
[
r zlexcount zset $cmin $cmax
]
r zremrangebylex zsetcopy $cmin $cmax
set output
[
r zrange zsetcopy 0 -1
]
# Remove the range with Tcl from the original list
if
{
$toremlen
}
{
set first
[
lsearch -exact $lexsetcopy
[
lindex $torem 0
]]
set last
[
expr
{
$first
+$toremlen-1
}]
set lexsetcopy
[
lreplace $lexsetcopy $first $last
]
}
assert
{
$lexsetcopy
eq $output
}
}
}
test
"ZSETs skiplist implementation backlink consistency test -
$encoding
"
{
set diff 0
for
{
set j 0
}
{
$j
< $elements
}
{
incr j
}
{
...
...
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