Added RM_UnlinkKey - a low level analog to UNLINK command

This commit is contained in:
Dvir Volk 2018-01-07 16:41:43 +02:00
parent e509fbb8d9
commit e76dfc90a7
3 changed files with 56 additions and 0 deletions

View File

@ -1456,6 +1456,20 @@ int RM_DeleteKey(RedisModuleKey *key) {
return REDISMODULE_OK; 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. /* Return the key expire value, as milliseconds of remaining TTL.
* If no TTL is associated with the key or if the key is empty, * If no TTL is associated with the key or if the key is empty,
* REDISMODULE_NO_EXPIRE is returned. */ * REDISMODULE_NO_EXPIRE is returned. */
@ -3960,6 +3974,7 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API(Replicate); REGISTER_API(Replicate);
REGISTER_API(ReplicateVerbatim); REGISTER_API(ReplicateVerbatim);
REGISTER_API(DeleteKey); REGISTER_API(DeleteKey);
REGISTER_API(UnlinkKey);
REGISTER_API(StringSet); REGISTER_API(StringSet);
REGISTER_API(StringDMA); REGISTER_API(StringDMA);
REGISTER_API(StringTruncate); REGISTER_API(StringTruncate);

View File

@ -120,6 +120,38 @@ int TestStringPrintf(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
return REDISMODULE_OK; 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. */ /* TEST.CTXFLAGS -- Test GetContextFlags. */
int TestCtxFlags(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { int TestCtxFlags(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
@ -269,6 +301,9 @@ int TestIt(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
T("test.string.append",""); T("test.string.append","");
if (!TestAssertStringReply(ctx,reply,"foobar",6)) goto fail; if (!TestAssertStringReply(ctx,reply,"foobar",6)) goto fail;
T("test.unlink","");
if (!TestAssertStringReply(ctx,reply,"OK",2)) goto fail;
T("test.string.append.am",""); T("test.string.append.am","");
if (!TestAssertStringReply(ctx,reply,"foobar",6)) goto fail; if (!TestAssertStringReply(ctx,reply,"foobar",6)) goto fail;
@ -311,6 +346,10 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
TestCtxFlags,"readonly",1,1,1) == REDISMODULE_ERR) TestCtxFlags,"readonly",1,1,1) == REDISMODULE_ERR)
return 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", 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;

View File

@ -185,6 +185,7 @@ int REDISMODULE_API_FUNC(RedisModule_ReplicateVerbatim)(RedisModuleCtx *ctx);
const char *REDISMODULE_API_FUNC(RedisModule_CallReplyStringPtr)(RedisModuleCallReply *reply, size_t *len); const char *REDISMODULE_API_FUNC(RedisModule_CallReplyStringPtr)(RedisModuleCallReply *reply, size_t *len);
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromCallReply)(RedisModuleCallReply *reply); RedisModuleString *REDISMODULE_API_FUNC(RedisModule_CreateStringFromCallReply)(RedisModuleCallReply *reply);
int REDISMODULE_API_FUNC(RedisModule_DeleteKey)(RedisModuleKey *key); 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); int REDISMODULE_API_FUNC(RedisModule_StringSet)(RedisModuleKey *key, RedisModuleString *str);
char *REDISMODULE_API_FUNC(RedisModule_StringDMA)(RedisModuleKey *key, size_t *len, int mode); char *REDISMODULE_API_FUNC(RedisModule_StringDMA)(RedisModuleKey *key, size_t *len, int mode);
int REDISMODULE_API_FUNC(RedisModule_StringTruncate)(RedisModuleKey *key, size_t newlen); 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(Replicate);
REDISMODULE_GET_API(ReplicateVerbatim); REDISMODULE_GET_API(ReplicateVerbatim);
REDISMODULE_GET_API(DeleteKey); REDISMODULE_GET_API(DeleteKey);
REDISMODULE_GET_API(UnlinkKey);
REDISMODULE_GET_API(StringSet); REDISMODULE_GET_API(StringSet);
REDISMODULE_GET_API(StringDMA); REDISMODULE_GET_API(StringDMA);
REDISMODULE_GET_API(StringTruncate); REDISMODULE_GET_API(StringTruncate);