mirror of https://github.com/redis/redis.git
				
				
				
			
		
			
				
	
	
		
			260 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			260 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
| #include "redismodule.h"
 | |
| 
 | |
| #include <string.h>
 | |
| #include <assert.h>
 | |
| 
 | |
| /* Module configuration, save aux or not? */
 | |
| long long conf_aux_count = 0;
 | |
| 
 | |
| /* Registered type */
 | |
| RedisModuleType *testrdb_type = NULL;
 | |
| 
 | |
| /* Global values to store and persist to aux */
 | |
| RedisModuleString *before_str = NULL;
 | |
| RedisModuleString *after_str = NULL;
 | |
| 
 | |
| void *testrdb_type_load(RedisModuleIO *rdb, int encver) {
 | |
|     int count = RedisModule_LoadSigned(rdb);
 | |
|     RedisModuleString *str = RedisModule_LoadString(rdb);
 | |
|     float f = RedisModule_LoadFloat(rdb);
 | |
|     long double ld = RedisModule_LoadLongDouble(rdb);
 | |
|     if (RedisModule_IsIOError(rdb)) {
 | |
|         RedisModuleCtx *ctx = RedisModule_GetContextFromIO(rdb);
 | |
|         if (str)
 | |
|             RedisModule_FreeString(ctx, str);
 | |
|         return NULL;
 | |
|     }
 | |
|     /* Using the values only after checking for io errors. */
 | |
|     assert(count==1);
 | |
|     assert(encver==1);
 | |
|     assert(f==1.5f);
 | |
|     assert(ld==0.333333333333333333L);
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| void testrdb_type_save(RedisModuleIO *rdb, void *value) {
 | |
|     RedisModuleString *str = (RedisModuleString*)value;
 | |
|     RedisModule_SaveSigned(rdb, 1);
 | |
|     RedisModule_SaveString(rdb, str);
 | |
|     RedisModule_SaveFloat(rdb, 1.5);
 | |
|     RedisModule_SaveLongDouble(rdb, 0.333333333333333333L);
 | |
| }
 | |
| 
 | |
| void testrdb_aux_save(RedisModuleIO *rdb, int when) {
 | |
|     if (conf_aux_count==1) assert(when == REDISMODULE_AUX_AFTER_RDB);
 | |
|     if (conf_aux_count==0) assert(0);
 | |
|     if (when == REDISMODULE_AUX_BEFORE_RDB) {
 | |
|         if (before_str) {
 | |
|             RedisModule_SaveSigned(rdb, 1);
 | |
|             RedisModule_SaveString(rdb, before_str);
 | |
|         } else {
 | |
|             RedisModule_SaveSigned(rdb, 0);
 | |
|         }
 | |
|     } else {
 | |
|         if (after_str) {
 | |
|             RedisModule_SaveSigned(rdb, 1);
 | |
|             RedisModule_SaveString(rdb, after_str);
 | |
|         } else {
 | |
|             RedisModule_SaveSigned(rdb, 0);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| int testrdb_aux_load(RedisModuleIO *rdb, int encver, int when) {
 | |
|     assert(encver == 1);
 | |
|     if (conf_aux_count==1) assert(when == REDISMODULE_AUX_AFTER_RDB);
 | |
|     if (conf_aux_count==0) assert(0);
 | |
|     RedisModuleCtx *ctx = RedisModule_GetContextFromIO(rdb);
 | |
|     if (when == REDISMODULE_AUX_BEFORE_RDB) {
 | |
|         if (before_str)
 | |
|             RedisModule_FreeString(ctx, before_str);
 | |
|         before_str = NULL;
 | |
|         int count = RedisModule_LoadSigned(rdb);
 | |
|         if (RedisModule_IsIOError(rdb))
 | |
|             return REDISMODULE_ERR;
 | |
|         if (count)
 | |
|             before_str = RedisModule_LoadString(rdb);
 | |
|     } else {
 | |
|         if (after_str)
 | |
|             RedisModule_FreeString(ctx, after_str);
 | |
|         after_str = NULL;
 | |
|         int count = RedisModule_LoadSigned(rdb);
 | |
|         if (RedisModule_IsIOError(rdb))
 | |
|             return REDISMODULE_ERR;
 | |
|         if (count)
 | |
|             after_str = RedisModule_LoadString(rdb);
 | |
|     }
 | |
|     if (RedisModule_IsIOError(rdb))
 | |
|         return REDISMODULE_ERR;
 | |
|     return REDISMODULE_OK;
 | |
| }
 | |
| 
 | |
| void testrdb_type_free(void *value) {
 | |
|     if (value)
 | |
|         RedisModule_FreeString(NULL, (RedisModuleString*)value);
 | |
| }
 | |
| 
 | |
| int testrdb_set_before(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
 | |
| {
 | |
|     if (argc != 2) {
 | |
|         RedisModule_WrongArity(ctx);
 | |
|         return REDISMODULE_OK;
 | |
|     }
 | |
| 
 | |
|     if (before_str)
 | |
|         RedisModule_FreeString(ctx, before_str);
 | |
|     before_str = argv[1];
 | |
|     RedisModule_RetainString(ctx, argv[1]);
 | |
|     RedisModule_ReplyWithLongLong(ctx, 1);
 | |
|     return REDISMODULE_OK;
 | |
| }
 | |
| 
 | |
| int testrdb_get_before(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
 | |
| {
 | |
|     REDISMODULE_NOT_USED(argv);
 | |
|     if (argc != 1){
 | |
|         RedisModule_WrongArity(ctx);
 | |
|         return REDISMODULE_OK;
 | |
|     }
 | |
|     if (before_str)
 | |
|         RedisModule_ReplyWithString(ctx, before_str);
 | |
|     else
 | |
|         RedisModule_ReplyWithStringBuffer(ctx, "", 0);
 | |
|     return REDISMODULE_OK;
 | |
| }
 | |
| 
 | |
| int testrdb_set_after(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
 | |
| {
 | |
|     if (argc != 2){
 | |
|         RedisModule_WrongArity(ctx);
 | |
|         return REDISMODULE_OK;
 | |
|     }
 | |
| 
 | |
|     if (after_str)
 | |
|         RedisModule_FreeString(ctx, after_str);
 | |
|     after_str = argv[1];
 | |
|     RedisModule_RetainString(ctx, argv[1]);
 | |
|     RedisModule_ReplyWithLongLong(ctx, 1);
 | |
|     return REDISMODULE_OK;
 | |
| }
 | |
| 
 | |
| int testrdb_get_after(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
 | |
| {
 | |
|     REDISMODULE_NOT_USED(argv);
 | |
|     if (argc != 1){
 | |
|         RedisModule_WrongArity(ctx);
 | |
|         return REDISMODULE_OK;
 | |
|     }
 | |
|     if (after_str)
 | |
|         RedisModule_ReplyWithString(ctx, after_str);
 | |
|     else
 | |
|         RedisModule_ReplyWithStringBuffer(ctx, "", 0);
 | |
|     return REDISMODULE_OK;
 | |
| }
 | |
| 
 | |
| int testrdb_set_key(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
 | |
| {
 | |
|     if (argc != 3){
 | |
|         RedisModule_WrongArity(ctx);
 | |
|         return REDISMODULE_OK;
 | |
|     }
 | |
| 
 | |
|     RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
 | |
|     RedisModuleString *str = RedisModule_ModuleTypeGetValue(key);
 | |
|     if (str)
 | |
|         RedisModule_FreeString(ctx, str);
 | |
|     RedisModule_ModuleTypeSetValue(key, testrdb_type, argv[2]);
 | |
|     RedisModule_RetainString(ctx, argv[2]);
 | |
|     RedisModule_CloseKey(key);
 | |
|     RedisModule_ReplyWithLongLong(ctx, 1);
 | |
|     return REDISMODULE_OK;
 | |
| }
 | |
| 
 | |
| int testrdb_get_key(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
 | |
| {
 | |
|     if (argc != 2){
 | |
|         RedisModule_WrongArity(ctx);
 | |
|         return REDISMODULE_OK;
 | |
|     }
 | |
| 
 | |
|     RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
 | |
|     RedisModuleString *str = RedisModule_ModuleTypeGetValue(key);
 | |
|     RedisModule_CloseKey(key);
 | |
|     RedisModule_ReplyWithString(ctx, str);
 | |
|     return REDISMODULE_OK;
 | |
| }
 | |
| 
 | |
| int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
 | |
|     REDISMODULE_NOT_USED(argv);
 | |
|     REDISMODULE_NOT_USED(argc);
 | |
| 
 | |
|     if (RedisModule_Init(ctx,"testrdb",1,REDISMODULE_APIVER_1) == REDISMODULE_ERR)
 | |
|         return REDISMODULE_ERR;
 | |
| 
 | |
|     RedisModule_SetModuleOptions(ctx, REDISMODULE_OPTIONS_HANDLE_IO_ERRORS);
 | |
| 
 | |
|     if (argc > 0)
 | |
|         RedisModule_StringToLongLong(argv[0], &conf_aux_count);
 | |
| 
 | |
|     if (conf_aux_count==0) {
 | |
|         RedisModuleTypeMethods datatype_methods = {
 | |
|             .version = 1,
 | |
|             .rdb_load = testrdb_type_load,
 | |
|             .rdb_save = testrdb_type_save,
 | |
|             .aof_rewrite = NULL,
 | |
|             .digest = NULL,
 | |
|             .free = testrdb_type_free,
 | |
|         };
 | |
| 
 | |
|         testrdb_type = RedisModule_CreateDataType(ctx, "test__rdb", 1, &datatype_methods);
 | |
|         if (testrdb_type == NULL)
 | |
|             return REDISMODULE_ERR;
 | |
|     } else {
 | |
|         RedisModuleTypeMethods datatype_methods = {
 | |
|             .version = REDISMODULE_TYPE_METHOD_VERSION,
 | |
|             .rdb_load = testrdb_type_load,
 | |
|             .rdb_save = testrdb_type_save,
 | |
|             .aof_rewrite = NULL,
 | |
|             .digest = NULL,
 | |
|             .free = testrdb_type_free,
 | |
|             .aux_load = testrdb_aux_load,
 | |
|             .aux_save = testrdb_aux_save,
 | |
|             .aux_save_triggers = (conf_aux_count == 1 ?
 | |
|                                   REDISMODULE_AUX_AFTER_RDB :
 | |
|                                   REDISMODULE_AUX_BEFORE_RDB | REDISMODULE_AUX_AFTER_RDB)
 | |
|         };
 | |
| 
 | |
|         testrdb_type = RedisModule_CreateDataType(ctx, "test__rdb", 1, &datatype_methods);
 | |
|         if (testrdb_type == NULL)
 | |
|             return REDISMODULE_ERR;
 | |
|     }
 | |
| 
 | |
|     if (RedisModule_CreateCommand(ctx,"testrdb.set.before", testrdb_set_before,"deny-oom",0,0,0) == REDISMODULE_ERR)
 | |
|         return REDISMODULE_ERR;
 | |
| 
 | |
|     if (RedisModule_CreateCommand(ctx,"testrdb.get.before", testrdb_get_before,"",0,0,0) == REDISMODULE_ERR)
 | |
|         return REDISMODULE_ERR;
 | |
| 
 | |
|     if (RedisModule_CreateCommand(ctx,"testrdb.set.after", testrdb_set_after,"deny-oom",0,0,0) == REDISMODULE_ERR)
 | |
|         return REDISMODULE_ERR;
 | |
| 
 | |
|     if (RedisModule_CreateCommand(ctx,"testrdb.get.after", testrdb_get_after,"",0,0,0) == REDISMODULE_ERR)
 | |
|         return REDISMODULE_ERR;
 | |
| 
 | |
|     if (RedisModule_CreateCommand(ctx,"testrdb.set.key", testrdb_set_key,"deny-oom",1,1,1) == REDISMODULE_ERR)
 | |
|         return REDISMODULE_ERR;
 | |
| 
 | |
|     if (RedisModule_CreateCommand(ctx,"testrdb.get.key", testrdb_get_key,"",1,1,1) == REDISMODULE_ERR)
 | |
|         return REDISMODULE_ERR;
 | |
| 
 | |
|     return REDISMODULE_OK;
 | |
| }
 | |
| 
 | |
| int RedisModule_OnUnload(RedisModuleCtx *ctx) {
 | |
|     if (before_str)
 | |
|         RedisModule_FreeString(ctx, before_str);
 | |
|     if (after_str)
 | |
|         RedisModule_FreeString(ctx, after_str);
 | |
|     return REDISMODULE_OK;
 | |
| }
 |