testrdb.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include "redismodule.h"
  2. #include <string.h>
  3. #include <assert.h>
  4. /* Module configuration, save aux or not? */
  5. long long conf_aux_count = 0;
  6. /* Registered type */
  7. RedisModuleType *testrdb_type = NULL;
  8. /* Global values to store and persist to aux */
  9. RedisModuleString *before_str = NULL;
  10. RedisModuleString *after_str = NULL;
  11. void *testrdb_type_load(RedisModuleIO *rdb, int encver) {
  12. int count = RedisModule_LoadSigned(rdb);
  13. RedisModuleString *str = RedisModule_LoadString(rdb);
  14. float f = RedisModule_LoadFloat(rdb);
  15. long double ld = RedisModule_LoadLongDouble(rdb);
  16. if (RedisModule_IsIOError(rdb)) {
  17. RedisModuleCtx *ctx = RedisModule_GetContextFromIO(rdb);
  18. if (str)
  19. RedisModule_FreeString(ctx, str);
  20. return NULL;
  21. }
  22. /* Using the values only after checking for io errors. */
  23. assert(count==1);
  24. assert(encver==1);
  25. assert(f==1.5f);
  26. assert(ld==0.333333333333333333L);
  27. return str;
  28. }
  29. void testrdb_type_save(RedisModuleIO *rdb, void *value) {
  30. RedisModuleString *str = (RedisModuleString*)value;
  31. RedisModule_SaveSigned(rdb, 1);
  32. RedisModule_SaveString(rdb, str);
  33. RedisModule_SaveFloat(rdb, 1.5);
  34. RedisModule_SaveLongDouble(rdb, 0.333333333333333333L);
  35. }
  36. void testrdb_aux_save(RedisModuleIO *rdb, int when) {
  37. if (conf_aux_count==1) assert(when == REDISMODULE_AUX_AFTER_RDB);
  38. if (conf_aux_count==0) assert(0);
  39. if (when == REDISMODULE_AUX_BEFORE_RDB) {
  40. if (before_str) {
  41. RedisModule_SaveSigned(rdb, 1);
  42. RedisModule_SaveString(rdb, before_str);
  43. } else {
  44. RedisModule_SaveSigned(rdb, 0);
  45. }
  46. } else {
  47. if (after_str) {
  48. RedisModule_SaveSigned(rdb, 1);
  49. RedisModule_SaveString(rdb, after_str);
  50. } else {
  51. RedisModule_SaveSigned(rdb, 0);
  52. }
  53. }
  54. }
  55. int testrdb_aux_load(RedisModuleIO *rdb, int encver, int when) {
  56. assert(encver == 1);
  57. if (conf_aux_count==1) assert(when == REDISMODULE_AUX_AFTER_RDB);
  58. if (conf_aux_count==0) assert(0);
  59. RedisModuleCtx *ctx = RedisModule_GetContextFromIO(rdb);
  60. if (when == REDISMODULE_AUX_BEFORE_RDB) {
  61. if (before_str)
  62. RedisModule_FreeString(ctx, before_str);
  63. before_str = NULL;
  64. int count = RedisModule_LoadSigned(rdb);
  65. if (RedisModule_IsIOError(rdb))
  66. return REDISMODULE_ERR;
  67. if (count)
  68. before_str = RedisModule_LoadString(rdb);
  69. } else {
  70. if (after_str)
  71. RedisModule_FreeString(ctx, after_str);
  72. after_str = NULL;
  73. int count = RedisModule_LoadSigned(rdb);
  74. if (RedisModule_IsIOError(rdb))
  75. return REDISMODULE_ERR;
  76. if (count)
  77. after_str = RedisModule_LoadString(rdb);
  78. }
  79. if (RedisModule_IsIOError(rdb))
  80. return REDISMODULE_ERR;
  81. return REDISMODULE_OK;
  82. }
  83. void testrdb_type_free(void *value) {
  84. if (value)
  85. RedisModule_FreeString(NULL, (RedisModuleString*)value);
  86. }
  87. int testrdb_set_before(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  88. {
  89. if (argc != 2) {
  90. RedisModule_WrongArity(ctx);
  91. return REDISMODULE_OK;
  92. }
  93. if (before_str)
  94. RedisModule_FreeString(ctx, before_str);
  95. before_str = argv[1];
  96. RedisModule_RetainString(ctx, argv[1]);
  97. RedisModule_ReplyWithLongLong(ctx, 1);
  98. return REDISMODULE_OK;
  99. }
  100. int testrdb_get_before(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  101. {
  102. REDISMODULE_NOT_USED(argv);
  103. if (argc != 1){
  104. RedisModule_WrongArity(ctx);
  105. return REDISMODULE_OK;
  106. }
  107. if (before_str)
  108. RedisModule_ReplyWithString(ctx, before_str);
  109. else
  110. RedisModule_ReplyWithStringBuffer(ctx, "", 0);
  111. return REDISMODULE_OK;
  112. }
  113. int testrdb_set_after(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  114. {
  115. if (argc != 2){
  116. RedisModule_WrongArity(ctx);
  117. return REDISMODULE_OK;
  118. }
  119. if (after_str)
  120. RedisModule_FreeString(ctx, after_str);
  121. after_str = argv[1];
  122. RedisModule_RetainString(ctx, argv[1]);
  123. RedisModule_ReplyWithLongLong(ctx, 1);
  124. return REDISMODULE_OK;
  125. }
  126. int testrdb_get_after(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  127. {
  128. REDISMODULE_NOT_USED(argv);
  129. if (argc != 1){
  130. RedisModule_WrongArity(ctx);
  131. return REDISMODULE_OK;
  132. }
  133. if (after_str)
  134. RedisModule_ReplyWithString(ctx, after_str);
  135. else
  136. RedisModule_ReplyWithStringBuffer(ctx, "", 0);
  137. return REDISMODULE_OK;
  138. }
  139. int testrdb_set_key(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  140. {
  141. if (argc != 3){
  142. RedisModule_WrongArity(ctx);
  143. return REDISMODULE_OK;
  144. }
  145. RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
  146. RedisModuleString *str = RedisModule_ModuleTypeGetValue(key);
  147. if (str)
  148. RedisModule_FreeString(ctx, str);
  149. RedisModule_ModuleTypeSetValue(key, testrdb_type, argv[2]);
  150. RedisModule_RetainString(ctx, argv[2]);
  151. RedisModule_CloseKey(key);
  152. RedisModule_ReplyWithLongLong(ctx, 1);
  153. return REDISMODULE_OK;
  154. }
  155. int testrdb_get_key(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  156. {
  157. if (argc != 2){
  158. RedisModule_WrongArity(ctx);
  159. return REDISMODULE_OK;
  160. }
  161. RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
  162. RedisModuleString *str = RedisModule_ModuleTypeGetValue(key);
  163. RedisModule_CloseKey(key);
  164. RedisModule_ReplyWithString(ctx, str);
  165. return REDISMODULE_OK;
  166. }
  167. int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  168. REDISMODULE_NOT_USED(argv);
  169. REDISMODULE_NOT_USED(argc);
  170. if (RedisModule_Init(ctx,"testrdb",1,REDISMODULE_APIVER_1) == REDISMODULE_ERR)
  171. return REDISMODULE_ERR;
  172. RedisModule_SetModuleOptions(ctx, REDISMODULE_OPTIONS_HANDLE_IO_ERRORS);
  173. if (argc > 0)
  174. RedisModule_StringToLongLong(argv[0], &conf_aux_count);
  175. if (conf_aux_count==0) {
  176. RedisModuleTypeMethods datatype_methods = {
  177. .version = 1,
  178. .rdb_load = testrdb_type_load,
  179. .rdb_save = testrdb_type_save,
  180. .aof_rewrite = NULL,
  181. .digest = NULL,
  182. .free = testrdb_type_free,
  183. };
  184. testrdb_type = RedisModule_CreateDataType(ctx, "test__rdb", 1, &datatype_methods);
  185. if (testrdb_type == NULL)
  186. return REDISMODULE_ERR;
  187. } else {
  188. RedisModuleTypeMethods datatype_methods = {
  189. .version = REDISMODULE_TYPE_METHOD_VERSION,
  190. .rdb_load = testrdb_type_load,
  191. .rdb_save = testrdb_type_save,
  192. .aof_rewrite = NULL,
  193. .digest = NULL,
  194. .free = testrdb_type_free,
  195. .aux_load = testrdb_aux_load,
  196. .aux_save = testrdb_aux_save,
  197. .aux_save_triggers = (conf_aux_count == 1 ?
  198. REDISMODULE_AUX_AFTER_RDB :
  199. REDISMODULE_AUX_BEFORE_RDB | REDISMODULE_AUX_AFTER_RDB)
  200. };
  201. testrdb_type = RedisModule_CreateDataType(ctx, "test__rdb", 1, &datatype_methods);
  202. if (testrdb_type == NULL)
  203. return REDISMODULE_ERR;
  204. }
  205. if (RedisModule_CreateCommand(ctx,"testrdb.set.before", testrdb_set_before,"deny-oom",0,0,0) == REDISMODULE_ERR)
  206. return REDISMODULE_ERR;
  207. if (RedisModule_CreateCommand(ctx,"testrdb.get.before", testrdb_get_before,"",0,0,0) == REDISMODULE_ERR)
  208. return REDISMODULE_ERR;
  209. if (RedisModule_CreateCommand(ctx,"testrdb.set.after", testrdb_set_after,"deny-oom",0,0,0) == REDISMODULE_ERR)
  210. return REDISMODULE_ERR;
  211. if (RedisModule_CreateCommand(ctx,"testrdb.get.after", testrdb_get_after,"",0,0,0) == REDISMODULE_ERR)
  212. return REDISMODULE_ERR;
  213. if (RedisModule_CreateCommand(ctx,"testrdb.set.key", testrdb_set_key,"deny-oom",1,1,1) == REDISMODULE_ERR)
  214. return REDISMODULE_ERR;
  215. if (RedisModule_CreateCommand(ctx,"testrdb.get.key", testrdb_get_key,"",1,1,1) == REDISMODULE_ERR)
  216. return REDISMODULE_ERR;
  217. return REDISMODULE_OK;
  218. }
  219. int RedisModule_OnUnload(RedisModuleCtx *ctx) {
  220. if (before_str)
  221. RedisModule_FreeString(ctx, before_str);
  222. if (after_str)
  223. RedisModule_FreeString(ctx, after_str);
  224. return REDISMODULE_OK;
  225. }