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
"deps/hiredis/examples/example-libevent-ssl.c" did not exist on "3ddb6ffa34740b877c759e9f0bd422f33424cd3b"
Commit
e9400e8e
authored
Dec 07, 2018
by
antirez
Browse files
DEBUG DIGEST refactoring: extract function to digest a value.
parent
0006c989
Changes
1
Show 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) {
digest
[
j
]
^=
hash
[
j
];
}
void xorObjectDigest(unsigned char *digest, robj *o) {
void
xor
String
ObjectDigest
(
unsigned
char
*
digest
,
robj
*
o
)
{
o
=
getDecodedObject
(
o
);
xorDigest
(
digest
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
decrRefCount
(
o
);
...
...
@@ -104,66 +104,35 @@ void mixDigest(unsigned char *digest, void *ptr, size_t len) {
SHA1Final
(
digest
,
&
ctx
);
}
void mixObjectDigest(unsigned char *digest, robj *o) {
void
mix
String
ObjectDigest
(
unsigned
char
*
digest
,
robj
*
o
)
{
o
=
getDecodedObject
(
o
);
mixDigest
(
digest
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
decrRefCount
(
o
);
}
/* Compute the dataset digest. Since keys, sets elements, hashes elements
* 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
* the result. For list instead we use a feedback entering the output digest
* as input in order to ensure that a different ordered list will result in
* a different digest. */
void computeDatasetDigest(unsigned char *final) {
unsigned char digest[20];
char buf[128];
dictIterator *di = NULL;
dictEntry *de;
int j;
uint32_t aux;
memset(final,0,20); /* Start with a clean result */
for (j = 0; j < server.dbnum; j++) {
redisDb *db = server.db+j;
if (dictSize(db->dict) == 0) continue;
di = dictGetSafeIterator(db->dict);
/* hash the DB id, so the same dataset moved in a different
* DB will lead to a different digest */
aux = htonl(j);
mixDigest(final,&aux,sizeof(aux));
/* Iterate this DB writing every entry */
while((de = dictNext(di)) != NULL) {
sds key;
robj *keyobj, *o;
long long expiretime;
memset(digest,0,20); /* This key-val digest */
key = dictGetKey(de);
keyobj = createStringObject(key,sdslen(key));
mixDigest(digest,key,sdslen(key));
o = dictGetVal(de);
aux = htonl(o->type);
/* 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
));
expiretime = getExpire(db,keyobj);
long
long
expiretime
=
getExpire
(
db
,
keyobj
);
char
buf
[
128
];
/* Save the key and associated value */
if
(
o
->
type
==
OBJ_STRING
)
{
mixObjectDigest(digest,o);
mix
String
ObjectDigest
(
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
);
mix
ObjectDigest(digest,eleobj);
mixString
ObjectDigest
(
digest
,
eleobj
);
decrRefCount
(
eleobj
);
}
listTypeReleaseIterator
(
li
);
...
...
@@ -278,6 +247,48 @@ void computeDatasetDigest(unsigned char *final) {
}
/* 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
* 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
* the result. For list instead we use a feedback entering the output digest
* as input in order to ensure that a different ordered list will result in
* a different digest. */
void
computeDatasetDigest
(
unsigned
char
*
final
)
{
unsigned
char
digest
[
20
];
dictIterator
*
di
=
NULL
;
dictEntry
*
de
;
int
j
;
uint32_t
aux
;
memset
(
final
,
0
,
20
);
/* Start with a clean result */
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
redisDb
*
db
=
server
.
db
+
j
;
if
(
dictSize
(
db
->
dict
)
==
0
)
continue
;
di
=
dictGetSafeIterator
(
db
->
dict
);
/* hash the DB id, so the same dataset moved in a different
* DB will lead to a different digest */
aux
=
htonl
(
j
);
mixDigest
(
final
,
&
aux
,
sizeof
(
aux
));
/* Iterate this DB writing every entry */
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
sds
key
;
robj
*
keyobj
,
*
o
;
memset
(
digest
,
0
,
20
);
/* This key-val digest */
key
=
dictGetKey
(
de
);
keyobj
=
createStringObject
(
key
,
sdslen
(
key
));
mixDigest
(
digest
,
key
,
sdslen
(
key
));
o
=
dictGetVal
(
de
);
xorObjectDigest
(
db
,
keyobj
,
digest
,
o
);
/* We can finally xor the key-val digest to the final digest */
xorDigest
(
final
,
digest
,
20
);
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