1
0

getkeys.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #define REDISMODULE_EXPERIMENTAL_API
  2. #include "redismodule.h"
  3. #include <strings.h>
  4. #include <assert.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #define UNUSED(V) ((void) V)
  8. /* A sample movable keys command that returns a list of all
  9. * arguments that follow a KEY argument, i.e.
  10. */
  11. int getkeys_command(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  12. {
  13. int i;
  14. int count = 0;
  15. /* Handle getkeys-api introspection */
  16. if (RedisModule_IsKeysPositionRequest(ctx)) {
  17. for (i = 0; i < argc; i++) {
  18. size_t len;
  19. const char *str = RedisModule_StringPtrLen(argv[i], &len);
  20. if (len == 3 && !strncasecmp(str, "key", 3) && i + 1 < argc)
  21. RedisModule_KeyAtPos(ctx, i + 1);
  22. }
  23. return REDISMODULE_OK;
  24. }
  25. /* Handle real command invocation */
  26. RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
  27. for (i = 0; i < argc; i++) {
  28. size_t len;
  29. const char *str = RedisModule_StringPtrLen(argv[i], &len);
  30. if (len == 3 && !strncasecmp(str, "key", 3) && i + 1 < argc) {
  31. RedisModule_ReplyWithString(ctx, argv[i+1]);
  32. count++;
  33. }
  34. }
  35. RedisModule_ReplySetArrayLength(ctx, count);
  36. return REDISMODULE_OK;
  37. }
  38. int getkeys_fixed(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  39. {
  40. int i;
  41. RedisModule_ReplyWithArray(ctx, argc - 1);
  42. for (i = 1; i < argc; i++) {
  43. RedisModule_ReplyWithString(ctx, argv[i]);
  44. }
  45. return REDISMODULE_OK;
  46. }
  47. /* Introspect a command using RM_GetCommandKeys() and returns the list
  48. * of keys. Essentially this is COMMAND GETKEYS implemented in a module.
  49. */
  50. int getkeys_introspect(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  51. {
  52. UNUSED(argv);
  53. UNUSED(argc);
  54. if (argc < 3) {
  55. RedisModule_WrongArity(ctx);
  56. return REDISMODULE_OK;
  57. }
  58. int num_keys;
  59. int *keyidx = RedisModule_GetCommandKeys(ctx, &argv[1], argc - 1, &num_keys);
  60. if (!keyidx) {
  61. if (!errno)
  62. RedisModule_ReplyWithEmptyArray(ctx);
  63. else {
  64. char err[100];
  65. switch (errno) {
  66. case ENOENT:
  67. RedisModule_ReplyWithError(ctx, "ERR ENOENT");
  68. break;
  69. case EINVAL:
  70. RedisModule_ReplyWithError(ctx, "ERR EINVAL");
  71. break;
  72. default:
  73. snprintf(err, sizeof(err) - 1, "ERR errno=%d", errno);
  74. RedisModule_ReplyWithError(ctx, err);
  75. break;
  76. }
  77. }
  78. } else {
  79. int i;
  80. RedisModule_ReplyWithArray(ctx, num_keys);
  81. for (i = 0; i < num_keys; i++)
  82. RedisModule_ReplyWithString(ctx, argv[1 + keyidx[i]]);
  83. RedisModule_Free(keyidx);
  84. }
  85. return REDISMODULE_OK;
  86. }
  87. int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  88. UNUSED(argv);
  89. UNUSED(argc);
  90. if (RedisModule_Init(ctx,"getkeys",1,REDISMODULE_APIVER_1)== REDISMODULE_ERR)
  91. return REDISMODULE_ERR;
  92. if (RedisModule_CreateCommand(ctx,"getkeys.command", getkeys_command,"getkeys-api",0,0,0) == REDISMODULE_ERR)
  93. return REDISMODULE_ERR;
  94. if (RedisModule_CreateCommand(ctx,"getkeys.fixed", getkeys_fixed,"",2,4,1) == REDISMODULE_ERR)
  95. return REDISMODULE_ERR;
  96. if (RedisModule_CreateCommand(ctx,"getkeys.introspect", getkeys_introspect,"",0,0,0) == REDISMODULE_ERR)
  97. return REDISMODULE_ERR;
  98. return REDISMODULE_OK;
  99. }