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