diff options
author | antirez <antirez@gmail.com> | 2016-10-06 17:05:38 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2016-10-06 17:09:26 +0200 |
commit | 152c1b6802b88fbad0113adb97500d92a84e3c63 (patch) | |
tree | 6edefb73e83484449e5854f36ac166f9083fc1fa | |
parent | 72279e3ea4e8a8d19005b91b0bf7ee7a8ecc87fc (diff) | |
download | redis-152c1b6802b88fbad0113adb97500d92a84e3c63.tar.gz |
Module: Ability to get context from IO context.
It was noted by @dvirsky that it is not possible to use string functions
when writing the AOF file. This sometimes is critical since the command
rewriting may need to be built in the context of the AOF callback, and
without access to the context, and the limited types that the AOF
production functions will accept, this can be an issue.
Moreover there are other needs that we can't anticipate regarding the
ability to use Redis Modules APIs using the context in order to build
representations to emit AOF / RDB.
Because of this a new API was added that allows the user to get a
temporary context from the IO context. The context is auto released
if obtained when the RDB / AOF callback returns.
Calling multiple time the function to get the context, always returns
the same one, since it is invalid to have more than a single context.
-rw-r--r-- | src/aof.c | 4 | ||||
-rw-r--r-- | src/module.c | 15 | ||||
-rw-r--r-- | src/rdb.c | 4 | ||||
-rw-r--r-- | src/redismodule.h | 3 | ||||
-rw-r--r-- | src/server.h | 4 |
5 files changed, 30 insertions, 0 deletions
@@ -1023,6 +1023,10 @@ int rewriteModuleObject(rio *r, robj *key, robj *o) { moduleType *mt = mv->type; moduleInitIOContext(io,mt,r); mt->aof_rewrite(&io,key,mv->value); + if (io.ctx) { + moduleFreeContext(io.ctx); + zfree(io.ctx); + } return io.error ? 0 : 1; } diff --git a/src/module.c b/src/module.c index c339303b5..742d9b974 100644 --- a/src/module.c +++ b/src/module.c @@ -2959,6 +2959,20 @@ void RM_EmitAOF(RedisModuleIO *io, const char *cmdname, const char *fmt, ...) { } /* -------------------------------------------------------------------------- + * IO context handling + * -------------------------------------------------------------------------- */ + +RedisModuleCtx *RM_GetContextFromIO(RedisModuleIO *io) { + if (io->ctx) return io->ctx; /* Can't have more than one... */ + RedisModuleCtx ctxtemplate = REDISMODULE_CTX_INIT; + io->ctx = zmalloc(sizeof(*io)); + *(io->ctx) = ctxtemplate; + io->ctx->module = io->type->module; + io->ctx->client = NULL; + return io->ctx; +} + +/* -------------------------------------------------------------------------- * Logging * -------------------------------------------------------------------------- */ @@ -3342,4 +3356,5 @@ void moduleRegisterCoreAPI(void) { REGISTER_API(StringAppendBuffer); REGISTER_API(RetainString); REGISTER_API(StringCompare); + REGISTER_API(GetContextFromIO); } @@ -770,6 +770,10 @@ ssize_t rdbSaveObject(rio *rdb, robj *o) { /* Then write the module-specific representation. */ mt->rdb_save(&io,mv->value); + if (io.ctx) { + moduleFreeContext(io.ctx); + zfree(io.ctx); + } return io.error ? -1 : (ssize_t)io.bytes; } else { serverPanic("Unknown object type"); diff --git a/src/redismodule.h b/src/redismodule.h index 346110090..9b3c061ac 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -191,6 +191,7 @@ void REDISMODULE_API_FUNC(RedisModule_LogIOError)(RedisModuleIO *io, const char int REDISMODULE_API_FUNC(RedisModule_StringAppendBuffer)(RedisModuleCtx *ctx, RedisModuleString *str, const char *buf, size_t len); void REDISMODULE_API_FUNC(RedisModule_RetainString)(RedisModuleCtx *ctx, RedisModuleString *str); int REDISMODULE_API_FUNC(RedisModule_StringCompare)(RedisModuleString *a, RedisModuleString *b); +RedisModuleCtx *REDISMODULE_API_FUNC(RM_GetContextFromIO)(RedisModuleIO *io); /* This is included inline inside each Redis module. */ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) __attribute__((unused)); @@ -291,6 +292,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(StringAppendBuffer); REDISMODULE_GET_API(RetainString); REDISMODULE_GET_API(StringCompare); + REDISMODULE_GET_API(GetIOContext); + REDISMODULE_GET_API(FreeIOContext); RedisModule_SetModuleAttribs(ctx,name,ver,apiver); return REDISMODULE_OK; diff --git a/src/server.h b/src/server.h index 8aad8f983..21e32824d 100644 --- a/src/server.h +++ b/src/server.h @@ -463,6 +463,7 @@ typedef long long mstime_t; /* millisecond time type. */ struct RedisModule; struct RedisModuleIO; struct RedisModuleDigest; +struct RedisModuleCtx; struct redisObject; /* Each module type implementation should export a set of methods in order @@ -516,6 +517,7 @@ typedef struct RedisModuleIO { rio *rio; /* Rio stream. */ moduleType *type; /* Module type doing the operation. */ int error; /* True if error condition happened. */ + struct RedisModuleCtx *ctx; /* Optional context, via GetIOContext() call. */ } RedisModuleIO; #define moduleInitIOContext(iovar,mtype,rioptr) do { \ @@ -523,6 +525,7 @@ typedef struct RedisModuleIO { iovar.type = mtype; \ iovar.bytes = 0; \ iovar.error = 0; \ + iovar.ctx = NULL; \ } while(0); /* Objects encoding. Some kind of objects like Strings and Hashes can be @@ -1222,6 +1225,7 @@ void moduleLoadFromQueue(void); int *moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, int *numkeys); moduleType *moduleTypeLookupModuleByID(uint64_t id); void moduleTypeNameByID(char *name, uint64_t moduleid); +void moduleFreeContext(struct RedisModuleCtx *ctx); /* Utils */ long long ustime(void); |