diff options
author | Dvir Volk <dvirsky@gmail.com> | 2018-01-07 16:41:43 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2018-01-18 12:14:42 +0100 |
commit | 9f7e214e8cfc9c5636e4198371aed209fe0522a5 (patch) | |
tree | 309eb3156c7ae3e133191ce02720292e29a4dff1 | |
parent | 947077bbcbb23905d78b8b7cad4ff775356fcf24 (diff) | |
download | redis-9f7e214e8cfc9c5636e4198371aed209fe0522a5.tar.gz |
Added RM_UnlinkKey - a low level analog to UNLINK command
-rw-r--r-- | src/module.c | 15 | ||||
-rw-r--r-- | src/modules/testmodule.c | 39 | ||||
-rw-r--r-- | src/redismodule.h | 2 |
3 files changed, 56 insertions, 0 deletions
diff --git a/src/module.c b/src/module.c index 978188023..545f1a74a 100644 --- a/src/module.c +++ b/src/module.c @@ -1456,6 +1456,20 @@ int RM_DeleteKey(RedisModuleKey *key) { return REDISMODULE_OK; } +/* If the key is open for writing, unlink it (that is delete it in a + * non-blocking way, not reclaiming memory immediately) and setup the key to + * accept new writes as an empty key (that will be created on demand). + * On success REDISMODULE_OK is returned. If the key is not open for + * writing REDISMODULE_ERR is returned. */ +int RM_UnlinkKey(RedisModuleKey *key) { + if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR; + if (key->value) { + dbAsyncDelete(key->db,key->key); + key->value = NULL; + } + return REDISMODULE_OK; +} + /* Return the key expire value, as milliseconds of remaining TTL. * If no TTL is associated with the key or if the key is empty, * REDISMODULE_NO_EXPIRE is returned. */ @@ -3960,6 +3974,7 @@ void moduleRegisterCoreAPI(void) { REGISTER_API(Replicate); REGISTER_API(ReplicateVerbatim); REGISTER_API(DeleteKey); + REGISTER_API(UnlinkKey); REGISTER_API(StringSet); REGISTER_API(StringDMA); REGISTER_API(StringTruncate); diff --git a/src/modules/testmodule.c b/src/modules/testmodule.c index a0d706fea..956b24179 100644 --- a/src/modules/testmodule.c +++ b/src/modules/testmodule.c @@ -120,6 +120,38 @@ int TestStringPrintf(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { return REDISMODULE_OK; } +int failTest(RedisModuleCtx *ctx, const char *msg) { + RedisModule_ReplyWithError(ctx, msg); + return REDISMODULE_ERR; +} +int TestUnlink(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + RedisModule_AutoMemory(ctx); + REDISMODULE_NOT_USED(argv); + REDISMODULE_NOT_USED(argc); + + RedisModuleKey *k = RedisModule_OpenKey(ctx, RedisModule_CreateStringPrintf(ctx, "unlinked"), REDISMODULE_WRITE | REDISMODULE_READ); + if (!k) return failTest(ctx, "Could not create key"); + + if (REDISMODULE_ERR == RedisModule_StringSet(k, RedisModule_CreateStringPrintf(ctx, "Foobar"))) { + return failTest(ctx, "Could not set string value"); + } + + RedisModuleCallReply *rep = RedisModule_Call(ctx, "EXISTS", "c", "unlinked"); + if (!rep || RedisModule_CallReplyInteger(rep) != 1) { + return failTest(ctx, "Key does not exist before unlink"); + } + + if (REDISMODULE_ERR == RedisModule_UnlinkKey(k)) { + return failTest(ctx, "Could not unlink key"); + } + + rep = RedisModule_Call(ctx, "EXISTS", "c", "unlinked"); + if (!rep || RedisModule_CallReplyInteger(rep) != 0) { + return failTest(ctx, "Could not verify key to be unlinked"); + } + return RedisModule_ReplyWithSimpleString(ctx, "OK"); + +} /* TEST.CTXFLAGS -- Test GetContextFlags. */ int TestCtxFlags(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { @@ -269,6 +301,9 @@ int TestIt(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { T("test.string.append",""); if (!TestAssertStringReply(ctx,reply,"foobar",6)) goto fail; + T("test.unlink",""); + if (!TestAssertStringReply(ctx,reply,"OK",2)) goto fail; + T("test.string.append.am",""); if (!TestAssertStringReply(ctx,reply,"foobar",6)) goto fail; @@ -310,6 +345,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) if (RedisModule_CreateCommand(ctx,"test.ctxflags", TestCtxFlags,"readonly",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; + + if (RedisModule_CreateCommand(ctx,"test.unlink", + TestUnlink,"write deny-oom",1,1,1) == REDISMODULE_ERR) + return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"test.it", TestIt,"readonly",1,1,1) == REDISMODULE_ERR) diff --git a/src/redismodule.h b/src/redismodule.h index 672951f78..374cde7f0 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -185,6 +185,7 @@ int REDISMODULE_API_FUNC(RedisModule_ReplicateVerbatim)(RedisModuleCtx *ctx); const char *REDISMODULE_API_FUNC(RedisModule_CallReplyStringPtr)(RedisModuleCallReply *reply, size_t *len); RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromCallReply)(RedisModuleCallReply *reply); int REDISMODULE_API_FUNC(RedisModule_DeleteKey)(RedisModuleKey *key); +int REDISMODULE_API_FUNC(RedisModule_UnlinkKey)(RedisModuleKey *key); int REDISMODULE_API_FUNC(RedisModule_StringSet)(RedisModuleKey *key, RedisModuleString *str); char *REDISMODULE_API_FUNC(RedisModule_StringDMA)(RedisModuleKey *key, size_t *len, int mode); int REDISMODULE_API_FUNC(RedisModule_StringTruncate)(RedisModuleKey *key, size_t newlen); @@ -306,6 +307,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(Replicate); REDISMODULE_GET_API(ReplicateVerbatim); REDISMODULE_GET_API(DeleteKey); + REDISMODULE_GET_API(UnlinkKey); REDISMODULE_GET_API(StringSet); REDISMODULE_GET_API(StringDMA); REDISMODULE_GET_API(StringTruncate); |