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
1ee195d2
Commit
1ee195d2
authored
Oct 31, 2019
by
antirez
Browse files
Merge branch 'unstable' of github.com:/antirez/redis into unstable
parents
dd5feec5
764b420f
Changes
8
Hide whitespace changes
Inline
Side-by-side
.github/workflows/ci.yml
0 → 100644
View file @
1ee195d2
name
:
CI
on
:
[
push
,
pull_request
]
jobs
:
build-ubuntu
:
strategy
:
matrix
:
platform
:
[
ubuntu-latest
,
ubuntu-16.04
]
runs-on
:
${{ matrix.platform }}
steps
:
-
uses
:
actions/checkout@v1
-
name
:
make
run
:
make
-
name
:
test
run
:
|
sudo apt-get install tcl8.5
make test
build-macos-latest
:
strategy
:
matrix
:
platform
:
[
macos-latest
,
macOS-10.14
]
runs-on
:
${{ matrix.platform }}
steps
:
-
uses
:
actions/checkout@v1
-
name
:
make
run
:
make
runtest-moduleapi
View file @
1ee195d2
...
...
@@ -13,4 +13,12 @@ then
fi
make
-C
tests/modules
&&
\
$TCLSH
tests/test_helper.tcl
--single
unit/moduleapi/commandfilter
--single
unit/moduleapi/fork
--single
unit/moduleapi/testrdb
--single
unit/moduleapi/infotest
--single
unit/moduleapi/propagate
--single
unit/moduleapi/hooks
"
${
@
}
"
$TCLSH
tests/test_helper.tcl
\
--single
unit/moduleapi/commandfilter
\
--single
unit/moduleapi/fork
\
--single
unit/moduleapi/testrdb
\
--single
unit/moduleapi/infotest
\
--single
unit/moduleapi/propagate
\
--single
unit/moduleapi/hooks
\
--single
unit/moduleapi/misc
\
"
${
@
}
"
src/module.c
View file @
1ee195d2
...
...
@@ -327,6 +327,13 @@ static struct RedisModuleForkInfo {
#define REDISMODULE_ARGV_NO_AOF (1<<1)
#define REDISMODULE_ARGV_NO_REPLICAS (1<<2)
/* Determine whether Redis should signalModifiedKey implicitly.
* In case 'ctx' has no 'module' member (and therefore no module->options),
* we assume default behavior, that is, Redis signals.
* (see RM_GetThreadSafeContext) */
#define SHOULD_SIGNAL_MODIFIED_KEYS(ctx) \
ctx->module? !(ctx->module->options & REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED) : 1
/* Server events hooks data structures and defines: this modules API
* allow modules to subscribe to certain events in Redis, such as
* the start and end of an RDB or AOF save, the change of role in replication,
...
...
@@ -827,6 +834,7 @@ void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int api
module
->
filters
=
listCreate
();
module
->
in_call
=
0
;
module
->
in_hook
=
0
;
module
->
options
=
0
;
ctx
->
module
=
module
;
}
...
...
@@ -857,6 +865,12 @@ void RM_SetModuleOptions(RedisModuleCtx *ctx, int options) {
ctx
->
module
->
options
=
options
;
}
/* Signals that the key is modified from user's perspective (i.e. invalidate WATCH). */
int
RM_SignalModifiedKey
(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
keyname
)
{
signalModifiedKey
(
ctx
->
client
->
db
,
keyname
);
return
REDISMODULE_OK
;
}
/* --------------------------------------------------------------------------
* Automatic memory management for modules
* -------------------------------------------------------------------------- */
...
...
@@ -1848,7 +1862,9 @@ void *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
/* Close a key handle. */
void
RM_CloseKey
(
RedisModuleKey
*
key
)
{
if
(
key
==
NULL
)
return
;
if
(
key
->
mode
&
REDISMODULE_WRITE
)
signalModifiedKey
(
key
->
db
,
key
->
key
);
int
signal
=
SHOULD_SIGNAL_MODIFIED_KEYS
(
key
->
ctx
);
if
((
key
->
mode
&
REDISMODULE_WRITE
)
&&
signal
)
signalModifiedKey
(
key
->
db
,
key
->
key
);
/* TODO: if (key->iter) RM_KeyIteratorStop(kp); */
RM_ZsetRangeStop
(
key
);
decrRefCount
(
key
->
key
);
...
...
@@ -3072,7 +3088,10 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
/* We handle the above format error only when the client is setup so that
* we can free it normally. */
if
(
argv
==
NULL
)
goto
cleanup
;
if
(
argv
==
NULL
)
{
errno
=
EINVAL
;
goto
cleanup
;
}
/* Call command filters */
moduleCallCommandFilters
(
c
);
...
...
@@ -3864,6 +3883,11 @@ const RedisModuleString *RM_GetKeyNameFromIO(RedisModuleIO *io) {
return
io
->
key
;
}
/* Returns a RedisModuleString with the name of the key from RedisModuleKey */
const
RedisModuleString
*
RM_GetKeyNameFromModuleKey
(
RedisModuleKey
*
key
)
{
return
key
?
key
->
key
:
NULL
;
}
/* --------------------------------------------------------------------------
* Logging
* -------------------------------------------------------------------------- */
...
...
@@ -4537,6 +4561,20 @@ int RM_SubscribeToKeyspaceEvents(RedisModuleCtx *ctx, int types, RedisModuleNoti
return
REDISMODULE_OK
;
}
/* Get the configured bitmap of notify-keyspace-events (Could be used
* for additional filtering in RedisModuleNotificationFunc) */
int
RM_GetNotifyKeyspaceEvents
()
{
return
server
.
notify_keyspace_events
;
}
/* Expose notifyKeyspaceEvent to modules */
int
RM_NotifyKeyspaceEvent
(
RedisModuleCtx
*
ctx
,
int
type
,
const
char
*
event
,
RedisModuleString
*
key
)
{
if
(
!
ctx
||
!
ctx
->
client
)
return
REDISMODULE_ERR
;
notifyKeyspaceEvent
(
type
,
(
char
*
)
event
,
key
,
ctx
->
client
->
db
->
id
);
return
REDISMODULE_OK
;
}
/* Dispatcher for keyspace notifications to module subscriber functions.
* This gets called only if at least one module requested to be notified on
* keyspace notifications */
...
...
@@ -6618,6 +6656,7 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API
(
ModuleTypeGetValue
);
REGISTER_API
(
IsIOError
);
REGISTER_API
(
SetModuleOptions
);
REGISTER_API
(
SignalModifiedKey
);
REGISTER_API
(
SaveUnsigned
);
REGISTER_API
(
LoadUnsigned
);
REGISTER_API
(
SaveSigned
);
...
...
@@ -6640,6 +6679,7 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API
(
StringCompare
);
REGISTER_API
(
GetContextFromIO
);
REGISTER_API
(
GetKeyNameFromIO
);
REGISTER_API
(
GetKeyNameFromModuleKey
);
REGISTER_API
(
BlockClient
);
REGISTER_API
(
UnblockClient
);
REGISTER_API
(
IsBlockedReplyRequest
);
...
...
@@ -6654,6 +6694,8 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API
(
DigestAddStringBuffer
);
REGISTER_API
(
DigestAddLongLong
);
REGISTER_API
(
DigestEndSequence
);
REGISTER_API
(
NotifyKeyspaceEvent
);
REGISTER_API
(
GetNotifyKeyspaceEvents
);
REGISTER_API
(
SubscribeToKeyspaceEvents
);
REGISTER_API
(
RegisterClusterMessageReceiver
);
REGISTER_API
(
SendClusterMessage
);
...
...
src/redismodule.h
View file @
1ee195d2
...
...
@@ -106,6 +106,11 @@
/* There is currently some background process active. */
#define REDISMODULE_CTX_FLAGS_ACTIVE_CHILD (1<<18)
/* Keyspace changes notification classes. Every class is associated with a
* character for configuration purposes.
* NOTE: These have to be in sync with NOTIFY_* in server.h */
#define REDISMODULE_NOTIFY_KEYSPACE (1<<0)
/* K */
#define REDISMODULE_NOTIFY_KEYEVENT (1<<1)
/* E */
#define REDISMODULE_NOTIFY_GENERIC (1<<2)
/* g */
#define REDISMODULE_NOTIFY_STRING (1<<3)
/* $ */
#define REDISMODULE_NOTIFY_LIST (1<<4)
/* l */
...
...
@@ -161,6 +166,10 @@ typedef uint64_t RedisModuleTimerID;
/* Declare that the module can handle errors with RedisModule_SetModuleOptions. */
#define REDISMODULE_OPTIONS_HANDLE_IO_ERRORS (1<<0)
/* When set, Redis will not call RedisModule_SignalModifiedKey(), implicitly in
* RedisModule_CloseKey, and the module needs to do that when manually when keys
* are modified from the user's sperspective, to invalidate WATCH. */
#define REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED (1<<1)
/* Server events definitions. */
#define REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED 0
...
...
@@ -181,7 +190,7 @@ typedef struct RedisModuleEvent {
struct
RedisModuleCtx
;
typedef
void
(
*
RedisModuleEventCallback
)(
struct
RedisModuleCtx
*
ctx
,
RedisModuleEvent
eid
,
uint64_t
subevent
,
void
*
data
);
static
RedisModuleEvent
static
const
RedisModuleEvent
RedisModuleEvent_ReplicationRoleChanged
=
{
REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED
,
1
...
...
@@ -434,6 +443,7 @@ RedisModuleType *REDISMODULE_API_FUNC(RedisModule_ModuleTypeGetType)(RedisModule
void
*
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeGetValue
)(
RedisModuleKey
*
key
);
int
REDISMODULE_API_FUNC
(
RedisModule_IsIOError
)(
RedisModuleIO
*
io
);
void
REDISMODULE_API_FUNC
(
RedisModule_SetModuleOptions
)(
RedisModuleCtx
*
ctx
,
int
options
);
int
REDISMODULE_API_FUNC
(
RedisModule_SignalModifiedKey
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
keyname
);
void
REDISMODULE_API_FUNC
(
RedisModule_SaveUnsigned
)(
RedisModuleIO
*
io
,
uint64_t
value
);
uint64_t
REDISMODULE_API_FUNC
(
RedisModule_LoadUnsigned
)(
RedisModuleIO
*
io
);
void
REDISMODULE_API_FUNC
(
RedisModule_SaveSigned
)(
RedisModuleIO
*
io
,
int64_t
value
);
...
...
@@ -456,6 +466,7 @@ void REDISMODULE_API_FUNC(RedisModule_RetainString)(RedisModuleCtx *ctx, RedisMo
int
REDISMODULE_API_FUNC
(
RedisModule_StringCompare
)(
RedisModuleString
*
a
,
RedisModuleString
*
b
);
RedisModuleCtx
*
REDISMODULE_API_FUNC
(
RedisModule_GetContextFromIO
)(
RedisModuleIO
*
io
);
const
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_GetKeyNameFromIO
)(
RedisModuleIO
*
io
);
const
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_GetKeyNameFromModuleKey
)(
RedisModuleKey
*
key
);
long
long
REDISMODULE_API_FUNC
(
RedisModule_Milliseconds
)(
void
);
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
);
...
...
@@ -511,6 +522,8 @@ void REDISMODULE_API_FUNC(RedisModule_FreeThreadSafeContext)(RedisModuleCtx *ctx
void
REDISMODULE_API_FUNC
(
RedisModule_ThreadSafeContextLock
)(
RedisModuleCtx
*
ctx
);
void
REDISMODULE_API_FUNC
(
RedisModule_ThreadSafeContextUnlock
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_SubscribeToKeyspaceEvents
)(
RedisModuleCtx
*
ctx
,
int
types
,
RedisModuleNotificationFunc
cb
);
int
REDISMODULE_API_FUNC
(
RedisModule_NotifyKeyspaceEvent
)(
RedisModuleCtx
*
ctx
,
int
type
,
const
char
*
event
,
RedisModuleString
*
key
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetNotifyKeyspaceEvents
)();
int
REDISMODULE_API_FUNC
(
RedisModule_BlockedClientDisconnected
)(
RedisModuleCtx
*
ctx
);
void
REDISMODULE_API_FUNC
(
RedisModule_RegisterClusterMessageReceiver
)(
RedisModuleCtx
*
ctx
,
uint8_t
type
,
RedisModuleClusterMessageReceiver
callback
);
int
REDISMODULE_API_FUNC
(
RedisModule_SendClusterMessage
)(
RedisModuleCtx
*
ctx
,
char
*
target_id
,
uint8_t
type
,
unsigned
char
*
msg
,
uint32_t
len
);
...
...
@@ -632,6 +645,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
ModuleTypeGetValue
);
REDISMODULE_GET_API
(
IsIOError
);
REDISMODULE_GET_API
(
SetModuleOptions
);
REDISMODULE_GET_API
(
SignalModifiedKey
);
REDISMODULE_GET_API
(
SaveUnsigned
);
REDISMODULE_GET_API
(
LoadUnsigned
);
REDISMODULE_GET_API
(
SaveSigned
);
...
...
@@ -654,6 +668,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
StringCompare
);
REDISMODULE_GET_API
(
GetContextFromIO
);
REDISMODULE_GET_API
(
GetKeyNameFromIO
);
REDISMODULE_GET_API
(
GetKeyNameFromModuleKey
);
REDISMODULE_GET_API
(
Milliseconds
);
REDISMODULE_GET_API
(
DigestAddStringBuffer
);
REDISMODULE_GET_API
(
DigestAddLongLong
);
...
...
@@ -709,6 +724,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
AbortBlock
);
REDISMODULE_GET_API
(
SetDisconnectCallback
);
REDISMODULE_GET_API
(
SubscribeToKeyspaceEvents
);
REDISMODULE_GET_API
(
NotifyKeyspaceEvent
);
REDISMODULE_GET_API
(
GetNotifyKeyspaceEvents
);
REDISMODULE_GET_API
(
BlockedClientDisconnected
);
REDISMODULE_GET_API
(
RegisterClusterMessageReceiver
);
REDISMODULE_GET_API
(
SendClusterMessage
);
...
...
tests/modules/Makefile
View file @
1ee195d2
...
...
@@ -17,6 +17,7 @@ TEST_MODULES = \
fork.so
\
infotest.so
\
propagate.so
\
misc.so
\
hooks.so
.PHONY
:
all
...
...
tests/modules/fork.c
View file @
1ee195d2
#define REDISMODULE_EXPERIMENTAL_API
#include "redismodule.h"
/* define macros for having usleep */
#define _BSD_SOURCE
#define _DEFAULT_SOURCE
#include "redismodule.h"
#include <string.h>
#include <assert.h>
#include <unistd.h>
...
...
tests/modules/misc.c
0 → 100644
View file @
1ee195d2
#define REDISMODULE_EXPERIMENTAL_API
#include "redismodule.h"
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
int
test_call_generic
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
<
2
)
{
RedisModule_WrongArity
(
ctx
);
return
REDISMODULE_OK
;
}
const
char
*
cmdname
=
RedisModule_StringPtrLen
(
argv
[
1
],
NULL
);
RedisModuleCallReply
*
reply
=
RedisModule_Call
(
ctx
,
cmdname
,
"v"
,
argv
+
2
,
argc
-
2
);
if
(
reply
)
{
RedisModule_ReplyWithCallReply
(
ctx
,
reply
);
RedisModule_FreeCallReply
(
reply
);
}
else
{
RedisModule_ReplyWithError
(
ctx
,
strerror
(
errno
));
}
return
REDISMODULE_OK
;
}
int
test_call_info
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
RedisModuleCallReply
*
reply
;
if
(
argc
>
1
)
reply
=
RedisModule_Call
(
ctx
,
"info"
,
"s"
,
argv
[
1
]);
else
reply
=
RedisModule_Call
(
ctx
,
"info"
,
""
);
if
(
reply
)
{
RedisModule_ReplyWithCallReply
(
ctx
,
reply
);
RedisModule_FreeCallReply
(
reply
);
}
else
{
RedisModule_ReplyWithError
(
ctx
,
strerror
(
errno
));
}
return
REDISMODULE_OK
;
}
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
if
(
RedisModule_Init
(
ctx
,
"misc"
,
1
,
REDISMODULE_APIVER_1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.call_generic"
,
test_call_generic
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.call_info"
,
test_call_info
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_OK
;
}
tests/unit/moduleapi/misc.tcl
0 → 100644
View file @
1ee195d2
set testmodule
[
file normalize tests/modules/misc.so
]
start_server
{
tags
{
"modules"
}}
{
r module load $testmodule
test
{
test RM_Call
}
{
set info
[
r test.call_info commandstats
]
# cmdstat is not in a default section, so we also test an argument was passed
assert
{
[
string match
"*cmdstat_module*"
$info
]
}
}
test
{
test RM_Call args array
}
{
set info
[
r test.call_generic info commandstats
]
# cmdstat is not in a default section, so we also test an argument was passed
assert
{
[
string match
"*cmdstat_module*"
$info
]
}
}
}
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