summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDvir Volk <dvirsky@gmail.com>2017-09-27 11:52:39 +0300
committerDvir Volk <dvirsky@gmail.com>2017-09-27 11:58:07 +0300
commit616c546b010b45571ec2fb569f127e50c9c5bf42 (patch)
tree2023a9a9e476704837347d2236d1e8223a56596c
parent474adba9fa7a173d866300b1abd7cddd34cbac40 (diff)
downloadredis-616c546b010b45571ec2fb569f127e50c9c5bf42.tar.gz
Added support for module context flags with RM_GetCtxFlags
-rw-r--r--src/module.c69
-rw-r--r--src/modules/testmodule.c82
-rw-r--r--src/redismodule.h26
3 files changed, 177 insertions, 0 deletions
diff --git a/src/module.c b/src/module.c
index fda68b273..f467c5a49 100644
--- a/src/module.c
+++ b/src/module.c
@@ -1262,6 +1262,74 @@ int RM_GetSelectedDb(RedisModuleCtx *ctx) {
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_GetCtxFlags(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
* is out of range.
*
@@ -3891,6 +3959,7 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API(IsKeysPositionRequest);
REGISTER_API(KeyAtPos);
REGISTER_API(GetClientId);
+ REGISTER_API(GetCtxFlags);
REGISTER_API(PoolAlloc);
REGISTER_API(CreateDataType);
REGISTER_API(ModuleTypeSetValue);
diff --git a/src/modules/testmodule.c b/src/modules/testmodule.c
index 8da45c0ea..58e397790 100644
--- a/src/modules/testmodule.c
+++ b/src/modules/testmodule.c
@@ -121,6 +121,81 @@ int TestStringPrintf(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
}
+/* TEST.CTXFLAGS -- Test GetCtxFlags. */
+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_GetCtxFlags(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_GetCtxFlags(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_GetCtxFlags(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_GetCtxFlags(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_GetCtxFlags(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 ----------------------------- */
/* Return 1 if the reply matches the specified string, otherwise log errors
@@ -188,6 +263,9 @@ int TestIt(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
T("test.call","");
if (!TestAssertStringReply(ctx,reply,"OK",2)) goto fail;
+ T("test.ctxflags","");
+ if (!TestAssertStringReply(ctx,reply,"OK",2)) goto fail;
+
T("test.string.append","");
if (!TestAssertStringReply(ctx,reply,"foobar",6)) goto fail;
@@ -229,6 +307,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
TestStringPrintf,"write deny-oom",1,1,1) == 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",
TestIt,"readonly",1,1,1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
diff --git a/src/redismodule.h b/src/redismodule.h
index 7fc0fec40..4aa35190b 100644
--- a/src/redismodule.h
+++ b/src/redismodule.h
@@ -58,6 +58,30 @@
#define REDISMODULE_HASH_CFIELDS (1<<2)
#define REDISMODULE_HASH_EXISTS (1<<3)
+/* Context Flags: Info about the current context returned by RM_GetCtxFlags */
+
+/* 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
* field deletion, and that is impossible to be a valid pointer. */
#define REDISMODULE_HASH_DELETE ((RedisModuleString*)(long)1)
@@ -183,6 +207,7 @@ int REDISMODULE_API_FUNC(RedisModule_HashGet)(RedisModuleKey *key, int flags, ..
int REDISMODULE_API_FUNC(RedisModule_IsKeysPositionRequest)(RedisModuleCtx *ctx);
void REDISMODULE_API_FUNC(RedisModule_KeyAtPos)(RedisModuleCtx *ctx, int pos);
unsigned long long REDISMODULE_API_FUNC(RedisModule_GetClientId)(RedisModuleCtx *ctx);
+int REDISMODULE_API_FUNC(RedisModule_GetCtxFlags)(RedisModuleCtx *ctx);
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);
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
REDISMODULE_GET_API(IsKeysPositionRequest);
REDISMODULE_GET_API(KeyAtPos);
REDISMODULE_GET_API(GetClientId);
+ REDISMODULE_GET_API(GetCtxFlags);
REDISMODULE_GET_API(PoolAlloc);
REDISMODULE_GET_API(CreateDataType);
REDISMODULE_GET_API(ModuleTypeSetValue);