123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /* This module current tests a small subset but should be extended in the future
- * for general ModuleDataType coverage.
- */
- #include "redismodule.h"
- static RedisModuleType *datatype = NULL;
- typedef struct {
- long long intval;
- RedisModuleString *strval;
- } DataType;
- static void *datatype_load(RedisModuleIO *io, int encver) {
- (void) encver;
- int intval = RedisModule_LoadSigned(io);
- if (RedisModule_IsIOError(io)) return NULL;
- RedisModuleString *strval = RedisModule_LoadString(io);
- if (RedisModule_IsIOError(io)) return NULL;
- DataType *dt = (DataType *) RedisModule_Alloc(sizeof(DataType));
- dt->intval = intval;
- dt->strval = strval;
- return dt;
- }
- static void datatype_save(RedisModuleIO *io, void *value) {
- DataType *dt = (DataType *) value;
- RedisModule_SaveSigned(io, dt->intval);
- RedisModule_SaveString(io, dt->strval);
- }
- static void datatype_free(void *value) {
- if (value) {
- DataType *dt = (DataType *) value;
- if (dt->strval) RedisModule_FreeString(NULL, dt->strval);
- RedisModule_Free(dt);
- }
- }
- static void *datatype_copy(RedisModuleString *fromkey, RedisModuleString *tokey, const void *value) {
- const DataType *old = value;
- /* Answers to ultimate questions cannot be copied! */
- if (old->intval == 42)
- return NULL;
- DataType *new = (DataType *) RedisModule_Alloc(sizeof(DataType));
- new->intval = old->intval;
- new->strval = RedisModule_CreateStringFromString(NULL, old->strval);
- /* Breaking the rules here! We return a copy that also includes traces
- * of fromkey/tokey to confirm we get what we expect.
- */
- size_t len;
- const char *str = RedisModule_StringPtrLen(fromkey, &len);
- RedisModule_StringAppendBuffer(NULL, new->strval, "/", 1);
- RedisModule_StringAppendBuffer(NULL, new->strval, str, len);
- RedisModule_StringAppendBuffer(NULL, new->strval, "/", 1);
- str = RedisModule_StringPtrLen(tokey, &len);
- RedisModule_StringAppendBuffer(NULL, new->strval, str, len);
- return new;
- }
- static int datatype_set(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 4) {
- RedisModule_WrongArity(ctx);
- return REDISMODULE_OK;
- }
- long long intval;
- if (RedisModule_StringToLongLong(argv[2], &intval) != REDISMODULE_OK) {
- RedisModule_ReplyWithError(ctx, "Invalid integr value");
- return REDISMODULE_OK;
- }
- RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
- DataType *dt = RedisModule_Calloc(sizeof(DataType), 1);
- dt->intval = intval;
- dt->strval = argv[3];
- RedisModule_RetainString(ctx, dt->strval);
- RedisModule_ModuleTypeSetValue(key, datatype, dt);
- RedisModule_CloseKey(key);
- RedisModule_ReplyWithSimpleString(ctx, "OK");
- return REDISMODULE_OK;
- }
- static int datatype_restore(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 3) {
- RedisModule_WrongArity(ctx);
- return REDISMODULE_OK;
- }
- DataType *dt = RedisModule_LoadDataTypeFromString(argv[2], datatype);
- if (!dt) {
- RedisModule_ReplyWithError(ctx, "Invalid data");
- return REDISMODULE_OK;
- }
- RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
- RedisModule_ModuleTypeSetValue(key, datatype, dt);
- RedisModule_CloseKey(key);
- RedisModule_ReplyWithSimpleString(ctx, "OK");
- return REDISMODULE_OK;
- }
- static int datatype_get(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 2) {
- RedisModule_WrongArity(ctx);
- return REDISMODULE_OK;
- }
- RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
- DataType *dt = RedisModule_ModuleTypeGetValue(key);
- RedisModule_CloseKey(key);
- if (!dt) {
- RedisModule_ReplyWithNullArray(ctx);
- } else {
- RedisModule_ReplyWithArray(ctx, 2);
- RedisModule_ReplyWithLongLong(ctx, dt->intval);
- RedisModule_ReplyWithString(ctx, dt->strval);
- }
- return REDISMODULE_OK;
- }
- static int datatype_dump(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 2) {
- RedisModule_WrongArity(ctx);
- return REDISMODULE_OK;
- }
- RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
- DataType *dt = RedisModule_ModuleTypeGetValue(key);
- RedisModule_CloseKey(key);
- RedisModuleString *reply = RedisModule_SaveDataTypeToString(ctx, dt, datatype);
- if (!reply) {
- RedisModule_ReplyWithError(ctx, "Failed to save");
- return REDISMODULE_OK;
- }
- RedisModule_ReplyWithString(ctx, reply);
- RedisModule_FreeString(ctx, reply);
- return REDISMODULE_OK;
- }
- static int datatype_swap(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 3) {
- RedisModule_WrongArity(ctx);
- return REDISMODULE_OK;
- }
- RedisModuleKey *a = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
- RedisModuleKey *b = RedisModule_OpenKey(ctx, argv[2], REDISMODULE_WRITE);
- void *val = RedisModule_ModuleTypeGetValue(a);
- int error = (RedisModule_ModuleTypeReplaceValue(b, datatype, val, &val) == REDISMODULE_ERR ||
- RedisModule_ModuleTypeReplaceValue(a, datatype, val, NULL) == REDISMODULE_ERR);
- if (!error)
- RedisModule_ReplyWithSimpleString(ctx, "OK");
- else
- RedisModule_ReplyWithError(ctx, "ERR failed");
- RedisModule_CloseKey(a);
- RedisModule_CloseKey(b);
- return REDISMODULE_OK;
- }
- int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- REDISMODULE_NOT_USED(argv);
- REDISMODULE_NOT_USED(argc);
- if (RedisModule_Init(ctx,"datatype",1,REDISMODULE_APIVER_1) == REDISMODULE_ERR)
- return REDISMODULE_ERR;
- RedisModule_SetModuleOptions(ctx, REDISMODULE_OPTIONS_HANDLE_IO_ERRORS);
- RedisModuleTypeMethods datatype_methods = {
- .version = REDISMODULE_TYPE_METHOD_VERSION,
- .rdb_load = datatype_load,
- .rdb_save = datatype_save,
- .free = datatype_free,
- .copy = datatype_copy
- };
- datatype = RedisModule_CreateDataType(ctx, "test___dt", 1, &datatype_methods);
- if (datatype == NULL)
- return REDISMODULE_ERR;
- if (RedisModule_CreateCommand(ctx,"datatype.set", datatype_set,"deny-oom",1,1,1) == REDISMODULE_ERR)
- return REDISMODULE_ERR;
- if (RedisModule_CreateCommand(ctx,"datatype.get", datatype_get,"",1,1,1) == REDISMODULE_ERR)
- return REDISMODULE_ERR;
- if (RedisModule_CreateCommand(ctx,"datatype.restore", datatype_restore,"deny-oom",1,1,1) == REDISMODULE_ERR)
- return REDISMODULE_ERR;
- if (RedisModule_CreateCommand(ctx,"datatype.dump", datatype_dump,"",1,1,1) == REDISMODULE_ERR)
- return REDISMODULE_ERR;
- if (RedisModule_CreateCommand(ctx,"datatype.swap", datatype_swap,"",1,1,1) == REDISMODULE_ERR)
- return REDISMODULE_ERR;
- return REDISMODULE_OK;
- }
|