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
51ffd062
Commit
51ffd062
authored
Jul 06, 2017
by
antirez
Browse files
Modules: DEBUG DIGEST interface.
parent
f9fac7f7
Changes
5
Show whitespace changes
Inline
Side-by-side
src/debug.c
View file @
51ffd062
...
...
@@ -239,6 +239,15 @@ void computeDatasetDigest(unsigned char *final) {
xorDigest
(
digest
,
eledigest
,
20
);
}
hashTypeReleaseIterator
(
hi
);
}
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"
);
}
...
...
src/module.c
View file @
51ffd062
...
...
@@ -3057,6 +3057,66 @@ loaderr:
return
0
;
/* Never reached. */
}
/* --------------------------------------------------------------------------
* Key digest API (DEBUG DIGEST interface for modules types)
* -------------------------------------------------------------------------- */
/* Add a new element to the digest. This function can be called multiple times
* one element after the other, for all the elements that constitute a given
* data structure. The function call must be followed by the call to
* `RedisModule_DigestEndSequence` eventually, when all the elements that are
* always in a given order are added. See the Redis Modules data types
* documentation for more info. However this is a quick example that uses Redis
* data types as an example.
*
* To add a sequence of unordered elements (for example in the case of a Redis
* Set), the pattern to use is:
*
* foreach element {
* AddElement(element);
* EndSequence();
* }
*
* Because Sets are not ordered, so every element added has a position that
* does not depend from the other. However if instead our elements are
* ordered in pairs, like field-value pairs of an Hash, then one should
* use:
*
* foreach key,value {
* AddElement(key);
* AddElement(value);
* EndSquence();
* }
*
* Because the key and value will be always in the above order, while instead
* the single key-value pairs, can appear in any position into a Redis hash.
*
* A list of ordered elements would be implemented with:
*
* foreach element {
* AddElement(element);
* }
* EndSequence();
*
*/
void
RM_DigestAddStringBuffer
(
RedisModuleDigest
*
md
,
unsigned
char
*
ele
,
size_t
len
)
{
mixDigest
(
md
->
o
,
ele
,
len
);
}
/* Like `RedisModule_DigestAddStringBuffer()` but takes a long long as input
* that gets converted into a string before adding it to the digest. */
void
RM_DigestAddLongLong
(
RedisModuleDigest
*
md
,
long
long
ll
)
{
char
buf
[
LONG_STR_SIZE
];
size_t
len
=
ll2string
(
buf
,
sizeof
(
buf
),
ll
);
mixDigest
(
md
->
o
,
buf
,
len
);
}
/* See the doucmnetation for `RedisModule_DigestAddElement()`. */
void
RM_DigestEndSequence
(
RedisModuleDigest
*
md
)
{
xorDigest
(
md
->
x
,
md
->
o
,
sizeof
(
md
->
o
));
memset
(
md
->
o
,
0
,
sizeof
(
md
->
o
));
}
/* --------------------------------------------------------------------------
* AOF API for modules data types
* -------------------------------------------------------------------------- */
...
...
@@ -3818,4 +3878,7 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API
(
FreeThreadSafeContext
);
REGISTER_API
(
ThreadSafeContextLock
);
REGISTER_API
(
ThreadSafeContextUnlock
);
REGISTER_API
(
DigestAddStringBuffer
);
REGISTER_API
(
DigestAddLongLong
);
REGISTER_API
(
DigestEndSequence
);
}
src/modules/hellotype.c
View file @
51ffd062
...
...
@@ -238,6 +238,16 @@ void HelloTypeFree(void *value) {
HelloTypeReleaseObject
(
value
);
}
void
HelloTypeDigest
(
RedisModuleDigest
*
md
,
void
*
value
)
{
struct
HelloTypeObject
*
hto
=
value
;
struct
HelloTypeNode
*
node
=
hto
->
head
;
while
(
node
)
{
RedisModule_DigestAddLongLong
(
md
,
node
->
value
);
node
=
node
->
next
;
}
RedisModule_DigestEndSequence
(
md
);
}
/* This function must be present on each Redis module. It is used in order to
* register the commands into the Redis server. */
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
...
...
@@ -253,7 +263,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
.
rdb_save
=
HelloTypeRdbSave
,
.
aof_rewrite
=
HelloTypeAofRewrite
,
.
mem_usage
=
HelloTypeMemUsage
,
.
free
=
HelloTypeFree
.
free
=
HelloTypeFree
,
.
digest
=
HelloTypeDigest
};
HelloType
=
RedisModule_CreateDataType
(
ctx
,
"hellotype"
,
0
,
&
tm
);
...
...
src/redismodule.h
View file @
51ffd062
...
...
@@ -218,6 +218,9 @@ RedisModuleCtx *REDISMODULE_API_FUNC(RedisModule_GetThreadSafeContext)(RedisModu
void
REDISMODULE_API_FUNC
(
RedisModule_FreeThreadSafeContext
)(
RedisModuleCtx
*
ctx
);
void
REDISMODULE_API_FUNC
(
RedisModule_ThreadSafeContextLock
)(
RedisModuleCtx
*
ctx
);
void
REDISMODULE_API_FUNC
(
RedisModule_ThreadSafeContextUnlock
)(
RedisModuleCtx
*
ctx
);
void
REDISMODULE_API_FUNC
(
RedisModule_DigestAddStringBuffer
)(
RedisModuleDigest
*
md
,
unsigned
char
*
ele
,
size_t
len
);
void
REDISMODULE_API_FUNC
(
RedisModule_DigestAddLongLong
)(
RedisModuleDigest
*
md
,
long
long
ele
);
void
REDISMODULE_API_FUNC
(
RedisModule_DigestEndSequence
)(
RedisModuleDigest
*
md
);
/* This is included inline inside each Redis module. */
static
int
RedisModule_Init
(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
int
ver
,
int
apiver
)
__attribute__
((
unused
));
...
...
@@ -330,6 +333,9 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
FreeThreadSafeContext
);
REDISMODULE_GET_API
(
ThreadSafeContextLock
);
REDISMODULE_GET_API
(
ThreadSafeContextUnlock
);
REDISMODULE_GET_API
(
DigestAddStringBuffer
);
REDISMODULE_GET_API
(
DigestAddLongLong
);
REDISMODULE_GET_API
(
DigestEndSequence
);
RedisModule_SetModuleAttribs
(
ctx
,
name
,
ver
,
apiver
);
return
REDISMODULE_OK
;
...
...
src/server.h
View file @
51ffd062
...
...
@@ -546,6 +546,22 @@ typedef struct RedisModuleIO {
iovar.ctx = NULL; \
} while(0);
/* This is a structure used to export DEBUG DIGEST capabilities to Redis
* modules. We want to capture both the ordered and unordered elements of
* a data structure, so that a digest can be created in a way that correctly
* reflects the values. See the DEBUG DIGEST command implementation for more
* background. */
typedef
struct
RedisModuleDigest
{
unsigned
char
o
[
20
];
/* Ordered elements. */
unsigned
char
x
[
20
];
/* Xored elements. */
}
RedisModuleDigest
;
/* Just start with a digest composed of all zero bytes. */
#define moduleInitDigestContext(mdvar) do { \
memset(mdvar.o,0,sizeof(mdvar.o)); \
memset(mdvar.x,0,sizeof(mdvar.x)); \
} while(0);
/* Objects encoding. Some kind of objects like Strings and Hashes can be
* internally represented in multiple ways. The 'encoding' field of the object
* is set to one of this fields for this object. */
...
...
@@ -1993,6 +2009,8 @@ void disableWatchdog(void);
void
watchdogScheduleSignal
(
int
period
);
void
serverLogHexDump
(
int
level
,
char
*
descr
,
void
*
value
,
size_t
len
);
int
memtest_preserving_test
(
unsigned
long
*
m
,
size_t
bytes
,
int
passes
);
void
mixDigest
(
unsigned
char
*
digest
,
void
*
ptr
,
size_t
len
);
void
xorDigest
(
unsigned
char
*
digest
,
void
*
ptr
,
size_t
len
);
#define redisDebug(fmt, ...) \
printf("DEBUG %s:%d > " fmt "\n", __FILE__, __LINE__, __VA_ARGS__)
...
...
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