diff --git a/src/module.c b/src/module.c index 07f88eff56a1d9ad1fa209b638c461887e898eb3..36e23a47c11e90eaf8207a3de5ce8a5dcca233c0 100644 --- a/src/module.c +++ b/src/module.c @@ -2666,7 +2666,7 @@ void moduleTypeNameByID(char *name, uint64_t moduleid) { /* Register a new data type exported by the module. The parameters are the * following. Please for in depth documentation check the modules API - * documentation, especially the INTRO.md file. + * documentation, especially the TYPES.md file. * * * **name**: A 9 characters data type name that MUST be unique in the Redis * Modules ecosystem. Be creative... and there will be no collisions. Use @@ -2685,12 +2685,31 @@ void moduleTypeNameByID(char *name, uint64_t moduleid) { * still load old data produced by an older version if the rdb_load * callback is able to check the encver value and act accordingly. * The encver must be a positive value between 0 and 1023. + * * **typemethods_ptr** is a pointer to a RedisModuleTypeMethods structure + * that should be populated with the methods callbacks and structure + * version, like in the following example: + * + * RedisModuleTypeMethods tm = { + * .version = REDISMODULE_TYPE_METHOD_VERSION, + * .rdb_load = myType_RDBLoadCallBack, + * .rdb_save = myType_RDBSaveCallBack, + * .aof_rewrite = myType_AOFRewriteCallBack, + * .free = myType_FreeCallBack, + * + * // Optional fields + * .digest = myType_DigestCallBack, + * .mem_usage = myType_MemUsageCallBack, + * } + * * * **rdb_load**: A callback function pointer that loads data from RDB files. * * **rdb_save**: A callback function pointer that saves data to RDB files. * * **aof_rewrite**: A callback function pointer that rewrites data as commands. * * **digest**: A callback function pointer that is used for `DEBUG DIGEST`. * * **free**: A callback function pointer that can free a type value. * + * The **digest* and **mem_usage** methods should currently be omitted since + * they are not yet implemented inside the Redis modules core. + * * Note: the module name "AAAAAAAAA" is reserved and produces an error, it * happens to be pretty lame as well. * @@ -2709,19 +2728,33 @@ void moduleTypeNameByID(char *name, uint64_t moduleid) { * BalancedTreeType = RM_CreateDataType(...); * } */ -moduleType *RM_CreateDataType(RedisModuleCtx *ctx, const char *name, int encver, moduleTypeLoadFunc rdb_load, moduleTypeSaveFunc rdb_save, moduleTypeRewriteFunc aof_rewrite, moduleTypeDigestFunc digest, moduleTypeFreeFunc free) { +moduleType *RM_CreateDataType(RedisModuleCtx *ctx, const char *name, int encver, void *typemethods_ptr) { uint64_t id = moduleTypeEncodeId(name,encver); if (id == 0) return NULL; if (moduleTypeLookupModuleByName(name) != NULL) return NULL; - moduleType *mt = zmalloc(sizeof(*mt)); + long typemethods_version = ((long*)typemethods_ptr)[0]; + if (typemethods_version == 0) return NULL; + + struct typemethods { + uint64_t version; + moduleTypeLoadFunc rdb_load; + moduleTypeSaveFunc rdb_save; + moduleTypeRewriteFunc aof_rewrite; + moduleTypeDigestFunc digest; + moduleTypeMemUsageFunc mem_usage; + moduleTypeFreeFunc free; + } *tms = (struct typemethods*) typemethods_ptr; + + moduleType *mt = zcalloc(sizeof(*mt)); mt->id = id; mt->module = ctx->module; - mt->rdb_load = rdb_load; - mt->rdb_save = rdb_save; - mt->aof_rewrite = aof_rewrite; - mt->digest = digest; - mt->free = free; + mt->rdb_load = tms->rdb_load; + mt->rdb_save = tms->rdb_save; + mt->aof_rewrite = tms->aof_rewrite; + mt->mem_usage = tms->mem_usage; + mt->digest = tms->digest; + mt->free = tms->free; memcpy(mt->name,name,sizeof(mt->name)); listAddNodeTail(ctx->module->types,mt); return mt; diff --git a/src/modules/hellotype.c b/src/modules/hellotype.c index 535eb88e1f2f0d5ffc1be0ece64df7a03766f255..02a5bb477e917bf7327ef3ef269369d566d5549e 100644 --- a/src/modules/hellotype.c +++ b/src/modules/hellotype.c @@ -245,7 +245,15 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) if (RedisModule_Init(ctx,"hellotype",1,REDISMODULE_APIVER_1) == REDISMODULE_ERR) return REDISMODULE_ERR; - HelloType = RedisModule_CreateDataType(ctx,"hellotype",0,HelloTypeRdbLoad,HelloTypeRdbSave,HelloTypeAofRewrite,HelloTypeDigest,HelloTypeFree); + RedisModuleTypeMethods tm = { + .version = REDISMODULE_TYPE_METHOD_VERSION, + .rdb_load = HelloTypeRdbLoad, + .rdb_save = HelloTypeRdbSave, + .aof_rewrite = HelloTypeAofRewrite, + .free = HelloTypeFree + }; + + HelloType = RedisModule_CreateDataType(ctx,"hellotype",0,&tm); if (HelloType == NULL) return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"hellotype.insert", diff --git a/src/redismodule.h b/src/redismodule.h index a07c09488367a038b8e06874679170910bce2296..4ecf3c8f284d443246389df154616b3493d77494 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -91,9 +91,21 @@ typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, RedisModuleString **argv typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver); typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value); typedef void (*RedisModuleTypeRewriteFunc)(RedisModuleIO *aof, RedisModuleString *key, void *value); +typedef size_t (*RedisModuleTypeMemUsageFunc)(void *value); typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value); typedef void (*RedisModuleTypeFreeFunc)(void *value); +#define REDISMODULE_TYPE_METHOD_VERSION 1 +typedef struct RedisModuleTypeMethods { + uint64_t version; + RedisModuleTypeLoadFunc rdb_load; + RedisModuleTypeSaveFunc rdb_save; + RedisModuleTypeRewriteFunc aof_rewrite; + RedisModuleTypeMemUsageFunc mem_usage; + RedisModuleTypeRewriteFunc digest; + RedisModuleTypeFreeFunc free; +} RedisModuleTypeMethods; + #define REDISMODULE_GET_API(name) \ RedisModule_GetApi("RedisModule_" #name, ((void **)&RedisModule_ ## name)) @@ -172,7 +184,7 @@ int REDISMODULE_API_FUNC(RedisModule_IsKeysPositionRequest)(RedisModuleCtx *ctx) void REDISMODULE_API_FUNC(RedisModule_KeyAtPos)(RedisModuleCtx *ctx, int pos); unsigned long long REDISMODULE_API_FUNC(RedisModule_GetClientId)(RedisModuleCtx *ctx); void *REDISMODULE_API_FUNC(RedisModule_PoolAlloc)(RedisModuleCtx *ctx, size_t bytes); -RedisModuleType *REDISMODULE_API_FUNC(RedisModule_CreateDataType)(RedisModuleCtx *ctx, const char *name, int encver, RedisModuleTypeLoadFunc rdb_load, RedisModuleTypeSaveFunc rdb_save, RedisModuleTypeRewriteFunc aof_rewrite, RedisModuleTypeDigestFunc digest, RedisModuleTypeFreeFunc free); +RedisModuleType *REDISMODULE_API_FUNC(RedisModule_CreateDataType)(RedisModuleCtx *ctx, const char *name, int encver, RedisModuleTypeMethods *typemethods); int REDISMODULE_API_FUNC(RedisModule_ModuleTypeSetValue)(RedisModuleKey *key, RedisModuleType *mt, void *value); RedisModuleType *REDISMODULE_API_FUNC(RedisModule_ModuleTypeGetType)(RedisModuleKey *key); void *REDISMODULE_API_FUNC(RedisModule_ModuleTypeGetValue)(RedisModuleKey *key); diff --git a/src/server.h b/src/server.h index b7f9099334702bab972a07d680e5f4b6b8e8d4aa..1ad862003f0eed73273240c8fda3fc5acf6d37b8 100644 --- a/src/server.h +++ b/src/server.h @@ -476,6 +476,7 @@ typedef void *(*moduleTypeLoadFunc)(struct RedisModuleIO *io, int encver); typedef void (*moduleTypeSaveFunc)(struct RedisModuleIO *io, void *value); typedef void (*moduleTypeRewriteFunc)(struct RedisModuleIO *io, struct redisObject *key, void *value); typedef void (*moduleTypeDigestFunc)(struct RedisModuleDigest *digest, void *value); +typedef size_t (*moduleTypeMemUsageFunc)(void *value); typedef void (*moduleTypeFreeFunc)(void *value); /* The module type, which is referenced in each value of a given type, defines @@ -486,6 +487,7 @@ typedef struct RedisModuleType { moduleTypeLoadFunc rdb_load; moduleTypeSaveFunc rdb_save; moduleTypeRewriteFunc aof_rewrite; + moduleTypeMemUsageFunc mem_usage; moduleTypeDigestFunc digest; moduleTypeFreeFunc free; char name[10]; /* 9 bytes name + null term. Charset: A-Z a-z 0-9 _- */