Revert shared APIs to modify the design.
This commit is contained in:
parent
ab37289fa6
commit
850b64c116
115
src/module.c
115
src/module.c
@ -47,16 +47,7 @@ struct RedisModule {
|
|||||||
int ver; /* Module version. We use just progressive integers. */
|
int ver; /* Module version. We use just progressive integers. */
|
||||||
int apiver; /* Module API version as requested during initialization.*/
|
int apiver; /* Module API version as requested during initialization.*/
|
||||||
list *types; /* Module data types. */
|
list *types; /* Module data types. */
|
||||||
list *usedBy; /* list of modules names using this module api. */
|
|
||||||
list *using; /* list of modules names that this module is using thier api . */
|
|
||||||
list *exportedFunctions; /* list of function names exported by this module. */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModuleExportedApi {
|
|
||||||
void* funcPointer;
|
|
||||||
struct RedisModule* module;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct RedisModule RedisModule;
|
typedef struct RedisModule RedisModule;
|
||||||
|
|
||||||
static dict *modules; /* Hash table of modules. SDS -> RedisModule ptr.*/
|
static dict *modules; /* Hash table of modules. SDS -> RedisModule ptr.*/
|
||||||
@ -709,9 +700,6 @@ void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int api
|
|||||||
module->ver = ver;
|
module->ver = ver;
|
||||||
module->apiver = apiver;
|
module->apiver = apiver;
|
||||||
module->types = listCreate();
|
module->types = listCreate();
|
||||||
module->usedBy = listCreate();
|
|
||||||
module->using = listCreate();
|
|
||||||
module->exportedFunctions = listCreate();
|
|
||||||
ctx->module = module;
|
ctx->module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4627,59 +4615,6 @@ void RM_GetRandomHexChars(char *dst, size_t len) {
|
|||||||
getRandomHexChars(dst,len);
|
getRandomHexChars(dst,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to register an api to be used by other modules. */
|
|
||||||
int RM_RegisterApi(RedisModuleCtx *ctx, const char *funcname, void *funcptr) {
|
|
||||||
struct ModuleExportedApi* eapi = zmalloc(sizeof(*eapi));
|
|
||||||
eapi->module = ctx->module;
|
|
||||||
eapi->funcPointer = funcptr;
|
|
||||||
if(dictAdd(server.exportedapi, (char*)funcname, eapi) != DICT_OK){
|
|
||||||
zfree(eapi);
|
|
||||||
return REDISMODULE_ERR;
|
|
||||||
}
|
|
||||||
listAddNodeHead(ctx->module->exportedFunctions, (char*)funcname);
|
|
||||||
return REDISMODULE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int IsModuleInList(list *l, const char* moduleName){
|
|
||||||
listIter *iter = listGetIterator(l, AL_START_HEAD);
|
|
||||||
listNode *node = NULL;
|
|
||||||
while((node = listNext(iter))){
|
|
||||||
char* name = listNodeValue(node);
|
|
||||||
if(strcmp(name, moduleName) == 0){
|
|
||||||
listReleaseIterator(iter);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listReleaseIterator(iter);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void RemoveFromList(list *l, const char* moduleName){
|
|
||||||
listIter *iter = listGetIterator(l, AL_START_HEAD);
|
|
||||||
listNode *node = NULL;
|
|
||||||
while((node = listNext(iter))){
|
|
||||||
char* name = listNodeValue(node);
|
|
||||||
if(strcmp(name, moduleName) == 0){
|
|
||||||
listDelNode(l, node);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listReleaseIterator(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* RM_GetExportedApi(RedisModuleCtx *ctx, const char *funcname) {
|
|
||||||
dictEntry* entry = dictFind(server.exportedapi, funcname);
|
|
||||||
if(!entry){
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
struct ModuleExportedApi* eapi = dictGetVal(entry);
|
|
||||||
if(!IsModuleInList(eapi->module->usedBy, ctx->module->name)){
|
|
||||||
listAddNodeHead(eapi->module->usedBy, ctx->module->name);
|
|
||||||
listAddNodeHead(ctx->module->using, eapi->module->name);
|
|
||||||
}
|
|
||||||
return eapi->funcPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* Modules API internals
|
* Modules API internals
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
@ -4800,28 +4735,6 @@ void moduleUnregisterCommands(struct RedisModule *module) {
|
|||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
}
|
}
|
||||||
|
|
||||||
void moduleUnregisterApi(struct RedisModule *module) {
|
|
||||||
listIter *iter = listGetIterator(module->exportedFunctions, AL_START_HEAD);
|
|
||||||
listNode* node = NULL;
|
|
||||||
while((node = listNext(iter))){
|
|
||||||
char* functionName = listNodeValue(node);
|
|
||||||
struct ModuleExportedApi* eapi = dictFetchValue(server.exportedapi, functionName);
|
|
||||||
serverAssert(eapi);
|
|
||||||
zfree(eapi);
|
|
||||||
dictDelete(server.exportedapi, functionName);
|
|
||||||
}
|
|
||||||
listReleaseIterator(iter);
|
|
||||||
iter = listGetIterator(module->using, AL_START_HEAD);
|
|
||||||
node = NULL;
|
|
||||||
while((node = listNext(iter))){
|
|
||||||
char* moduleName = listNodeValue(node);
|
|
||||||
struct RedisModule* usingModule = dictFetchValue(modules, moduleName);
|
|
||||||
serverAssert(usingModule);
|
|
||||||
RemoveFromList(usingModule->usedBy, module->name);
|
|
||||||
}
|
|
||||||
listReleaseIterator(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load a module and initialize it. On success C_OK is returned, otherwise
|
/* Load a module and initialize it. On success C_OK is returned, otherwise
|
||||||
* C_ERR is returned. */
|
* C_ERR is returned. */
|
||||||
int moduleLoad(const char *path, void **module_argv, int module_argc) {
|
int moduleLoad(const char *path, void **module_argv, int module_argc) {
|
||||||
@ -4881,12 +4794,6 @@ int moduleUnload(sds name) {
|
|||||||
return REDISMODULE_ERR;
|
return REDISMODULE_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listLength(module->usedBy)) {
|
|
||||||
errno = EPERM;
|
|
||||||
return REDISMODULE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleUnregisterApi(module);
|
|
||||||
moduleUnregisterCommands(module);
|
moduleUnregisterCommands(module);
|
||||||
|
|
||||||
/* Remove any notification subscribers this module might have */
|
/* Remove any notification subscribers this module might have */
|
||||||
@ -4919,7 +4826,6 @@ void moduleCommand(client *c) {
|
|||||||
if (c->argc == 2 && !strcasecmp(subcmd,"help")) {
|
if (c->argc == 2 && !strcasecmp(subcmd,"help")) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"LIST -- Return a list of loaded modules.",
|
"LIST -- Return a list of loaded modules.",
|
||||||
"LISTAPI <module-name> -- Return a list of exported api.",
|
|
||||||
"LOAD <path> [arg ...] -- Load a module library from <path>.",
|
"LOAD <path> [arg ...] -- Load a module library from <path>.",
|
||||||
"UNLOAD <name> -- Unload a module.",
|
"UNLOAD <name> -- Unload a module.",
|
||||||
NULL
|
NULL
|
||||||
@ -4952,9 +4858,6 @@ NULL
|
|||||||
case EBUSY:
|
case EBUSY:
|
||||||
errmsg = "the module exports one or more module-side data types, can't unload";
|
errmsg = "the module exports one or more module-side data types, can't unload";
|
||||||
break;
|
break;
|
||||||
case EPERM:
|
|
||||||
errmsg = "the module api is used by other modules, please unload them first and try again.";
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
errmsg = "operation not possible.";
|
errmsg = "operation not possible.";
|
||||||
break;
|
break;
|
||||||
@ -4976,21 +4879,6 @@ NULL
|
|||||||
addReplyLongLong(c,module->ver);
|
addReplyLongLong(c,module->ver);
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
} else if (!strcasecmp(subcmd,"listapi") && c->argc == 3) {
|
|
||||||
char *moduleName = c->argv[2]->ptr;
|
|
||||||
struct RedisModule* module = dictFetchValue(modules, moduleName);
|
|
||||||
if(!module){
|
|
||||||
addReplyErrorFormat(c,"Error listing module api: no such module %s", moduleName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addReplyMultiBulkLen(c,listLength(module->exportedFunctions));
|
|
||||||
listIter *iter = listGetIterator(module->exportedFunctions, AL_START_HEAD);
|
|
||||||
listNode* node = NULL;
|
|
||||||
while((node = listNext(iter))){
|
|
||||||
char* functionName = listNodeValue(node);
|
|
||||||
addReplyBulkCString(c,functionName);
|
|
||||||
}
|
|
||||||
listReleaseIterator(iter);
|
|
||||||
} else {
|
} else {
|
||||||
addReplySubcommandSyntaxError(c);
|
addReplySubcommandSyntaxError(c);
|
||||||
return;
|
return;
|
||||||
@ -5006,7 +4894,6 @@ size_t moduleCount(void) {
|
|||||||
* file so that's easy to seek it to add new entries. */
|
* file so that's easy to seek it to add new entries. */
|
||||||
void moduleRegisterCoreAPI(void) {
|
void moduleRegisterCoreAPI(void) {
|
||||||
server.moduleapi = dictCreate(&moduleAPIDictType,NULL);
|
server.moduleapi = dictCreate(&moduleAPIDictType,NULL);
|
||||||
server.exportedapi = dictCreate(&moduleAPIDictType,NULL);
|
|
||||||
REGISTER_API(Alloc);
|
REGISTER_API(Alloc);
|
||||||
REGISTER_API(Calloc);
|
REGISTER_API(Calloc);
|
||||||
REGISTER_API(Realloc);
|
REGISTER_API(Realloc);
|
||||||
@ -5157,6 +5044,4 @@ void moduleRegisterCoreAPI(void) {
|
|||||||
REGISTER_API(DictPrev);
|
REGISTER_API(DictPrev);
|
||||||
REGISTER_API(DictCompareC);
|
REGISTER_API(DictCompareC);
|
||||||
REGISTER_API(DictCompare);
|
REGISTER_API(DictCompare);
|
||||||
REGISTER_API(RegisterApi);
|
|
||||||
REGISTER_API(GetExportedApi);
|
|
||||||
}
|
}
|
||||||
|
@ -332,8 +332,6 @@ void REDISMODULE_API_FUNC(RedisModule_GetRandomBytes)(unsigned char *dst, size_t
|
|||||||
void REDISMODULE_API_FUNC(RedisModule_GetRandomHexChars)(char *dst, size_t len);
|
void REDISMODULE_API_FUNC(RedisModule_GetRandomHexChars)(char *dst, size_t len);
|
||||||
void REDISMODULE_API_FUNC(RedisModule_SetDisconnectCallback)(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback);
|
void REDISMODULE_API_FUNC(RedisModule_SetDisconnectCallback)(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback);
|
||||||
void REDISMODULE_API_FUNC(RedisModule_SetClusterFlags)(RedisModuleCtx *ctx, uint64_t flags);
|
void REDISMODULE_API_FUNC(RedisModule_SetClusterFlags)(RedisModuleCtx *ctx, uint64_t flags);
|
||||||
int REDISMODULE_API_FUNC(RedisModule_RegisterApi)(RedisModuleCtx *ctx, const char *funcname, void *funcptr);
|
|
||||||
void* REDISMODULE_API_FUNC(RedisModule_GetExportedApi)(RedisModuleCtx *ctx, const char *funcname);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This is included inline inside each Redis module. */
|
/* This is included inline inside each Redis module. */
|
||||||
@ -494,8 +492,6 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
|
|||||||
REDISMODULE_GET_API(GetRandomBytes);
|
REDISMODULE_GET_API(GetRandomBytes);
|
||||||
REDISMODULE_GET_API(GetRandomHexChars);
|
REDISMODULE_GET_API(GetRandomHexChars);
|
||||||
REDISMODULE_GET_API(SetClusterFlags);
|
REDISMODULE_GET_API(SetClusterFlags);
|
||||||
REDISMODULE_GET_API(RegisterApi);
|
|
||||||
REDISMODULE_GET_API(GetExportedApi);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (RedisModule_IsModuleNameBusy && RedisModule_IsModuleNameBusy(name)) return REDISMODULE_ERR;
|
if (RedisModule_IsModuleNameBusy && RedisModule_IsModuleNameBusy(name)) return REDISMODULE_ERR;
|
||||||
|
@ -955,7 +955,6 @@ struct redisServer {
|
|||||||
int always_show_logo; /* Show logo even for non-stdout logging. */
|
int always_show_logo; /* Show logo even for non-stdout logging. */
|
||||||
/* Modules */
|
/* Modules */
|
||||||
dict *moduleapi; /* Exported APIs dictionary for modules. */
|
dict *moduleapi; /* Exported APIs dictionary for modules. */
|
||||||
dict *exportedapi; /* Api exported by other modules. */
|
|
||||||
list *loadmodule_queue; /* List of modules to load at startup. */
|
list *loadmodule_queue; /* List of modules to load at startup. */
|
||||||
int module_blocked_pipe[2]; /* Pipe used to awake the event loop if a
|
int module_blocked_pipe[2]; /* Pipe used to awake the event loop if a
|
||||||
client blocked on a module command needs
|
client blocked on a module command needs
|
||||||
|
Loading…
x
Reference in New Issue
Block a user