From cb9dde3280244ec3b449f081639c37dd5a1916ab Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Thu, 28 Sep 2017 16:21:21 +0800 Subject: [PATCH 1/2] Modules: handle the conflict of registering commands --- src/module.c | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/module.c b/src/module.c index fda68b273..4604c0bef 100644 --- a/src/module.c +++ b/src/module.c @@ -615,7 +615,7 @@ int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc c sds cmdname = sdsnew(name); /* Check if the command name is busy. */ - if (lookupCommand((char*)name) != NULL) { + if (lookupCommand(cmdname) != NULL) { sdsfree(cmdname); return REDISMODULE_ERR; } @@ -3661,6 +3661,28 @@ void moduleFreeModuleStructure(struct RedisModule *module) { zfree(module); } +void moduleUnregisterCommands(struct RedisModule *module) { + /* Unregister all the commands registered by this module. */ + dictIterator *di = dictGetSafeIterator(server.commands); + dictEntry *de; + while ((de = dictNext(di)) != NULL) { + struct redisCommand *cmd = dictGetVal(de); + if (cmd->proc == RedisModuleCommandDispatcher) { + RedisModuleCommandProxy *cp = + (void*)(unsigned long)cmd->getkeys_proc; + sds cmdname = cp->rediscmd->name; + if (cp->module == module) { + dictDelete(server.commands,cmdname); + dictDelete(server.orig_commands,cmdname); + sdsfree(cmdname); + zfree(cp->rediscmd); + zfree(cp); + } + } + } + dictReleaseIterator(di); +} + /* Load a module and initialize it. On success C_OK is returned, otherwise * C_ERR is returned. */ int moduleLoad(const char *path, void **module_argv, int module_argc) { @@ -3681,7 +3703,10 @@ int moduleLoad(const char *path, void **module_argv, int module_argc) { return C_ERR; } if (onload((void*)&ctx,module_argv,module_argc) == REDISMODULE_ERR) { - if (ctx.module) moduleFreeModuleStructure(ctx.module); + if (ctx.module) { + moduleUnregisterCommands(ctx.module); + moduleFreeModuleStructure(ctx.module); + } dlclose(handle); serverLog(LL_WARNING, "Module %s initialization failed. Module not loaded",path); @@ -3715,25 +3740,7 @@ int moduleUnload(sds name) { return REDISMODULE_ERR; } - /* Unregister all the commands registered by this module. */ - dictIterator *di = dictGetSafeIterator(server.commands); - dictEntry *de; - while ((de = dictNext(di)) != NULL) { - struct redisCommand *cmd = dictGetVal(de); - if (cmd->proc == RedisModuleCommandDispatcher) { - RedisModuleCommandProxy *cp = - (void*)(unsigned long)cmd->getkeys_proc; - sds cmdname = cp->rediscmd->name; - if (cp->module == module) { - dictDelete(server.commands,cmdname); - dictDelete(server.orig_commands,cmdname); - sdsfree(cmdname); - zfree(cp->rediscmd); - zfree(cp); - } - } - } - dictReleaseIterator(di); + moduleUnregisterCommands(module); /* Unregister all the hooks. TODO: Yet no hooks support here. */ From 6dffc1b7a33f1fd4fa1ff0368933ed575bca5606 Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Thu, 28 Sep 2017 17:38:40 +0800 Subject: [PATCH 2/2] Modules: handle the busy module name --- src/module.c | 16 +++++++++++++++- src/redismodule.h | 5 ++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/module.c b/src/module.c index 4604c0bef..2303b00ee 100644 --- a/src/module.c +++ b/src/module.c @@ -650,7 +650,7 @@ int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc c * * This is an internal function, Redis modules developers don't need * to use it. */ -void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int apiver){ +void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int apiver) { RedisModule *module; if (ctx->module != NULL) return; @@ -662,6 +662,19 @@ void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int api ctx->module = module; } +/* Return non-zero if the module name is busy. + * Otherwise zero is returned. */ +int RM_IsModuleNameBusy(const char *name) { + sds modulename = sdsnew(name); + + /* Check if the module name is busy. */ + if (dictFind(modules,modulename) != NULL) { + sdsfree(modulename); + return 1; + } + return 0; +} + /* Return the current UNIX time in milliseconds. */ long long RM_Milliseconds(void) { return mstime(); @@ -3835,6 +3848,7 @@ void moduleRegisterCoreAPI(void) { REGISTER_API(Strdup); REGISTER_API(CreateCommand); REGISTER_API(SetModuleAttribs); + REGISTER_API(IsModuleNameBusy); REGISTER_API(WrongArity); REGISTER_API(ReplyWithLongLong); REGISTER_API(ReplyWithError); diff --git a/src/redismodule.h b/src/redismodule.h index 7fc0fec40..8078e9fe3 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -119,7 +119,8 @@ void *REDISMODULE_API_FUNC(RedisModule_Calloc)(size_t nmemb, size_t size); char *REDISMODULE_API_FUNC(RedisModule_Strdup)(const char *str); int REDISMODULE_API_FUNC(RedisModule_GetApi)(const char *, void *); int REDISMODULE_API_FUNC(RedisModule_CreateCommand)(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep); -int REDISMODULE_API_FUNC(RedisModule_SetModuleAttribs)(RedisModuleCtx *ctx, const char *name, int ver, int apiver); +void REDISMODULE_API_FUNC(RedisModule_SetModuleAttribs)(RedisModuleCtx *ctx, const char *name, int ver, int apiver); +int REDISMODULE_API_FUNC(RedisModule_IsModuleNameBusy)(const char *name); int REDISMODULE_API_FUNC(RedisModule_WrongArity)(RedisModuleCtx *ctx); int REDISMODULE_API_FUNC(RedisModule_ReplyWithLongLong)(RedisModuleCtx *ctx, long long ll); int REDISMODULE_API_FUNC(RedisModule_GetSelectedDb)(RedisModuleCtx *ctx); @@ -238,6 +239,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(Strdup); REDISMODULE_GET_API(CreateCommand); REDISMODULE_GET_API(SetModuleAttribs); + REDISMODULE_GET_API(IsModuleNameBusy); REDISMODULE_GET_API(WrongArity); REDISMODULE_GET_API(ReplyWithLongLong); REDISMODULE_GET_API(ReplyWithError); @@ -344,6 +346,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(AbortBlock); #endif + if (RedisModule_IsModuleNameBusy(name)) return REDISMODULE_ERR; RedisModule_SetModuleAttribs(ctx,name,ver,apiver); return REDISMODULE_OK; }