datatype.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* This module current tests a small subset but should be extended in the future
  2. * for general ModuleDataType coverage.
  3. */
  4. #include "redismodule.h"
  5. static RedisModuleType *datatype = NULL;
  6. typedef struct {
  7. long long intval;
  8. RedisModuleString *strval;
  9. } DataType;
  10. static void *datatype_load(RedisModuleIO *io, int encver) {
  11. (void) encver;
  12. int intval = RedisModule_LoadSigned(io);
  13. if (RedisModule_IsIOError(io)) return NULL;
  14. RedisModuleString *strval = RedisModule_LoadString(io);
  15. if (RedisModule_IsIOError(io)) return NULL;
  16. DataType *dt = (DataType *) RedisModule_Alloc(sizeof(DataType));
  17. dt->intval = intval;
  18. dt->strval = strval;
  19. return dt;
  20. }
  21. static void datatype_save(RedisModuleIO *io, void *value) {
  22. DataType *dt = (DataType *) value;
  23. RedisModule_SaveSigned(io, dt->intval);
  24. RedisModule_SaveString(io, dt->strval);
  25. }
  26. static void datatype_free(void *value) {
  27. if (value) {
  28. DataType *dt = (DataType *) value;
  29. if (dt->strval) RedisModule_FreeString(NULL, dt->strval);
  30. RedisModule_Free(dt);
  31. }
  32. }
  33. static int datatype_set(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  34. if (argc != 4) {
  35. RedisModule_WrongArity(ctx);
  36. return REDISMODULE_OK;
  37. }
  38. long long intval;
  39. if (RedisModule_StringToLongLong(argv[2], &intval) != REDISMODULE_OK) {
  40. RedisModule_ReplyWithError(ctx, "Invalid integr value");
  41. return REDISMODULE_OK;
  42. }
  43. RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
  44. DataType *dt = RedisModule_Calloc(sizeof(DataType), 1);
  45. dt->intval = intval;
  46. dt->strval = argv[3];
  47. RedisModule_RetainString(ctx, dt->strval);
  48. RedisModule_ModuleTypeSetValue(key, datatype, dt);
  49. RedisModule_CloseKey(key);
  50. RedisModule_ReplyWithSimpleString(ctx, "OK");
  51. return REDISMODULE_OK;
  52. }
  53. static int datatype_restore(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  54. if (argc != 3) {
  55. RedisModule_WrongArity(ctx);
  56. return REDISMODULE_OK;
  57. }
  58. DataType *dt = RedisModule_LoadDataTypeFromString(argv[2], datatype);
  59. if (!dt) {
  60. RedisModule_ReplyWithError(ctx, "Invalid data");
  61. return REDISMODULE_OK;
  62. }
  63. RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
  64. RedisModule_ModuleTypeSetValue(key, datatype, dt);
  65. RedisModule_CloseKey(key);
  66. RedisModule_ReplyWithSimpleString(ctx, "OK");
  67. return REDISMODULE_OK;
  68. }
  69. static int datatype_get(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  70. if (argc != 2) {
  71. RedisModule_WrongArity(ctx);
  72. return REDISMODULE_OK;
  73. }
  74. RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
  75. DataType *dt = RedisModule_ModuleTypeGetValue(key);
  76. RedisModule_CloseKey(key);
  77. RedisModule_ReplyWithArray(ctx, 2);
  78. RedisModule_ReplyWithLongLong(ctx, dt->intval);
  79. RedisModule_ReplyWithString(ctx, dt->strval);
  80. return REDISMODULE_OK;
  81. }
  82. static int datatype_dump(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  83. if (argc != 2) {
  84. RedisModule_WrongArity(ctx);
  85. return REDISMODULE_OK;
  86. }
  87. RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
  88. DataType *dt = RedisModule_ModuleTypeGetValue(key);
  89. RedisModule_CloseKey(key);
  90. RedisModuleString *reply = RedisModule_SaveDataTypeToString(ctx, dt, datatype);
  91. if (!reply) {
  92. RedisModule_ReplyWithError(ctx, "Failed to save");
  93. return REDISMODULE_OK;
  94. }
  95. RedisModule_ReplyWithString(ctx, reply);
  96. RedisModule_FreeString(ctx, reply);
  97. return REDISMODULE_OK;
  98. }
  99. static int datatype_swap(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  100. if (argc != 3) {
  101. RedisModule_WrongArity(ctx);
  102. return REDISMODULE_OK;
  103. }
  104. RedisModuleKey *a = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
  105. RedisModuleKey *b = RedisModule_OpenKey(ctx, argv[2], REDISMODULE_WRITE);
  106. void *val = RedisModule_ModuleTypeGetValue(a);
  107. int error = (RedisModule_ModuleTypeReplaceValue(b, datatype, val, &val) == REDISMODULE_ERR ||
  108. RedisModule_ModuleTypeReplaceValue(a, datatype, val, NULL) == REDISMODULE_ERR);
  109. if (!error)
  110. RedisModule_ReplyWithSimpleString(ctx, "OK");
  111. else
  112. RedisModule_ReplyWithError(ctx, "ERR failed");
  113. RedisModule_CloseKey(a);
  114. RedisModule_CloseKey(b);
  115. return REDISMODULE_OK;
  116. }
  117. int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  118. REDISMODULE_NOT_USED(argv);
  119. REDISMODULE_NOT_USED(argc);
  120. if (RedisModule_Init(ctx,"datatype",1,REDISMODULE_APIVER_1) == REDISMODULE_ERR)
  121. return REDISMODULE_ERR;
  122. RedisModule_SetModuleOptions(ctx, REDISMODULE_OPTIONS_HANDLE_IO_ERRORS);
  123. RedisModuleTypeMethods datatype_methods = {
  124. .version = REDISMODULE_TYPE_METHOD_VERSION,
  125. .rdb_load = datatype_load,
  126. .rdb_save = datatype_save,
  127. .free = datatype_free,
  128. };
  129. datatype = RedisModule_CreateDataType(ctx, "test___dt", 1, &datatype_methods);
  130. if (datatype == NULL)
  131. return REDISMODULE_ERR;
  132. if (RedisModule_CreateCommand(ctx,"datatype.set", datatype_set,"deny-oom",1,1,1) == REDISMODULE_ERR)
  133. return REDISMODULE_ERR;
  134. if (RedisModule_CreateCommand(ctx,"datatype.get", datatype_get,"",1,1,1) == REDISMODULE_ERR)
  135. return REDISMODULE_ERR;
  136. if (RedisModule_CreateCommand(ctx,"datatype.restore", datatype_restore,"deny-oom",1,1,1) == REDISMODULE_ERR)
  137. return REDISMODULE_ERR;
  138. if (RedisModule_CreateCommand(ctx,"datatype.dump", datatype_dump,"",1,1,1) == REDISMODULE_ERR)
  139. return REDISMODULE_ERR;
  140. if (RedisModule_CreateCommand(ctx,"datatype.swap", datatype_swap,"",1,1,1) == REDISMODULE_ERR)
  141. return REDISMODULE_ERR;
  142. return REDISMODULE_OK;
  143. }