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
54ad626c
Commit
54ad626c
authored
Sep 28, 2017
by
Salvatore Sanfilippo
Committed by
GitHub
Sep 28, 2017
Browse files
Merge pull request #4337 from dvirsky/module_ctx_flags
Module Context flags
parents
474adba9
7393fd81
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/module.c
View file @
54ad626c
...
@@ -1262,6 +1262,74 @@ int RM_GetSelectedDb(RedisModuleCtx *ctx) {
...
@@ -1262,6 +1262,74 @@ int RM_GetSelectedDb(RedisModuleCtx *ctx) {
return
ctx
->
client
->
db
->
id
;
return
ctx
->
client
->
db
->
id
;
}
}
/* Return the current context's flags. The flags provide information on the
* current request context (whether the client is a Lua script or in a MULTI),
* and about the Redis instance in general, i.e replication and persistence.
*
* The available flags are:
*
* * REDISMODULE_CTX_FLAGS_LUA: The command is running in a Lua script
*
* * REDISMODULE_CTX_FLAGS_MULTI: The command is running inside a transaction
*
* * REDISMODULE_CTX_FLAGS_MASTER: The Redis instance is a master
*
* * REDISMODULE_CTX_FLAGS_SLAVE: The Redis instance is a slave
*
* * REDISMODULE_CTX_FLAGS_READONLY: The Redis instance is read-only
*
* * REDISMODULE_CTX_FLAGS_CLUSTER: The Redis instance is in cluster mode
*
* * REDISMODULE_CTX_FLAGS_AOF: The Redis instance has AOF enabled
*
* * REDISMODULE_CTX_FLAGS_RDB: The instance has RDB enabled
*
* * REDISMODULE_CTX_FLAGS_MAXMEMORY: The instance has Maxmemory set
*
* * REDISMODULE_CTX_FLAGS_EVICT: Maxmemory is set and has an eviction
* policy that may delete keys
*/
int
RM_GetContextFlags
(
RedisModuleCtx
*
ctx
)
{
int
flags
=
0
;
/* Client specific flags */
if
(
ctx
->
client
)
{
if
(
ctx
->
client
->
flags
&
CLIENT_LUA
)
flags
|=
REDISMODULE_CTX_FLAGS_LUA
;
if
(
ctx
->
client
->
flags
&
CLIENT_MULTI
)
flags
|=
REDISMODULE_CTX_FLAGS_MULTI
;
}
if
(
server
.
cluster_enabled
)
flags
|=
REDISMODULE_CTX_FLAGS_CLUSTER
;
/* Maxmemory and eviction policy */
if
(
server
.
maxmemory
>
0
)
{
flags
|=
REDISMODULE_CTX_FLAGS_MAXMEMORY
;
if
(
server
.
maxmemory_policy
!=
MAXMEMORY_NO_EVICTION
)
flags
|=
REDISMODULE_CTX_FLAGS_EVICT
;
}
/* Persistence flags */
if
(
server
.
aof_state
!=
AOF_OFF
)
flags
|=
REDISMODULE_CTX_FLAGS_AOF
;
if
(
server
.
saveparamslen
>
0
)
flags
|=
REDISMODULE_CTX_FLAGS_RDB
;
/* Replication flags */
if
(
server
.
masterhost
==
NULL
)
{
flags
|=
REDISMODULE_CTX_FLAGS_MASTER
;
}
else
{
flags
|=
REDISMODULE_CTX_FLAGS_SLAVE
;
if
(
server
.
repl_slave_ro
)
flags
|=
REDISMODULE_CTX_FLAGS_READONLY
;
}
return
flags
;
}
/* Change the currently selected DB. Returns an error if the id
/* Change the currently selected DB. Returns an error if the id
* is out of range.
* is out of range.
*
*
...
@@ -3333,14 +3401,16 @@ void unblockClientFromModule(client *c) {
...
@@ -3333,14 +3401,16 @@ void unblockClientFromModule(client *c) {
RedisModuleBlockedClient
*
RM_BlockClient
(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
void
*
),
long
long
timeout_ms
)
{
RedisModuleBlockedClient
*
RM_BlockClient
(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
void
*
),
long
long
timeout_ms
)
{
client
*
c
=
ctx
->
client
;
client
*
c
=
ctx
->
client
;
int
islua
=
c
->
flags
&
CLIENT_LUA
;
int
islua
=
c
->
flags
&
CLIENT_LUA
;
int
ismulti
=
c
->
flags
&
CLIENT_MULTI
;
c
->
bpop
.
module_blocked_handle
=
zmalloc
(
sizeof
(
RedisModuleBlockedClient
));
c
->
bpop
.
module_blocked_handle
=
zmalloc
(
sizeof
(
RedisModuleBlockedClient
));
RedisModuleBlockedClient
*
bc
=
c
->
bpop
.
module_blocked_handle
;
RedisModuleBlockedClient
*
bc
=
c
->
bpop
.
module_blocked_handle
;
/* We need to handle the invalid operation of calling modules blocking
/* We need to handle the invalid operation of calling modules blocking
* commands from Lua. We actually create an already aborted (client set to
* commands from Lua or MULTI. We actually create an already aborted
* NULL) blocked client handle, and actually reply to Lua with an error. */
* (client set to NULL) blocked client handle, and actually reply with
bc
->
client
=
islua
?
NULL
:
c
;
* an error. */
bc
->
client
=
(
islua
||
ismulti
)
?
NULL
:
c
;
bc
->
module
=
ctx
->
module
;
bc
->
module
=
ctx
->
module
;
bc
->
reply_callback
=
reply_callback
;
bc
->
reply_callback
=
reply_callback
;
bc
->
timeout_callback
=
timeout_callback
;
bc
->
timeout_callback
=
timeout_callback
;
...
@@ -3351,9 +3421,10 @@ RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc
...
@@ -3351,9 +3421,10 @@ RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc
bc
->
dbid
=
c
->
db
->
id
;
bc
->
dbid
=
c
->
db
->
id
;
c
->
bpop
.
timeout
=
timeout_ms
?
(
mstime
()
+
timeout_ms
)
:
0
;
c
->
bpop
.
timeout
=
timeout_ms
?
(
mstime
()
+
timeout_ms
)
:
0
;
if
(
islua
)
{
if
(
islua
||
ismulti
)
{
c
->
bpop
.
module_blocked_handle
=
NULL
;
c
->
bpop
.
module_blocked_handle
=
NULL
;
addReplyError
(
c
,
"Blocking module command called from Lua script"
);
addReplyError
(
c
,
islua
?
"Blocking module command called from Lua script"
:
"Blocking module command called from transaction"
);
}
else
{
}
else
{
blockClient
(
c
,
BLOCKED_MODULE
);
blockClient
(
c
,
BLOCKED_MODULE
);
}
}
...
@@ -3891,6 +3962,7 @@ void moduleRegisterCoreAPI(void) {
...
@@ -3891,6 +3962,7 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API
(
IsKeysPositionRequest
);
REGISTER_API
(
IsKeysPositionRequest
);
REGISTER_API
(
KeyAtPos
);
REGISTER_API
(
KeyAtPos
);
REGISTER_API
(
GetClientId
);
REGISTER_API
(
GetClientId
);
REGISTER_API
(
GetContextFlags
);
REGISTER_API
(
PoolAlloc
);
REGISTER_API
(
PoolAlloc
);
REGISTER_API
(
CreateDataType
);
REGISTER_API
(
CreateDataType
);
REGISTER_API
(
ModuleTypeSetValue
);
REGISTER_API
(
ModuleTypeSetValue
);
...
...
src/modules/testmodule.c
View file @
54ad626c
...
@@ -121,6 +121,81 @@ int TestStringPrintf(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
...
@@ -121,6 +121,81 @@ int TestStringPrintf(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
}
}
/* TEST.CTXFLAGS -- Test GetContextFlags. */
int
TestCtxFlags
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argc
);
REDISMODULE_NOT_USED
(
argv
);
RedisModule_AutoMemory
(
ctx
);
int
ok
=
1
;
const
char
*
errString
=
NULL
;
#define FAIL(msg) \
{ \
ok = 0; \
errString = msg; \
goto end; \
}
int
flags
=
RedisModule_GetContextFlags
(
ctx
);
if
(
flags
==
0
)
{
FAIL
(
"Got no flags"
);
}
if
(
flags
&
REDISMODULE_CTX_FLAGS_LUA
)
FAIL
(
"Lua flag was set"
);
if
(
flags
&
REDISMODULE_CTX_FLAGS_MULTI
)
FAIL
(
"Multi flag was set"
);
if
(
flags
&
REDISMODULE_CTX_FLAGS_AOF
)
FAIL
(
"AOF Flag was set"
)
/* Enable AOF to test AOF flags */
RedisModule_Call
(
ctx
,
"config"
,
"ccc"
,
"set"
,
"appendonly"
,
"yes"
);
flags
=
RedisModule_GetContextFlags
(
ctx
);
if
(
!
(
flags
&
REDISMODULE_CTX_FLAGS_AOF
))
FAIL
(
"AOF Flag not set after config set"
);
if
(
flags
&
REDISMODULE_CTX_FLAGS_RDB
)
FAIL
(
"RDB Flag was set"
);
/* Enable RDB to test RDB flags */
RedisModule_Call
(
ctx
,
"config"
,
"ccc"
,
"set"
,
"save"
,
"900 1"
);
flags
=
RedisModule_GetContextFlags
(
ctx
);
if
(
!
(
flags
&
REDISMODULE_CTX_FLAGS_RDB
))
FAIL
(
"RDB Flag was not set after config set"
);
if
(
!
(
flags
&
REDISMODULE_CTX_FLAGS_MASTER
))
FAIL
(
"Master flag was not set"
);
if
(
flags
&
REDISMODULE_CTX_FLAGS_SLAVE
)
FAIL
(
"Slave flag was set"
);
if
(
flags
&
REDISMODULE_CTX_FLAGS_READONLY
)
FAIL
(
"Read-only flag was set"
);
if
(
flags
&
REDISMODULE_CTX_FLAGS_CLUSTER
)
FAIL
(
"Cluster flag was set"
);
if
(
flags
&
REDISMODULE_CTX_FLAGS_MAXMEMORY
)
FAIL
(
"Maxmemory flag was set"
);
;
RedisModule_Call
(
ctx
,
"config"
,
"ccc"
,
"set"
,
"maxmemory"
,
"100000000"
);
flags
=
RedisModule_GetContextFlags
(
ctx
);
if
(
!
(
flags
&
REDISMODULE_CTX_FLAGS_MAXMEMORY
))
FAIL
(
"Maxmemory flag was not set after config set"
);
if
(
flags
&
REDISMODULE_CTX_FLAGS_EVICT
)
FAIL
(
"Eviction flag was set"
);
RedisModule_Call
(
ctx
,
"config"
,
"ccc"
,
"set"
,
"maxmemory-policy"
,
"allkeys-lru"
);
flags
=
RedisModule_GetContextFlags
(
ctx
);
if
(
!
(
flags
&
REDISMODULE_CTX_FLAGS_EVICT
))
FAIL
(
"Eviction flag was not set after config set"
);
end:
/* Revert config changes */
RedisModule_Call
(
ctx
,
"config"
,
"ccc"
,
"set"
,
"appendonly"
,
"no"
);
RedisModule_Call
(
ctx
,
"config"
,
"ccc"
,
"set"
,
"save"
,
""
);
RedisModule_Call
(
ctx
,
"config"
,
"ccc"
,
"set"
,
"maxmemory"
,
"0"
);
RedisModule_Call
(
ctx
,
"config"
,
"ccc"
,
"set"
,
"maxmemory-policy"
,
"noeviction"
);
if
(
!
ok
)
{
RedisModule_Log
(
ctx
,
"warning"
,
"Failed CTXFLAGS Test. Reason: %s"
,
errString
);
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"ERR"
);
}
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
}
/* ----------------------------- Test framework ----------------------------- */
/* ----------------------------- Test framework ----------------------------- */
/* Return 1 if the reply matches the specified string, otherwise log errors
/* Return 1 if the reply matches the specified string, otherwise log errors
...
@@ -188,6 +263,9 @@ int TestIt(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
...
@@ -188,6 +263,9 @@ int TestIt(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
T
(
"test.call"
,
""
);
T
(
"test.call"
,
""
);
if
(
!
TestAssertStringReply
(
ctx
,
reply
,
"OK"
,
2
))
goto
fail
;
if
(
!
TestAssertStringReply
(
ctx
,
reply
,
"OK"
,
2
))
goto
fail
;
T
(
"test.ctxflags"
,
""
);
if
(
!
TestAssertStringReply
(
ctx
,
reply
,
"OK"
,
2
))
goto
fail
;
T
(
"test.string.append"
,
""
);
T
(
"test.string.append"
,
""
);
if
(
!
TestAssertStringReply
(
ctx
,
reply
,
"foobar"
,
6
))
goto
fail
;
if
(
!
TestAssertStringReply
(
ctx
,
reply
,
"foobar"
,
6
))
goto
fail
;
...
@@ -229,6 +307,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
...
@@ -229,6 +307,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
TestStringPrintf
,
"write deny-oom"
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
TestStringPrintf
,
"write deny-oom"
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.ctxflags"
,
TestCtxFlags
,
"readonly"
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"test.it"
,
if
(
RedisModule_CreateCommand
(
ctx
,
"test.it"
,
TestIt
,
"readonly"
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
TestIt
,
"readonly"
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_ERR
;
...
...
src/redismodule.h
View file @
54ad626c
...
@@ -58,6 +58,30 @@
...
@@ -58,6 +58,30 @@
#define REDISMODULE_HASH_CFIELDS (1<<2)
#define REDISMODULE_HASH_CFIELDS (1<<2)
#define REDISMODULE_HASH_EXISTS (1<<3)
#define REDISMODULE_HASH_EXISTS (1<<3)
/* Context Flags: Info about the current context returned by RM_GetContextFlags */
/* The command is running in the context of a Lua script */
#define REDISMODULE_CTX_FLAGS_LUA 0x0001
/* The command is running inside a Redis transaction */
#define REDISMODULE_CTX_FLAGS_MULTI 0x0002
/* The instance is a master */
#define REDISMODULE_CTX_FLAGS_MASTER 0x0004
/* The instance is a slave */
#define REDISMODULE_CTX_FLAGS_SLAVE 0x0008
/* The instance is read-only (usually meaning it's a slave as well) */
#define REDISMODULE_CTX_FLAGS_READONLY 0x0010
/* The instance is running in cluster mode */
#define REDISMODULE_CTX_FLAGS_CLUSTER 0x0020
/* The instance has AOF enabled */
#define REDISMODULE_CTX_FLAGS_AOF 0x0040 //
/* The instance has RDB enabled */
#define REDISMODULE_CTX_FLAGS_RDB 0x0080 //
/* The instance has Maxmemory set */
#define REDISMODULE_CTX_FLAGS_MAXMEMORY 0x0100
/* Maxmemory is set and has an eviction policy that may delete keys */
#define REDISMODULE_CTX_FLAGS_EVICT 0x0200
/* A special pointer that we can use between the core and the module to signal
/* A special pointer that we can use between the core and the module to signal
* field deletion, and that is impossible to be a valid pointer. */
* field deletion, and that is impossible to be a valid pointer. */
#define REDISMODULE_HASH_DELETE ((RedisModuleString*)(long)1)
#define REDISMODULE_HASH_DELETE ((RedisModuleString*)(long)1)
...
@@ -183,6 +207,7 @@ int REDISMODULE_API_FUNC(RedisModule_HashGet)(RedisModuleKey *key, int flags, ..
...
@@ -183,6 +207,7 @@ int REDISMODULE_API_FUNC(RedisModule_HashGet)(RedisModuleKey *key, int flags, ..
int
REDISMODULE_API_FUNC
(
RedisModule_IsKeysPositionRequest
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_IsKeysPositionRequest
)(
RedisModuleCtx
*
ctx
);
void
REDISMODULE_API_FUNC
(
RedisModule_KeyAtPos
)(
RedisModuleCtx
*
ctx
,
int
pos
);
void
REDISMODULE_API_FUNC
(
RedisModule_KeyAtPos
)(
RedisModuleCtx
*
ctx
,
int
pos
);
unsigned
long
long
REDISMODULE_API_FUNC
(
RedisModule_GetClientId
)(
RedisModuleCtx
*
ctx
);
unsigned
long
long
REDISMODULE_API_FUNC
(
RedisModule_GetClientId
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetContextFlags
)(
RedisModuleCtx
*
ctx
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_PoolAlloc
)(
RedisModuleCtx
*
ctx
,
size_t
bytes
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_PoolAlloc
)(
RedisModuleCtx
*
ctx
,
size_t
bytes
);
RedisModuleType
*
REDISMODULE_API_FUNC
(
RedisModule_CreateDataType
)(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
int
encver
,
RedisModuleTypeMethods
*
typemethods
);
RedisModuleType
*
REDISMODULE_API_FUNC
(
RedisModule_CreateDataType
)(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
int
encver
,
RedisModuleTypeMethods
*
typemethods
);
int
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeSetValue
)(
RedisModuleKey
*
key
,
RedisModuleType
*
mt
,
void
*
value
);
int
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeSetValue
)(
RedisModuleKey
*
key
,
RedisModuleType
*
mt
,
void
*
value
);
...
@@ -302,6 +327,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -302,6 +327,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
IsKeysPositionRequest
);
REDISMODULE_GET_API
(
IsKeysPositionRequest
);
REDISMODULE_GET_API
(
KeyAtPos
);
REDISMODULE_GET_API
(
KeyAtPos
);
REDISMODULE_GET_API
(
GetClientId
);
REDISMODULE_GET_API
(
GetClientId
);
REDISMODULE_GET_API
(
GetContextFlags
);
REDISMODULE_GET_API
(
PoolAlloc
);
REDISMODULE_GET_API
(
PoolAlloc
);
REDISMODULE_GET_API
(
CreateDataType
);
REDISMODULE_GET_API
(
CreateDataType
);
REDISMODULE_GET_API
(
ModuleTypeSetValue
);
REDISMODULE_GET_API
(
ModuleTypeSetValue
);
...
...
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