1
0

hash.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include "redismodule.h"
  2. #include <strings.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. /* If a string is ":deleted:", the special value for deleted hash fields is
  6. * returned; otherwise the input string is returned. */
  7. static RedisModuleString *value_or_delete(RedisModuleString *s) {
  8. if (!strcasecmp(RedisModule_StringPtrLen(s, NULL), ":delete:"))
  9. return REDISMODULE_HASH_DELETE;
  10. else
  11. return s;
  12. }
  13. /* HASH.SET key flags field1 value1 [field2 value2 ..]
  14. *
  15. * Sets 1-4 fields. Returns the same as RedisModule_HashSet().
  16. * Flags is a string of "nxa" where n = NX, x = XX, a = COUNT_ALL.
  17. * To delete a field, use the value ":delete:".
  18. */
  19. int hash_set(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  20. if (argc < 5 || argc % 2 == 0 || argc > 11)
  21. return RedisModule_WrongArity(ctx);
  22. RedisModule_AutoMemory(ctx);
  23. RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
  24. size_t flags_len;
  25. const char *flags_str = RedisModule_StringPtrLen(argv[2], &flags_len);
  26. int flags = REDISMODULE_HASH_NONE;
  27. for (size_t i = 0; i < flags_len; i++) {
  28. switch (flags_str[i]) {
  29. case 'n': flags |= REDISMODULE_HASH_NX; break;
  30. case 'x': flags |= REDISMODULE_HASH_XX; break;
  31. case 'a': flags |= REDISMODULE_HASH_COUNT_ALL; break;
  32. }
  33. }
  34. /* Test some varargs. (In real-world, use a loop and set one at a time.) */
  35. int result;
  36. errno = 0;
  37. if (argc == 5) {
  38. result = RedisModule_HashSet(key, flags,
  39. argv[3], value_or_delete(argv[4]),
  40. NULL);
  41. } else if (argc == 7) {
  42. result = RedisModule_HashSet(key, flags,
  43. argv[3], value_or_delete(argv[4]),
  44. argv[5], value_or_delete(argv[6]),
  45. NULL);
  46. } else if (argc == 9) {
  47. result = RedisModule_HashSet(key, flags,
  48. argv[3], value_or_delete(argv[4]),
  49. argv[5], value_or_delete(argv[6]),
  50. argv[7], value_or_delete(argv[8]),
  51. NULL);
  52. } else if (argc == 11) {
  53. result = RedisModule_HashSet(key, flags,
  54. argv[3], value_or_delete(argv[4]),
  55. argv[5], value_or_delete(argv[6]),
  56. argv[7], value_or_delete(argv[8]),
  57. argv[9], value_or_delete(argv[10]),
  58. NULL);
  59. } else {
  60. return RedisModule_ReplyWithError(ctx, "ERR too many fields");
  61. }
  62. /* Check errno */
  63. if (result == 0) {
  64. if (errno == ENOTSUP)
  65. return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
  66. else
  67. RedisModule_Assert(errno == ENOENT);
  68. }
  69. return RedisModule_ReplyWithLongLong(ctx, result);
  70. }
  71. int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  72. REDISMODULE_NOT_USED(argv);
  73. REDISMODULE_NOT_USED(argc);
  74. if (RedisModule_Init(ctx, "hash", 1, REDISMODULE_APIVER_1) ==
  75. REDISMODULE_OK &&
  76. RedisModule_CreateCommand(ctx, "hash.set", hash_set, "",
  77. 1, 1, 1) == REDISMODULE_OK) {
  78. return REDISMODULE_OK;
  79. } else {
  80. return REDISMODULE_ERR;
  81. }
  82. }