Merge pull request #3293 from yossigo/module_config

Allow passing arguments to modules on load.
This commit is contained in:
Salvatore Sanfilippo 2016-06-13 09:31:59 +02:00 committed by GitHub
commit e8d5387a44
3 changed files with 40 additions and 13 deletions

View File

@ -153,6 +153,19 @@ void resetServerSaveParams(void) {
server.saveparamslen = 0; server.saveparamslen = 0;
} }
void queueLoadModule(sds path, sds *argv, int argc)
{
struct loadmodule *loadmod = zmalloc(sizeof(struct loadmodule)+sizeof(robj*)*argc);
int i;
loadmod->path = sdsnew(path);
loadmod->argc = argc;
for (i = 0; i < argc; i++) {
loadmod->argv[i] = createStringObject(argv[i],sdslen(argv[i]));
}
listAddNodeTail(server.loadmodule_queue,loadmod);
}
void loadServerConfigFromString(char *config) { void loadServerConfigFromString(char *config) {
char *err = NULL; char *err = NULL;
int linenum = 0, totlines, i; int linenum = 0, totlines, i;
@ -632,8 +645,8 @@ void loadServerConfigFromString(char *config) {
"Allowed values: 'upstart', 'systemd', 'auto', or 'no'"; "Allowed values: 'upstart', 'systemd', 'auto', or 'no'";
goto loaderr; goto loaderr;
} }
} else if (!strcasecmp(argv[0],"loadmodule") && argc == 2) { } else if (!strcasecmp(argv[0],"loadmodule") && argc >= 2) {
listAddNodeTail(server.loadmodule_queue,sdsnew(argv[1])); queueLoadModule(argv[1],&argv[2],argc-2);
} else if (!strcasecmp(argv[0],"sentinel")) { } else if (!strcasecmp(argv[0],"sentinel")) {
/* argc == 1 is handled by main() as we need to enter the sentinel /* argc == 1 is handled by main() as we need to enter the sentinel
* mode ASAP. */ * mode ASAP. */

View File

@ -2897,11 +2897,11 @@ void moduleLoadFromQueue(void) {
listRewind(server.loadmodule_queue,&li); listRewind(server.loadmodule_queue,&li);
while((ln = listNext(&li))) { while((ln = listNext(&li))) {
sds modulepath = ln->value; struct loadmodule *loadmod = ln->value;
if (moduleLoad(modulepath) == C_ERR) { if (moduleLoad(loadmod->path,(void **)loadmod->argv,loadmod->argc) == C_ERR) {
serverLog(LL_WARNING, serverLog(LL_WARNING,
"Can't load module from %s: server aborting", "Can't load module from %s: server aborting",
modulepath); loadmod->path);
exit(1); exit(1);
} }
} }
@ -2915,8 +2915,8 @@ void moduleFreeModuleStructure(struct RedisModule *module) {
/* 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) { int moduleLoad(const char *path, void **module_argv, int module_argc) {
int (*onload)(void *); int (*onload)(void *, void **, int);
void *handle; void *handle;
RedisModuleCtx ctx = REDISMODULE_CTX_INIT; RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
@ -2925,14 +2925,14 @@ int moduleLoad(const char *path) {
serverLog(LL_WARNING, "Module %s failed to load: %s", path, dlerror()); serverLog(LL_WARNING, "Module %s failed to load: %s", path, dlerror());
return C_ERR; return C_ERR;
} }
onload = (int (*)(void *))(unsigned long) dlsym(handle,"RedisModule_OnLoad"); onload = (int (*)(void *, void **, int))(unsigned long) dlsym(handle,"RedisModule_OnLoad");
if (onload == NULL) { if (onload == NULL) {
serverLog(LL_WARNING, serverLog(LL_WARNING,
"Module %s does not export RedisModule_OnLoad() " "Module %s does not export RedisModule_OnLoad() "
"symbol. Module not loaded.",path); "symbol. Module not loaded.",path);
return C_ERR; return C_ERR;
} }
if (onload((void*)&ctx) == REDISMODULE_ERR) { if (onload((void*)&ctx,module_argv,module_argc) == REDISMODULE_ERR) {
if (ctx.module) moduleFreeModuleStructure(ctx.module); if (ctx.module) moduleFreeModuleStructure(ctx.module);
dlclose(handle); dlclose(handle);
serverLog(LL_WARNING, serverLog(LL_WARNING,
@ -3006,12 +3006,20 @@ int moduleUnload(sds name) {
/* Redis MODULE command. /* Redis MODULE command.
* *
* MODULE LOAD <path> */ * MODULE LOAD <path> [args...] */
void moduleCommand(client *c) { void moduleCommand(client *c) {
char *subcmd = c->argv[1]->ptr; char *subcmd = c->argv[1]->ptr;
if (!strcasecmp(subcmd,"load") && c->argc == 3) { if (!strcasecmp(subcmd,"load") && c->argc >= 3) {
if (moduleLoad(c->argv[2]->ptr) == C_OK) robj **argv = NULL;
int argc = 0;
if (c->argc > 3) {
argc = c->argc - 3;
argv = &c->argv[3];
}
if (moduleLoad(c->argv[2]->ptr,(void **)argv,argc) == C_OK)
addReply(c,shared.ok); addReply(c,shared.ok);
else else
addReplyError(c, addReplyError(c,

View File

@ -683,6 +683,12 @@ struct saveparam {
int changes; int changes;
}; };
struct loadmodule {
sds path;
int argc;
robj *argv[];
};
struct sharedObjectsStruct { struct sharedObjectsStruct {
robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *cnegone, *pong, *space, robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *cnegone, *pong, *space,
*colon, *nullbulk, *nullmultibulk, *queued, *colon, *nullbulk, *nullmultibulk, *queued,
@ -1156,7 +1162,7 @@ extern dictType modulesDictType;
/* Modules */ /* Modules */
void moduleInitModulesSystem(void); void moduleInitModulesSystem(void);
int moduleLoad(const char *path); int moduleLoad(const char *path, void **argv, int argc);
void moduleLoadFromQueue(void); void moduleLoadFromQueue(void);
int *moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, int *numkeys); int *moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);
moduleType *moduleTypeLookupModuleByID(uint64_t id); moduleType *moduleTypeLookupModuleByID(uint64_t id);