From b7f2a1a217b5c5b7b0320bfe0511dfdf2e0eb174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20S=C3=B6derqvist?= Date: Mon, 18 Oct 2021 21:21:19 +0200 Subject: [PATCH] Add RedisModule_KeyExists (#9600) The LRU of the key is not touched. Locically expired keys are logically not existing, so they're treated as such. --- src/module.c | 12 ++++++++++++ src/redismodule.h | 2 ++ tests/modules/misc.c | 9 +++++++++ tests/unit/moduleapi/misc.tcl | 7 +++++++ 4 files changed, 30 insertions(+) diff --git a/src/module.c b/src/module.c index 0cdad7eac..9cf30938d 100644 --- a/src/module.c +++ b/src/module.c @@ -2707,6 +2707,17 @@ int RM_SelectDb(RedisModuleCtx *ctx, int newid) { return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR; } +/* Check if a key exists, without affecting its last access time. + * + * This is equivalent to calling RM_OpenKey with the mode REDISMODULE_READ | + * REDISMODULE_OPEN_KEY_NOTOUCH, then checking if NULL was returned and, if not, + * calling RM_CloseKey on the opened key. + */ +int RM_KeyExists(RedisModuleCtx *ctx, robj *keyname) { + robj *value = lookupKeyReadWithFlags(ctx->client->db, keyname, LOOKUP_NOTOUCH); + return (value != NULL); +} + /* Initialize a RedisModuleKey struct */ static void moduleInitKey(RedisModuleKey *kp, RedisModuleCtx *ctx, robj *keyname, robj *value, int mode){ kp->ctx = ctx; @@ -10261,6 +10272,7 @@ void moduleRegisterCoreAPI(void) { REGISTER_API(ReplyWithLongDouble); REGISTER_API(GetSelectedDb); REGISTER_API(SelectDb); + REGISTER_API(KeyExists); REGISTER_API(OpenKey); REGISTER_API(CloseKey); REGISTER_API(KeyType); diff --git a/src/redismodule.h b/src/redismodule.h index 938bacc5c..85c963d58 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -610,6 +610,7 @@ REDISMODULE_API int (*RedisModule_WrongArity)(RedisModuleCtx *ctx) REDISMODULE_A REDISMODULE_API int (*RedisModule_ReplyWithLongLong)(RedisModuleCtx *ctx, long long ll) REDISMODULE_ATTR; REDISMODULE_API int (*RedisModule_GetSelectedDb)(RedisModuleCtx *ctx) REDISMODULE_ATTR; REDISMODULE_API int (*RedisModule_SelectDb)(RedisModuleCtx *ctx, int newid) REDISMODULE_ATTR; +REDISMODULE_API int (*RedisModule_KeyExists)(RedisModuleCtx *ctx, RedisModuleString *keyname) REDISMODULE_ATTR; REDISMODULE_API void * (*RedisModule_OpenKey)(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode) REDISMODULE_ATTR; REDISMODULE_API void (*RedisModule_CloseKey)(RedisModuleKey *kp) REDISMODULE_ATTR; REDISMODULE_API int (*RedisModule_KeyType)(RedisModuleKey *kp) REDISMODULE_ATTR; @@ -953,6 +954,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(ReplyWithLongDouble); REDISMODULE_GET_API(GetSelectedDb); REDISMODULE_GET_API(SelectDb); + REDISMODULE_GET_API(KeyExists); REDISMODULE_GET_API(OpenKey); REDISMODULE_GET_API(CloseKey); REDISMODULE_GET_API(KeyType); diff --git a/tests/modules/misc.c b/tests/modules/misc.c index 1c7c47a90..88039c6dd 100644 --- a/tests/modules/misc.c +++ b/tests/modules/misc.c @@ -122,6 +122,13 @@ int test_randomkey(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) return REDISMODULE_OK; } +int test_keyexists(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + if (argc < 2) return RedisModule_WrongArity(ctx); + RedisModuleString *key = argv[1]; + int exists = RedisModule_KeyExists(ctx, key); + return RedisModule_ReplyWithBool(ctx, exists); +} + RedisModuleKey *open_key_or_reply(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode) { RedisModuleKey *key = RedisModule_OpenKey(ctx, keyname, mode); if (!key) { @@ -306,6 +313,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"test.randomkey", test_randomkey,"",0,0,0) == REDISMODULE_ERR) return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"test.keyexists", test_keyexists,"",1,1,1) == REDISMODULE_ERR) + return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"test.setlru", test_setlru,"",0,0,0) == REDISMODULE_ERR) return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"test.getlru", test_getlru,"",0,0,0) == REDISMODULE_ERR) diff --git a/tests/unit/moduleapi/misc.tcl b/tests/unit/moduleapi/misc.tcl index 3205b1c45..a74c89aec 100644 --- a/tests/unit/moduleapi/misc.tcl +++ b/tests/unit/moduleapi/misc.tcl @@ -40,6 +40,13 @@ start_server {tags {"modules"}} { assert_equal [r test.dbsize] 0 } + test {test module keyexists} { + r set x foo + assert_equal 1 [r test.keyexists x] + r del x + assert_equal 0 [r test.keyexists x] + } + test {test module lru api} { r config set maxmemory-policy allkeys-lru r set x foo