summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDvir Volk <dvirsky@gmail.com>2018-01-07 16:41:43 +0200
committerantirez <antirez@gmail.com>2018-01-18 12:14:42 +0100
commit9f7e214e8cfc9c5636e4198371aed209fe0522a5 (patch)
tree309eb3156c7ae3e133191ce02720292e29a4dff1
parent947077bbcbb23905d78b8b7cad4ff775356fcf24 (diff)
downloadredis-9f7e214e8cfc9c5636e4198371aed209fe0522a5.tar.gz
Added RM_UnlinkKey - a low level analog to UNLINK command
-rw-r--r--src/module.c15
-rw-r--r--src/modules/testmodule.c39
-rw-r--r--src/redismodule.h2
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);