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
e9400e8e
Commit
e9400e8e
authored
Dec 07, 2018
by
antirez
Browse files
DEBUG DIGEST refactoring: extract function to digest a value.
parent
0006c989
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/debug.c
View file @
e9400e8e
...
@@ -74,7 +74,7 @@ void xorDigest(unsigned char *digest, void *ptr, size_t len) {
...
@@ -74,7 +74,7 @@ void xorDigest(unsigned char *digest, void *ptr, size_t len) {
digest
[
j
]
^=
hash
[
j
];
digest
[
j
]
^=
hash
[
j
];
}
}
void
xorObjectDigest
(
unsigned
char
*
digest
,
robj
*
o
)
{
void
xor
String
ObjectDigest
(
unsigned
char
*
digest
,
robj
*
o
)
{
o
=
getDecodedObject
(
o
);
o
=
getDecodedObject
(
o
);
xorDigest
(
digest
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
xorDigest
(
digest
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
decrRefCount
(
o
);
decrRefCount
(
o
);
...
@@ -104,12 +104,151 @@ void mixDigest(unsigned char *digest, void *ptr, size_t len) {
...
@@ -104,12 +104,151 @@ void mixDigest(unsigned char *digest, void *ptr, size_t len) {
SHA1Final
(
digest
,
&
ctx
);
SHA1Final
(
digest
,
&
ctx
);
}
}
void
mixObjectDigest
(
unsigned
char
*
digest
,
robj
*
o
)
{
void
mix
String
ObjectDigest
(
unsigned
char
*
digest
,
robj
*
o
)
{
o
=
getDecodedObject
(
o
);
o
=
getDecodedObject
(
o
);
mixDigest
(
digest
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
mixDigest
(
digest
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
decrRefCount
(
o
);
decrRefCount
(
o
);
}
}
/* This function computes the digest of a data structure stored in the
* object 'o'. It is the core of the DEBUG DIGEST command: when taking the
* digest of a whole dataset, we take the digest of the key and the value
* pair, and xor all those together.
*
* Note that this function does not reset the initial 'digest' passed, it
* will continue mixing this object digest to anything that was already
* present. */
void
xorObjectDigest
(
redisDb
*
db
,
robj
*
keyobj
,
unsigned
char
*
digest
,
robj
*
o
)
{
uint32_t
aux
=
htonl
(
o
->
type
);
mixDigest
(
digest
,
&
aux
,
sizeof
(
aux
));
long
long
expiretime
=
getExpire
(
db
,
keyobj
);
char
buf
[
128
];
/* Save the key and associated value */
if
(
o
->
type
==
OBJ_STRING
)
{
mixStringObjectDigest
(
digest
,
o
);
}
else
if
(
o
->
type
==
OBJ_LIST
)
{
listTypeIterator
*
li
=
listTypeInitIterator
(
o
,
0
,
LIST_TAIL
);
listTypeEntry
entry
;
while
(
listTypeNext
(
li
,
&
entry
))
{
robj
*
eleobj
=
listTypeGet
(
&
entry
);
mixStringObjectDigest
(
digest
,
eleobj
);
decrRefCount
(
eleobj
);
}
listTypeReleaseIterator
(
li
);
}
else
if
(
o
->
type
==
OBJ_SET
)
{
setTypeIterator
*
si
=
setTypeInitIterator
(
o
);
sds
sdsele
;
while
((
sdsele
=
setTypeNextObject
(
si
))
!=
NULL
)
{
xorDigest
(
digest
,
sdsele
,
sdslen
(
sdsele
));
sdsfree
(
sdsele
);
}
setTypeReleaseIterator
(
si
);
}
else
if
(
o
->
type
==
OBJ_ZSET
)
{
unsigned
char
eledigest
[
20
];
if
(
o
->
encoding
==
OBJ_ENCODING_ZIPLIST
)
{
unsigned
char
*
zl
=
o
->
ptr
;
unsigned
char
*
eptr
,
*
sptr
;
unsigned
char
*
vstr
;
unsigned
int
vlen
;
long
long
vll
;
double
score
;
eptr
=
ziplistIndex
(
zl
,
0
);
serverAssert
(
eptr
!=
NULL
);
sptr
=
ziplistNext
(
zl
,
eptr
);
serverAssert
(
sptr
!=
NULL
);
while
(
eptr
!=
NULL
)
{
serverAssert
(
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
==
OBJ_ENCODING_SKIPLIST
)
{
zset
*
zs
=
o
->
ptr
;
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictEntry
*
de
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
sds
sdsele
=
dictGetKey
(
de
);
double
*
score
=
dictGetVal
(
de
);
snprintf
(
buf
,
sizeof
(
buf
),
"%.17g"
,
*
score
);
memset
(
eledigest
,
0
,
20
);
mixDigest
(
eledigest
,
sdsele
,
sdslen
(
sdsele
));
mixDigest
(
eledigest
,
buf
,
strlen
(
buf
));
xorDigest
(
digest
,
eledigest
,
20
);
}
dictReleaseIterator
(
di
);
}
else
{
serverPanic
(
"Unknown sorted set encoding"
);
}
}
else
if
(
o
->
type
==
OBJ_HASH
)
{
hashTypeIterator
*
hi
=
hashTypeInitIterator
(
o
);
while
(
hashTypeNext
(
hi
)
!=
C_ERR
)
{
unsigned
char
eledigest
[
20
];
sds
sdsele
;
memset
(
eledigest
,
0
,
20
);
sdsele
=
hashTypeCurrentObjectNewSds
(
hi
,
OBJ_HASH_KEY
);
mixDigest
(
eledigest
,
sdsele
,
sdslen
(
sdsele
));
sdsfree
(
sdsele
);
sdsele
=
hashTypeCurrentObjectNewSds
(
hi
,
OBJ_HASH_VALUE
);
mixDigest
(
eledigest
,
sdsele
,
sdslen
(
sdsele
));
sdsfree
(
sdsele
);
xorDigest
(
digest
,
eledigest
,
20
);
}
hashTypeReleaseIterator
(
hi
);
}
else
if
(
o
->
type
==
OBJ_STREAM
)
{
streamIterator
si
;
streamIteratorStart
(
&
si
,
o
->
ptr
,
NULL
,
NULL
,
0
);
streamID
id
;
int64_t
numfields
;
while
(
streamIteratorGetID
(
&
si
,
&
id
,
&
numfields
))
{
sds
itemid
=
sdscatfmt
(
sdsempty
(),
"%U.%U"
,
id
.
ms
,
id
.
seq
);
mixDigest
(
digest
,
itemid
,
sdslen
(
itemid
));
sdsfree
(
itemid
);
while
(
numfields
--
)
{
unsigned
char
*
field
,
*
value
;
int64_t
field_len
,
value_len
;
streamIteratorGetField
(
&
si
,
&
field
,
&
value
,
&
field_len
,
&
value_len
);
mixDigest
(
digest
,
field
,
field_len
);
mixDigest
(
digest
,
value
,
value_len
);
}
}
streamIteratorStop
(
&
si
);
}
else
if
(
o
->
type
==
OBJ_MODULE
)
{
RedisModuleDigest
md
;
moduleValue
*
mv
=
o
->
ptr
;
moduleType
*
mt
=
mv
->
type
;
moduleInitDigestContext
(
md
);
if
(
mt
->
digest
)
{
mt
->
digest
(
&
md
,
mv
->
value
);
xorDigest
(
digest
,
md
.
x
,
sizeof
(
md
.
x
));
}
}
else
{
serverPanic
(
"Unknown object type"
);
}
/* If the key has an expire, add it to the mix */
if
(
expiretime
!=
-
1
)
xorDigest
(
digest
,
"!!expire!!"
,
10
);
}
/* Compute the dataset digest. Since keys, sets elements, hashes elements
/* Compute the dataset digest. Since keys, sets elements, hashes elements
* are not ordered, we use a trick: every aggregate digest is the xor
* are not ordered, we use a trick: every aggregate digest is the xor
* of the digests of their elements. This way the order will not change
* of the digests of their elements. This way the order will not change
...
@@ -118,7 +257,6 @@ void mixObjectDigest(unsigned char *digest, robj *o) {
...
@@ -118,7 +257,6 @@ void mixObjectDigest(unsigned char *digest, robj *o) {
* a different digest. */
* a different digest. */
void
computeDatasetDigest
(
unsigned
char
*
final
)
{
void
computeDatasetDigest
(
unsigned
char
*
final
)
{
unsigned
char
digest
[
20
];
unsigned
char
digest
[
20
];
char
buf
[
128
];
dictIterator
*
di
=
NULL
;
dictIterator
*
di
=
NULL
;
dictEntry
*
de
;
dictEntry
*
de
;
int
j
;
int
j
;
...
@@ -141,7 +279,6 @@ void computeDatasetDigest(unsigned char *final) {
...
@@ -141,7 +279,6 @@ void computeDatasetDigest(unsigned char *final) {
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
sds
key
;
sds
key
;
robj
*
keyobj
,
*
o
;
robj
*
keyobj
,
*
o
;
long
long
expiretime
;
memset
(
digest
,
0
,
20
);
/* This key-val digest */
memset
(
digest
,
0
,
20
);
/* This key-val digest */
key
=
dictGetKey
(
de
);
key
=
dictGetKey
(
de
);
...
@@ -150,134 +287,8 @@ void computeDatasetDigest(unsigned char *final) {
...
@@ -150,134 +287,8 @@ void computeDatasetDigest(unsigned char *final) {
mixDigest
(
digest
,
key
,
sdslen
(
key
));
mixDigest
(
digest
,
key
,
sdslen
(
key
));
o
=
dictGetVal
(
de
);
o
=
dictGetVal
(
de
);
xorObjectDigest
(
db
,
keyobj
,
digest
,
o
);
aux
=
htonl
(
o
->
type
);
mixDigest
(
digest
,
&
aux
,
sizeof
(
aux
));
expiretime
=
getExpire
(
db
,
keyobj
);
/* Save the key and associated value */
if
(
o
->
type
==
OBJ_STRING
)
{
mixObjectDigest
(
digest
,
o
);
}
else
if
(
o
->
type
==
OBJ_LIST
)
{
listTypeIterator
*
li
=
listTypeInitIterator
(
o
,
0
,
LIST_TAIL
);
listTypeEntry
entry
;
while
(
listTypeNext
(
li
,
&
entry
))
{
robj
*
eleobj
=
listTypeGet
(
&
entry
);
mixObjectDigest
(
digest
,
eleobj
);
decrRefCount
(
eleobj
);
}
listTypeReleaseIterator
(
li
);
}
else
if
(
o
->
type
==
OBJ_SET
)
{
setTypeIterator
*
si
=
setTypeInitIterator
(
o
);
sds
sdsele
;
while
((
sdsele
=
setTypeNextObject
(
si
))
!=
NULL
)
{
xorDigest
(
digest
,
sdsele
,
sdslen
(
sdsele
));
sdsfree
(
sdsele
);
}
setTypeReleaseIterator
(
si
);
}
else
if
(
o
->
type
==
OBJ_ZSET
)
{
unsigned
char
eledigest
[
20
];
if
(
o
->
encoding
==
OBJ_ENCODING_ZIPLIST
)
{
unsigned
char
*
zl
=
o
->
ptr
;
unsigned
char
*
eptr
,
*
sptr
;
unsigned
char
*
vstr
;
unsigned
int
vlen
;
long
long
vll
;
double
score
;
eptr
=
ziplistIndex
(
zl
,
0
);
serverAssert
(
eptr
!=
NULL
);
sptr
=
ziplistNext
(
zl
,
eptr
);
serverAssert
(
sptr
!=
NULL
);
while
(
eptr
!=
NULL
)
{
serverAssert
(
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
==
OBJ_ENCODING_SKIPLIST
)
{
zset
*
zs
=
o
->
ptr
;
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictEntry
*
de
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
sds
sdsele
=
dictGetKey
(
de
);
double
*
score
=
dictGetVal
(
de
);
snprintf
(
buf
,
sizeof
(
buf
),
"%.17g"
,
*
score
);
memset
(
eledigest
,
0
,
20
);
mixDigest
(
eledigest
,
sdsele
,
sdslen
(
sdsele
));
mixDigest
(
eledigest
,
buf
,
strlen
(
buf
));
xorDigest
(
digest
,
eledigest
,
20
);
}
dictReleaseIterator
(
di
);
}
else
{
serverPanic
(
"Unknown sorted set encoding"
);
}
}
else
if
(
o
->
type
==
OBJ_HASH
)
{
hashTypeIterator
*
hi
=
hashTypeInitIterator
(
o
);
while
(
hashTypeNext
(
hi
)
!=
C_ERR
)
{
unsigned
char
eledigest
[
20
];
sds
sdsele
;
memset
(
eledigest
,
0
,
20
);
sdsele
=
hashTypeCurrentObjectNewSds
(
hi
,
OBJ_HASH_KEY
);
mixDigest
(
eledigest
,
sdsele
,
sdslen
(
sdsele
));
sdsfree
(
sdsele
);
sdsele
=
hashTypeCurrentObjectNewSds
(
hi
,
OBJ_HASH_VALUE
);
mixDigest
(
eledigest
,
sdsele
,
sdslen
(
sdsele
));
sdsfree
(
sdsele
);
xorDigest
(
digest
,
eledigest
,
20
);
}
hashTypeReleaseIterator
(
hi
);
}
else
if
(
o
->
type
==
OBJ_STREAM
)
{
streamIterator
si
;
streamIteratorStart
(
&
si
,
o
->
ptr
,
NULL
,
NULL
,
0
);
streamID
id
;
int64_t
numfields
;
while
(
streamIteratorGetID
(
&
si
,
&
id
,
&
numfields
))
{
sds
itemid
=
sdscatfmt
(
sdsempty
(),
"%U.%U"
,
id
.
ms
,
id
.
seq
);
mixDigest
(
digest
,
itemid
,
sdslen
(
itemid
));
sdsfree
(
itemid
);
while
(
numfields
--
)
{
unsigned
char
*
field
,
*
value
;
int64_t
field_len
,
value_len
;
streamIteratorGetField
(
&
si
,
&
field
,
&
value
,
&
field_len
,
&
value_len
);
mixDigest
(
digest
,
field
,
field_len
);
mixDigest
(
digest
,
value
,
value_len
);
}
}
streamIteratorStop
(
&
si
);
}
else
if
(
o
->
type
==
OBJ_MODULE
)
{
RedisModuleDigest
md
;
moduleValue
*
mv
=
o
->
ptr
;
moduleType
*
mt
=
mv
->
type
;
moduleInitDigestContext
(
md
);
if
(
mt
->
digest
)
{
mt
->
digest
(
&
md
,
mv
->
value
);
xorDigest
(
digest
,
md
.
x
,
sizeof
(
md
.
x
));
}
}
else
{
serverPanic
(
"Unknown object type"
);
}
/* If the key has an expire, add it to the mix */
if
(
expiretime
!=
-
1
)
xorDigest
(
digest
,
"!!expire!!"
,
10
);
/* We can finally xor the key-val digest to the final digest */
/* We can finally xor the key-val digest to the final digest */
xorDigest
(
final
,
digest
,
20
);
xorDigest
(
final
,
digest
,
20
);
decrRefCount
(
keyobj
);
decrRefCount
(
keyobj
);
...
...
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