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
7c0e1b53
Commit
7c0e1b53
authored
Apr 14, 2011
by
antirez
Browse files
Merge remote branch 'pietern/unstable-zset' into unstable
parents
d0cfb2be
02e60065
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
redis.conf
View file @
7c0e1b53
...
@@ -340,6 +340,12 @@ list-max-ziplist-value 64
...
@@ -340,6 +340,12 @@ list-max-ziplist-value 64
# set in order to use this special memory saving encoding.
# set in order to use this special memory saving encoding.
set
-
max
-
intset
-
entries
512
set
-
max
-
intset
-
entries
512
# Similarly to hashes and lists, sorted sets are also specially encoded in
# order to save a lot of space. This encoding is only used when the length and
# elements of a sorted set are below the following limits:
zset
-
max
-
ziplist
-
entries
128
zset
-
max
-
ziplist
-
value
64
# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
# 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
# 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)
# keys to values). The hash table implementation redis uses (see dict.c)
...
...
src/aof.c
View file @
7c0e1b53
...
@@ -429,21 +429,55 @@ int rewriteAppendOnlyFile(char *filename) {
...
@@ -429,21 +429,55 @@ int rewriteAppendOnlyFile(char *filename) {
}
}
}
else
if
(
o
->
type
==
REDIS_ZSET
)
{
}
else
if
(
o
->
type
==
REDIS_ZSET
)
{
/* Emit the ZADDs needed to rebuild the sorted set */
/* Emit the ZADDs needed to rebuild the sorted set */
zset
*
zs
=
o
->
ptr
;
char
cmd
[]
=
"*4
\r\n
$4
\r\n
ZADD
\r\n
"
;
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictEntry
*
de
;
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
unsigned
char
*
zl
=
o
->
ptr
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
unsigned
char
*
eptr
,
*
sptr
;
char
cmd
[]
=
"*4
\r\n
$4
\r\n
ZADD
\r\n
"
;
unsigned
char
*
vstr
;
robj
*
eleobj
=
dictGetEntryKey
(
de
);
unsigned
int
vlen
;
double
*
score
=
dictGetEntryVal
(
de
);
long
long
vll
;
double
score
;
if
(
fwrite
(
cmd
,
sizeof
(
cmd
)
-
1
,
1
,
fp
)
==
0
)
goto
werr
;
if
(
fwriteBulkObject
(
fp
,
&
key
)
==
0
)
goto
werr
;
eptr
=
ziplistIndex
(
zl
,
0
);
if
(
fwriteBulkDouble
(
fp
,
*
score
)
==
0
)
goto
werr
;
redisAssert
(
eptr
!=
NULL
);
if
(
fwriteBulkObject
(
fp
,
eleobj
)
==
0
)
goto
werr
;
sptr
=
ziplistNext
(
zl
,
eptr
);
redisAssert
(
sptr
!=
NULL
);
while
(
eptr
!=
NULL
)
{
redisAssert
(
ziplistGet
(
eptr
,
&
vstr
,
&
vlen
,
&
vll
));
score
=
zzlGetScore
(
sptr
);
if
(
fwrite
(
cmd
,
sizeof
(
cmd
)
-
1
,
1
,
fp
)
==
0
)
goto
werr
;
if
(
fwriteBulkObject
(
fp
,
&
key
)
==
0
)
goto
werr
;
if
(
fwriteBulkDouble
(
fp
,
score
)
==
0
)
goto
werr
;
if
(
vstr
!=
NULL
)
{
if
(
fwriteBulkString
(
fp
,(
char
*
)
vstr
,
vlen
)
==
0
)
goto
werr
;
}
else
{
if
(
fwriteBulkLongLong
(
fp
,
vll
)
==
0
)
goto
werr
;
}
zzlNext
(
zl
,
&
eptr
,
&
sptr
);
}
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_SKIPLIST
)
{
zset
*
zs
=
o
->
ptr
;
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictEntry
*
de
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
eleobj
=
dictGetEntryKey
(
de
);
double
*
score
=
dictGetEntryVal
(
de
);
if
(
fwrite
(
cmd
,
sizeof
(
cmd
)
-
1
,
1
,
fp
)
==
0
)
goto
werr
;
if
(
fwriteBulkObject
(
fp
,
&
key
)
==
0
)
goto
werr
;
if
(
fwriteBulkDouble
(
fp
,
*
score
)
==
0
)
goto
werr
;
if
(
fwriteBulkObject
(
fp
,
eleobj
)
==
0
)
goto
werr
;
}
dictReleaseIterator
(
di
);
}
else
{
redisPanic
(
"Unknown sorted set encoding"
);
}
}
dictReleaseIterator
(
di
);
}
else
if
(
o
->
type
==
REDIS_HASH
)
{
}
else
if
(
o
->
type
==
REDIS_HASH
)
{
char
cmd
[]
=
"*4
\r\n
$4
\r\n
HSET
\r\n
"
;
char
cmd
[]
=
"*4
\r\n
$4
\r\n
HSET
\r\n
"
;
...
...
src/config.c
View file @
7c0e1b53
...
@@ -261,6 +261,10 @@ void loadServerConfig(char *filename) {
...
@@ -261,6 +261,10 @@ void loadServerConfig(char *filename) {
server
.
list_max_ziplist_value
=
memtoll
(
argv
[
1
],
NULL
);
server
.
list_max_ziplist_value
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"set-max-intset-entries"
)
&&
argc
==
2
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"set-max-intset-entries"
)
&&
argc
==
2
)
{
server
.
set_max_intset_entries
=
memtoll
(
argv
[
1
],
NULL
);
server
.
set_max_intset_entries
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"zset-max-ziplist-entries"
)
&&
argc
==
2
)
{
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
],
"rename-command"
)
&&
argc
==
3
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"rename-command"
)
&&
argc
==
3
)
{
struct
redisCommand
*
cmd
=
lookupCommand
(
argv
[
1
]);
struct
redisCommand
*
cmd
=
lookupCommand
(
argv
[
1
]);
int
retval
;
int
retval
;
...
@@ -450,6 +454,12 @@ void configSetCommand(redisClient *c) {
...
@@ -450,6 +454,12 @@ void configSetCommand(redisClient *c) {
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"set-max-intset-entries"
))
{
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"set-max-intset-entries"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
server
.
set_max_intset_entries
=
ll
;
server
.
set_max_intset_entries
=
ll
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"zset-max-ziplist-entries"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
server
.
zset_max_ziplist_entries
=
ll
;
}
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
{
}
else
{
addReplyErrorFormat
(
c
,
"Unsupported CONFIG parameter: %s"
,
addReplyErrorFormat
(
c
,
"Unsupported CONFIG parameter: %s"
,
(
char
*
)
c
->
argv
[
2
]
->
ptr
);
(
char
*
)
c
->
argv
[
2
]
->
ptr
);
...
@@ -601,6 +611,16 @@ void configGetCommand(redisClient *c) {
...
@@ -601,6 +611,16 @@ void configGetCommand(redisClient *c) {
addReplyBulkLongLong
(
c
,
server
.
set_max_intset_entries
);
addReplyBulkLongLong
(
c
,
server
.
set_max_intset_entries
);
matches
++
;
matches
++
;
}
}
if
(
stringmatch
(
pattern
,
"zset-max-ziplist-entries"
,
0
))
{
addReplyBulkCString
(
c
,
"zset-max-ziplist-entries"
);
addReplyBulkLongLong
(
c
,
server
.
zset_max_ziplist_entries
);
matches
++
;
}
if
(
stringmatch
(
pattern
,
"zset-max-ziplist-value"
,
0
))
{
addReplyBulkCString
(
c
,
"zset-max-ziplist-value"
);
addReplyBulkLongLong
(
c
,
server
.
zset_max_ziplist_value
);
matches
++
;
}
setDeferredMultiBulkLength
(
c
,
replylen
,
matches
*
2
);
setDeferredMultiBulkLength
(
c
,
replylen
,
matches
*
2
);
}
}
...
...
src/debug.c
View file @
7c0e1b53
...
@@ -127,22 +127,57 @@ void computeDatasetDigest(unsigned char *final) {
...
@@ -127,22 +127,57 @@ void computeDatasetDigest(unsigned char *final) {
}
}
setTypeReleaseIterator
(
si
);
setTypeReleaseIterator
(
si
);
}
else
if
(
o
->
type
==
REDIS_ZSET
)
{
}
else
if
(
o
->
type
==
REDIS_ZSET
)
{
zset
*
zs
=
o
->
ptr
;
unsigned
char
eledigest
[
20
];
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictEntry
*
de
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
robj
*
eleobj
=
dictGetEntryKey
(
de
);
unsigned
char
*
zl
=
o
->
ptr
;
double
*
score
=
dictGetEntryVal
(
de
);
unsigned
char
*
eptr
,
*
sptr
;
unsigned
char
eledigest
[
20
];
unsigned
char
*
vstr
;
unsigned
int
vlen
;
long
long
vll
;
double
score
;
snprintf
(
buf
,
sizeof
(
buf
),
"%.17g"
,
*
score
);
eptr
=
ziplistIndex
(
zl
,
0
);
memset
(
eledigest
,
0
,
20
);
redisAssert
(
eptr
!=
NULL
);
mixObjectDigest
(
eledigest
,
eleobj
);
sptr
=
ziplistNext
(
zl
,
eptr
);
mixDigest
(
eledigest
,
buf
,
strlen
(
buf
));
redisAssert
(
sptr
!=
NULL
);
xorDigest
(
digest
,
eledigest
,
20
);
while
(
eptr
!=
NULL
)
{
redisAssert
(
ziplistGet
(
eptr
,
&
vstr
,
&
vlen
,
&
vll
));
score
=
zzlGetScore
(
sptr
);
memset
(
eledigest
,
0
,
20
);
if
(
vstr
!=
NULL
)
{
mixDigest
(
eledigest
,
vstr
,
vlen
);
}
else
{
ll2string
(
buf
,
sizeof
(
buf
),
vll
);
mixDigest
(
eledigest
,
buf
,
strlen
(
buf
));
}
snprintf
(
buf
,
sizeof
(
buf
),
"%.17g"
,
score
);
mixDigest
(
eledigest
,
buf
,
strlen
(
buf
));
xorDigest
(
digest
,
eledigest
,
20
);
zzlNext
(
zl
,
&
eptr
,
&
sptr
);
}
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_SKIPLIST
)
{
zset
*
zs
=
o
->
ptr
;
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictEntry
*
de
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
eleobj
=
dictGetEntryKey
(
de
);
double
*
score
=
dictGetEntryVal
(
de
);
snprintf
(
buf
,
sizeof
(
buf
),
"%.17g"
,
*
score
);
memset
(
eledigest
,
0
,
20
);
mixObjectDigest
(
eledigest
,
eleobj
);
mixDigest
(
eledigest
,
buf
,
strlen
(
buf
));
xorDigest
(
digest
,
eledigest
,
20
);
}
dictReleaseIterator
(
di
);
}
else
{
redisPanic
(
"Unknown sorted set encoding"
);
}
}
dictReleaseIterator
(
di
);
}
else
if
(
o
->
type
==
REDIS_HASH
)
{
}
else
if
(
o
->
type
==
REDIS_HASH
)
{
hashTypeIterator
*
hi
;
hashTypeIterator
*
hi
;
robj
*
obj
;
robj
*
obj
;
...
...
src/object.c
View file @
7c0e1b53
...
@@ -102,6 +102,13 @@ robj *createZsetObject(void) {
...
@@ -102,6 +102,13 @@ robj *createZsetObject(void) {
return
o
;
return
o
;
}
}
robj
*
createZsetZiplistObject
(
void
)
{
unsigned
char
*
zl
=
ziplistNew
();
robj
*
o
=
createObject
(
REDIS_ZSET
,
zl
);
o
->
encoding
=
REDIS_ENCODING_ZIPLIST
;
return
o
;
}
void
freeStringObject
(
robj
*
o
)
{
void
freeStringObject
(
robj
*
o
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_RAW
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_RAW
)
{
sdsfree
(
o
->
ptr
);
sdsfree
(
o
->
ptr
);
...
@@ -135,11 +142,20 @@ void freeSetObject(robj *o) {
...
@@ -135,11 +142,20 @@ void freeSetObject(robj *o) {
}
}
void
freeZsetObject
(
robj
*
o
)
{
void
freeZsetObject
(
robj
*
o
)
{
zset
*
zs
=
o
->
ptr
;
zset
*
zs
;
switch
(
o
->
encoding
)
{
dictRelease
(
zs
->
dict
);
case
REDIS_ENCODING_SKIPLIST
:
zslFree
(
zs
->
zsl
);
zs
=
o
->
ptr
;
zfree
(
zs
);
dictRelease
(
zs
->
dict
);
zslFree
(
zs
->
zsl
);
zfree
(
zs
);
break
;
case
REDIS_ENCODING_ZIPLIST
:
zfree
(
o
->
ptr
);
break
;
default:
redisPanic
(
"Unknown sorted set encoding"
);
}
}
}
void
freeHashObject
(
robj
*
o
)
{
void
freeHashObject
(
robj
*
o
)
{
...
...
src/rdb.c
View file @
7c0e1b53
...
@@ -302,24 +302,33 @@ int rdbSaveObject(FILE *fp, robj *o) {
...
@@ -302,24 +302,33 @@ int rdbSaveObject(FILE *fp, robj *o) {
redisPanic
(
"Unknown set encoding"
);
redisPanic
(
"Unknown set encoding"
);
}
}
}
else
if
(
o
->
type
==
REDIS_ZSET
)
{
}
else
if
(
o
->
type
==
REDIS_ZSET
)
{
/* Save a set value */
/* Save a sorted set value */
zset
*
zs
=
o
->
ptr
;
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
size_t
l
=
ziplistBlobLen
((
unsigned
char
*
)
o
->
ptr
);
dictEntry
*
de
;
if
((
n
=
rdbSaveLen
(
fp
,
dictSize
(
zs
->
dict
)))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
eleobj
=
dictGetEntryKey
(
de
);
double
*
score
=
dictGetEntryVal
(
de
);
if
((
n
=
rdbSaveString
Object
(
fp
,
eleobj
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSave
Raw
String
(
fp
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
if
((
n
=
rdbSaveDoubleValue
(
fp
,
*
score
))
==
-
1
)
return
-
1
;
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_SKIPLIST
)
{
zset
*
zs
=
o
->
ptr
;
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictEntry
*
de
;
if
((
n
=
rdbSaveLen
(
fp
,
dictSize
(
zs
->
dict
)))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
eleobj
=
dictGetEntryKey
(
de
);
double
*
score
=
dictGetEntryVal
(
de
);
if
((
n
=
rdbSaveStringObject
(
fp
,
eleobj
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
if
((
n
=
rdbSaveDoubleValue
(
fp
,
*
score
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
}
dictReleaseIterator
(
di
);
}
else
{
redisPanic
(
"Unknown sorted set encoding"
);
}
}
dictReleaseIterator
(
di
);
}
else
if
(
o
->
type
==
REDIS_HASH
)
{
}
else
if
(
o
->
type
==
REDIS_HASH
)
{
/* Save a hash value */
/* Save a hash value */
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPMAP
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPMAP
)
{
...
@@ -386,6 +395,8 @@ int rdbSaveKeyValuePair(FILE *fp, robj *key, robj *val,
...
@@ -386,6 +395,8 @@ int rdbSaveKeyValuePair(FILE *fp, robj *key, robj *val,
vtype
=
REDIS_LIST_ZIPLIST
;
vtype
=
REDIS_LIST_ZIPLIST
;
else
if
(
vtype
==
REDIS_SET
&&
val
->
encoding
==
REDIS_ENCODING_INTSET
)
else
if
(
vtype
==
REDIS_SET
&&
val
->
encoding
==
REDIS_ENCODING_INTSET
)
vtype
=
REDIS_SET_INTSET
;
vtype
=
REDIS_SET_INTSET
;
else
if
(
vtype
==
REDIS_ZSET
&&
val
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
vtype
=
REDIS_ZSET_ZIPLIST
;
/* Save type, key, value */
/* Save type, key, value */
if
(
rdbSaveType
(
fp
,
vtype
)
==
-
1
)
return
-
1
;
if
(
rdbSaveType
(
fp
,
vtype
)
==
-
1
)
return
-
1
;
if
(
rdbSaveStringObject
(
fp
,
key
)
==
-
1
)
return
-
1
;
if
(
rdbSaveStringObject
(
fp
,
key
)
==
-
1
)
return
-
1
;
...
@@ -745,11 +756,13 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -745,11 +756,13 @@ robj *rdbLoadObject(int type, FILE *fp) {
}
else
if
(
type
==
REDIS_ZSET
)
{
}
else
if
(
type
==
REDIS_ZSET
)
{
/* Read list/set value */
/* Read list/set value */
size_t
zsetlen
;
size_t
zsetlen
;
size_t
maxelelen
=
0
;
zset
*
zs
;
zset
*
zs
;
if
((
zsetlen
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
zsetlen
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
o
=
createZsetObject
();
o
=
createZsetObject
();
zs
=
o
->
ptr
;
zs
=
o
->
ptr
;
/* Load every single element of the list/set */
/* Load every single element of the list/set */
while
(
zsetlen
--
)
{
while
(
zsetlen
--
)
{
robj
*
ele
;
robj
*
ele
;
...
@@ -759,10 +772,21 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -759,10 +772,21 @@ robj *rdbLoadObject(int type, FILE *fp) {
if
((
ele
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
ele
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
ele
=
tryObjectEncoding
(
ele
);
ele
=
tryObjectEncoding
(
ele
);
if
(
rdbLoadDoubleValue
(
fp
,
&
score
)
==
-
1
)
return
NULL
;
if
(
rdbLoadDoubleValue
(
fp
,
&
score
)
==
-
1
)
return
NULL
;
/* Don't care about integer-encoded strings. */
if
(
ele
->
encoding
==
REDIS_ENCODING_RAW
&&
sdslen
(
ele
->
ptr
)
>
maxelelen
)
maxelelen
=
sdslen
(
ele
->
ptr
);
znode
=
zslInsert
(
zs
->
zsl
,
score
,
ele
);
znode
=
zslInsert
(
zs
->
zsl
,
score
,
ele
);
dictAdd
(
zs
->
dict
,
ele
,
&
znode
->
score
);
dictAdd
(
zs
->
dict
,
ele
,
&
znode
->
score
);
incrRefCount
(
ele
);
/* added to skiplist */
incrRefCount
(
ele
);
/* added to skiplist */
}
}
/* Convert *after* loading, since sorted sets are not stored ordered. */
if
(
zsetLength
(
o
)
<=
server
.
zset_max_ziplist_entries
&&
maxelelen
<=
server
.
zset_max_ziplist_value
)
zsetConvert
(
o
,
REDIS_ENCODING_ZIPLIST
);
}
else
if
(
type
==
REDIS_HASH
)
{
}
else
if
(
type
==
REDIS_HASH
)
{
size_t
hashlen
;
size_t
hashlen
;
...
@@ -811,7 +835,8 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -811,7 +835,8 @@ robj *rdbLoadObject(int type, FILE *fp) {
}
}
}
else
if
(
type
==
REDIS_HASH_ZIPMAP
||
}
else
if
(
type
==
REDIS_HASH_ZIPMAP
||
type
==
REDIS_LIST_ZIPLIST
||
type
==
REDIS_LIST_ZIPLIST
||
type
==
REDIS_SET_INTSET
)
type
==
REDIS_SET_INTSET
||
type
==
REDIS_ZSET_ZIPLIST
)
{
{
robj
*
aux
=
rdbLoadStringObject
(
fp
);
robj
*
aux
=
rdbLoadStringObject
(
fp
);
...
@@ -846,8 +871,14 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -846,8 +871,14 @@ robj *rdbLoadObject(int type, FILE *fp) {
if
(
intsetLen
(
o
->
ptr
)
>
server
.
set_max_intset_entries
)
if
(
intsetLen
(
o
->
ptr
)
>
server
.
set_max_intset_entries
)
setTypeConvert
(
o
,
REDIS_ENCODING_HT
);
setTypeConvert
(
o
,
REDIS_ENCODING_HT
);
break
;
break
;
case
REDIS_ZSET_ZIPLIST
:
o
->
type
=
REDIS_ZSET
;
o
->
encoding
=
REDIS_ENCODING_ZIPLIST
;
if
(
zsetLength
(
o
)
>
server
.
zset_max_ziplist_entries
)
zsetConvert
(
o
,
REDIS_ENCODING_SKIPLIST
);
break
;
default:
default:
redisPanic
(
"Unknown enoding"
);
redisPanic
(
"Unknown en
c
oding"
);
break
;
break
;
}
}
}
else
{
}
else
{
...
...
src/redis.c
View file @
7c0e1b53
...
@@ -846,6 +846,8 @@ void initServerConfig() {
...
@@ -846,6 +846,8 @@ void initServerConfig() {
server
.
list_max_ziplist_entries
=
REDIS_LIST_MAX_ZIPLIST_ENTRIES
;
server
.
list_max_ziplist_entries
=
REDIS_LIST_MAX_ZIPLIST_ENTRIES
;
server
.
list_max_ziplist_value
=
REDIS_LIST_MAX_ZIPLIST_VALUE
;
server
.
list_max_ziplist_value
=
REDIS_LIST_MAX_ZIPLIST_VALUE
;
server
.
set_max_intset_entries
=
REDIS_SET_MAX_INTSET_ENTRIES
;
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
.
shutdown_asap
=
0
;
server
.
shutdown_asap
=
0
;
server
.
cache_flush_delay
=
0
;
server
.
cache_flush_delay
=
0
;
server
.
cluster_enabled
=
0
;
server
.
cluster_enabled
=
0
;
...
...
src/redis.h
View file @
7c0e1b53
...
@@ -71,10 +71,12 @@
...
@@ -71,10 +71,12 @@
#define REDIS_ZSET 3
#define REDIS_ZSET 3
#define REDIS_HASH 4
#define REDIS_HASH 4
#define REDIS_VMPOINTER 8
#define REDIS_VMPOINTER 8
/* Object types only used for persistence in .rdb files */
/* Object types only used for persistence in .rdb files */
#define REDIS_HASH_ZIPMAP 9
#define REDIS_HASH_ZIPMAP 9
#define REDIS_LIST_ZIPLIST 10
#define REDIS_LIST_ZIPLIST 10
#define REDIS_SET_INTSET 11
#define REDIS_SET_INTSET 11
#define REDIS_ZSET_ZIPLIST 12
/* Objects encoding. Some kind of objects like Strings and Hashes can be
/* Objects encoding. Some kind of objects like Strings and Hashes can be
* internally represented in multiple ways. The 'encoding' field of the object
* internally represented in multiple ways. The 'encoding' field of the object
...
@@ -198,6 +200,8 @@
...
@@ -198,6 +200,8 @@
#define REDIS_LIST_MAX_ZIPLIST_ENTRIES 512
#define REDIS_LIST_MAX_ZIPLIST_ENTRIES 512
#define REDIS_LIST_MAX_ZIPLIST_VALUE 64
#define REDIS_LIST_MAX_ZIPLIST_VALUE 64
#define REDIS_SET_MAX_INTSET_ENTRIES 512
#define REDIS_SET_MAX_INTSET_ENTRIES 512
#define REDIS_ZSET_MAX_ZIPLIST_ENTRIES 128
#define REDIS_ZSET_MAX_ZIPLIST_VALUE 64
/* Sets operations codes */
/* Sets operations codes */
#define REDIS_OP_UNION 0
#define REDIS_OP_UNION 0
...
@@ -589,6 +593,8 @@ struct redisServer {
...
@@ -589,6 +593,8 @@ struct redisServer {
size_t
list_max_ziplist_entries
;
size_t
list_max_ziplist_entries
;
size_t
list_max_ziplist_value
;
size_t
list_max_ziplist_value
;
size_t
set_max_intset_entries
;
size_t
set_max_intset_entries
;
size_t
zset_max_ziplist_entries
;
size_t
zset_max_ziplist_value
;
time_t
unixtime
;
/* Unix time sampled every second. */
time_t
unixtime
;
/* Unix time sampled every second. */
/* Virtual memory I/O threads stuff */
/* Virtual memory I/O threads stuff */
/* An I/O thread process an element taken from the io_jobs queue and
/* An I/O thread process an element taken from the io_jobs queue and
...
@@ -853,6 +859,7 @@ robj *createSetObject(void);
...
@@ -853,6 +859,7 @@ robj *createSetObject(void);
robj
*
createIntsetObject
(
void
);
robj
*
createIntsetObject
(
void
);
robj
*
createHashObject
(
void
);
robj
*
createHashObject
(
void
);
robj
*
createZsetObject
(
void
);
robj
*
createZsetObject
(
void
);
robj
*
createZsetZiplistObject
(
void
);
int
getLongFromObjectOrReply
(
redisClient
*
c
,
robj
*
o
,
long
*
target
,
const
char
*
msg
);
int
getLongFromObjectOrReply
(
redisClient
*
c
,
robj
*
o
,
long
*
target
,
const
char
*
msg
);
int
checkType
(
redisClient
*
c
,
robj
*
o
,
int
type
);
int
checkType
(
redisClient
*
c
,
robj
*
o
,
int
type
);
int
getLongLongFromObjectOrReply
(
redisClient
*
c
,
robj
*
o
,
long
long
*
target
,
const
char
*
msg
);
int
getLongLongFromObjectOrReply
(
redisClient
*
c
,
robj
*
o
,
long
long
*
target
,
const
char
*
msg
);
...
@@ -916,6 +923,12 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal);
...
@@ -916,6 +923,12 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal);
zskiplist
*
zslCreate
(
void
);
zskiplist
*
zslCreate
(
void
);
void
zslFree
(
zskiplist
*
zsl
);
void
zslFree
(
zskiplist
*
zsl
);
zskiplistNode
*
zslInsert
(
zskiplist
*
zsl
,
double
score
,
robj
*
obj
);
zskiplistNode
*
zslInsert
(
zskiplist
*
zsl
,
double
score
,
robj
*
obj
);
unsigned
char
*
zzlInsert
(
unsigned
char
*
zl
,
robj
*
ele
,
double
score
);
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
);
unsigned
int
zsetLength
(
robj
*
zobj
);
void
zsetConvert
(
robj
*
zobj
,
int
encoding
);
/* Core functions */
/* Core functions */
void
freeMemoryIfNeeded
(
void
);
void
freeMemoryIfNeeded
(
void
);
...
@@ -1009,6 +1022,8 @@ int stringmatchlen(const char *pattern, int patternLen,
...
@@ -1009,6 +1022,8 @@ int stringmatchlen(const char *pattern, int patternLen,
int
stringmatch
(
const
char
*
pattern
,
const
char
*
string
,
int
nocase
);
int
stringmatch
(
const
char
*
pattern
,
const
char
*
string
,
int
nocase
);
long
long
memtoll
(
const
char
*
p
,
int
*
err
);
long
long
memtoll
(
const
char
*
p
,
int
*
err
);
int
ll2string
(
char
*
s
,
size_t
len
,
long
long
value
);
int
ll2string
(
char
*
s
,
size_t
len
,
long
long
value
);
int
string2ll
(
char
*
s
,
size_t
len
,
long
long
*
value
);
int
d2string
(
char
*
s
,
size_t
len
,
double
value
);
int
isStringRepresentableAsLong
(
sds
s
,
long
*
longval
);
int
isStringRepresentableAsLong
(
sds
s
,
long
*
longval
);
int
isStringRepresentableAsLongLong
(
sds
s
,
long
long
*
longval
);
int
isStringRepresentableAsLongLong
(
sds
s
,
long
long
*
longval
);
int
isObjectRepresentableAsLongLong
(
robj
*
o
,
long
long
*
llongval
);
int
isObjectRepresentableAsLongLong
(
robj
*
o
,
long
long
*
llongval
);
...
...
src/sort.c
View file @
7c0e1b53
...
@@ -199,6 +199,9 @@ void sortCommand(redisClient *c) {
...
@@ -199,6 +199,9 @@ void sortCommand(redisClient *c) {
j
++
;
j
++
;
}
}
/* Destructively convert encoded sorted sets for SORT. */
if
(
sortval
->
type
==
REDIS_ZSET
)
zsetConvert
(
sortval
,
REDIS_ENCODING_SKIPLIST
);
/* Load the sorting vector with all the objects to sort */
/* Load the sorting vector with all the objects to sort */
switch
(
sortval
->
type
)
{
switch
(
sortval
->
type
)
{
case
REDIS_LIST
:
vectorlen
=
listTypeLength
(
sortval
);
break
;
case
REDIS_LIST
:
vectorlen
=
listTypeLength
(
sortval
);
break
;
...
...
src/t_zset.c
View file @
7c0e1b53
This diff is collapsed.
Click to expand it.
src/util.c
View file @
7c0e1b53
#include "redis.h"
#include "redis.h"
#include <ctype.h>
#include <ctype.h>
#include <limits.h>
#include <limits.h>
#include <math.h>
/* Glob-style pattern matching. */
/* Glob-style pattern matching. */
int
stringmatchlen
(
const
char
*
pattern
,
int
patternLen
,
int
stringmatchlen
(
const
char
*
pattern
,
int
patternLen
,
...
@@ -200,6 +201,102 @@ int ll2string(char *s, size_t len, long long value) {
...
@@ -200,6 +201,102 @@ int ll2string(char *s, size_t len, long long value) {
return
l
;
return
l
;
}
}
/* Convert a string into a long long. Returns 1 if the string could be parsed
* into a (non-overflowing) long long, 0 otherwise. The value will be set to
* the parsed value when appropriate. */
int
string2ll
(
char
*
s
,
size_t
slen
,
long
long
*
value
)
{
char
*
p
=
s
;
size_t
plen
=
0
;
int
negative
=
0
;
unsigned
long
long
v
;
if
(
plen
==
slen
)
return
0
;
if
(
p
[
0
]
==
'-'
)
{
negative
=
1
;
p
++
;
plen
++
;
/* Abort on only a negative sign. */
if
(
plen
==
slen
)
return
0
;
}
/* First digit should be 1-9. */
if
(
p
[
0
]
>=
'1'
&&
p
[
0
]
<=
'9'
)
{
v
=
p
[
0
]
-
'0'
;
p
++
;
plen
++
;
}
else
{
return
0
;
}
while
(
plen
<
slen
&&
p
[
0
]
>=
'0'
&&
p
[
0
]
<=
'9'
)
{
if
(
v
>
(
ULLONG_MAX
/
10
))
/* Overflow. */
return
0
;
v
*=
10
;
if
(
v
>
(
ULLONG_MAX
-
(
p
[
0
]
-
'0'
)))
/* Overflow. */
return
0
;
v
+=
p
[
0
]
-
'0'
;
p
++
;
plen
++
;
}
/* Return if not all bytes were used. */
if
(
plen
<
slen
)
return
0
;
if
(
negative
)
{
if
(
v
>
(
-
(
unsigned
long
long
)
LLONG_MIN
))
/* Overflow. */
return
0
;
if
(
value
!=
NULL
)
*
value
=
-
v
;
}
else
{
if
(
v
>
LLONG_MAX
)
/* Overflow. */
return
0
;
if
(
value
!=
NULL
)
*
value
=
v
;
}
return
1
;
}
/* Convert a double to a string representation. Returns the number of bytes
* required. The representation should always be parsable by stdtod(3). */
int
d2string
(
char
*
buf
,
size_t
len
,
double
value
)
{
if
(
isnan
(
value
))
{
len
=
snprintf
(
buf
,
len
,
"nan"
);
}
else
if
(
isinf
(
value
))
{
if
(
value
<
0
)
len
=
snprintf
(
buf
,
len
,
"-inf"
);
else
len
=
snprintf
(
buf
,
len
,
"inf"
);
}
else
if
(
value
==
0
)
{
/* See: http://en.wikipedia.org/wiki/Signed_zero, "Comparisons". */
if
(
1
.
0
/
value
<
0
)
len
=
snprintf
(
buf
,
len
,
"-0"
);
else
len
=
snprintf
(
buf
,
len
,
"0"
);
}
else
{
#if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
/* Check if the float is in a safe range to be casted into a
* long long. We are assuming that long long is 64 bit here.
* Also we are assuming that there are no implementations around where
* double has precision < 52 bit.
*
* Under this assumptions we test if a double is inside an interval
* where casting to long long is safe. Then using two castings we
* make sure the decimal part is zero. If all this is true we use
* integer printing function that is much faster. */
double
min
=
-
4503599627370495
;
/* (2^52)-1 */
double
max
=
4503599627370496
;
/* -(2^52) */
if
(
val
>
min
&&
val
<
max
&&
value
==
((
double
)((
long
long
)
value
)))
len
=
ll2string
(
buf
,
len
,(
long
long
)
value
);
else
#endif
len
=
snprintf
(
buf
,
len
,
"%.17g"
,
value
);
}
return
len
;
}
/* Check if the sds string 's' can be represented by a long long
/* Check if the sds string 's' can be represented by a long long
* (that is, is a number that fits into long without any other space or
* (that is, is a number that fits into long without any other space or
* character before or after the digits, so that converting this number
* character before or after the digits, so that converting this number
...
...
src/ziplist.c
View file @
7c0e1b53
...
@@ -385,8 +385,8 @@ static unsigned char *ziplistResize(unsigned char *zl, unsigned int len) {
...
@@ -385,8 +385,8 @@ static unsigned char *ziplistResize(unsigned char *zl, unsigned int len) {
* The pointer "p" points to the first entry that does NOT need to be
* The pointer "p" points to the first entry that does NOT need to be
* updated, i.e. consecutive fields MAY need an update. */
* updated, i.e. consecutive fields MAY need an update. */
static
unsigned
char
*
__ziplistCascadeUpdate
(
unsigned
char
*
zl
,
unsigned
char
*
p
)
{
static
unsigned
char
*
__ziplistCascadeUpdate
(
unsigned
char
*
zl
,
unsigned
char
*
p
)
{
unsigned
in
t
curlen
=
ZIPLIST_BYTES
(
zl
),
rawlen
,
rawlensize
;
size_
t
curlen
=
ZIPLIST_BYTES
(
zl
),
rawlen
,
rawlensize
;
unsigned
in
t
offset
,
noffset
,
extra
;
size_
t
offset
,
noffset
,
extra
;
unsigned
char
*
np
;
unsigned
char
*
np
;
zlentry
cur
,
next
;
zlentry
cur
,
next
;
...
@@ -441,7 +441,8 @@ static unsigned char *__ziplistCascadeUpdate(unsigned char *zl, unsigned char *p
...
@@ -441,7 +441,8 @@ static unsigned char *__ziplistCascadeUpdate(unsigned char *zl, unsigned char *p
/* Delete "num" entries, starting at "p". Returns pointer to the ziplist. */
/* Delete "num" entries, starting at "p". Returns pointer to the ziplist. */
static
unsigned
char
*
__ziplistDelete
(
unsigned
char
*
zl
,
unsigned
char
*
p
,
unsigned
int
num
)
{
static
unsigned
char
*
__ziplistDelete
(
unsigned
char
*
zl
,
unsigned
char
*
p
,
unsigned
int
num
)
{
unsigned
int
i
,
totlen
,
deleted
=
0
;
unsigned
int
i
,
totlen
,
deleted
=
0
;
int
offset
,
nextdiff
=
0
;
size_t
offset
;
int
nextdiff
=
0
;
zlentry
first
,
tail
;
zlentry
first
,
tail
;
first
=
zipEntry
(
p
);
first
=
zipEntry
(
p
);
...
@@ -493,8 +494,9 @@ static unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, unsig
...
@@ -493,8 +494,9 @@ static unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, unsig
/* Insert item at "p". */
/* Insert item at "p". */
static
unsigned
char
*
__ziplistInsert
(
unsigned
char
*
zl
,
unsigned
char
*
p
,
unsigned
char
*
s
,
unsigned
int
slen
)
{
static
unsigned
char
*
__ziplistInsert
(
unsigned
char
*
zl
,
unsigned
char
*
p
,
unsigned
char
*
s
,
unsigned
int
slen
)
{
unsigned
int
curlen
=
ZIPLIST_BYTES
(
zl
),
reqlen
,
prevlen
=
0
;
size_t
curlen
=
ZIPLIST_BYTES
(
zl
),
reqlen
,
prevlen
=
0
;
unsigned
int
offset
,
nextdiff
=
0
;
size_t
offset
;
int
nextdiff
=
0
;
unsigned
char
encoding
=
0
;
unsigned
char
encoding
=
0
;
long
long
value
;
long
long
value
;
zlentry
entry
,
tail
;
zlentry
entry
,
tail
;
...
@@ -678,7 +680,7 @@ unsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char
...
@@ -678,7 +680,7 @@ unsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char
* Also update *p in place, to be able to iterate over the
* Also update *p in place, to be able to iterate over the
* ziplist, while deleting entries. */
* ziplist, while deleting entries. */
unsigned
char
*
ziplistDelete
(
unsigned
char
*
zl
,
unsigned
char
**
p
)
{
unsigned
char
*
ziplistDelete
(
unsigned
char
*
zl
,
unsigned
char
**
p
)
{
unsigned
in
t
offset
=
*
p
-
zl
;
size_
t
offset
=
*
p
-
zl
;
zl
=
__ziplistDelete
(
zl
,
*
p
,
1
);
zl
=
__ziplistDelete
(
zl
,
*
p
,
1
);
/* Store pointer to current element in p, because ziplistDelete will
/* Store pointer to current element in p, because ziplistDelete will
...
...
tests/unit/type/zset.tcl
View file @
7c0e1b53
This diff is collapsed.
Click to expand it.
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