misc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. #define REDISMODULE_EXPERIMENTAL_API
  2. #include "redismodule.h"
  3. #include <string.h>
  4. #include <assert.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #define UNUSED(x) (void)(x)
  8. int test_call_generic(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  9. {
  10. if (argc<2) {
  11. RedisModule_WrongArity(ctx);
  12. return REDISMODULE_OK;
  13. }
  14. const char* cmdname = RedisModule_StringPtrLen(argv[1], NULL);
  15. RedisModuleCallReply *reply = RedisModule_Call(ctx, cmdname, "v", argv+2, argc-2);
  16. if (reply) {
  17. RedisModule_ReplyWithCallReply(ctx, reply);
  18. RedisModule_FreeCallReply(reply);
  19. } else {
  20. RedisModule_ReplyWithError(ctx, strerror(errno));
  21. }
  22. return REDISMODULE_OK;
  23. }
  24. int test_call_info(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  25. {
  26. RedisModuleCallReply *reply;
  27. if (argc>1)
  28. reply = RedisModule_Call(ctx, "info", "s", argv[1]);
  29. else
  30. reply = RedisModule_Call(ctx, "info", "");
  31. if (reply) {
  32. RedisModule_ReplyWithCallReply(ctx, reply);
  33. RedisModule_FreeCallReply(reply);
  34. } else {
  35. RedisModule_ReplyWithError(ctx, strerror(errno));
  36. }
  37. return REDISMODULE_OK;
  38. }
  39. int test_ld_conv(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  40. UNUSED(argv);
  41. UNUSED(argc);
  42. long double ld = 0.00000000000000001L;
  43. const char *ldstr = "0.00000000000000001";
  44. RedisModuleString *s1 = RedisModule_CreateStringFromLongDouble(ctx, ld, 1);
  45. RedisModuleString *s2 =
  46. RedisModule_CreateString(ctx, ldstr, strlen(ldstr));
  47. if (RedisModule_StringCompare(s1, s2) != 0) {
  48. char err[4096];
  49. snprintf(err, 4096,
  50. "Failed to convert long double to string ('%s' != '%s')",
  51. RedisModule_StringPtrLen(s1, NULL),
  52. RedisModule_StringPtrLen(s2, NULL));
  53. RedisModule_ReplyWithError(ctx, err);
  54. goto final;
  55. }
  56. long double ld2 = 0;
  57. if (RedisModule_StringToLongDouble(s2, &ld2) == REDISMODULE_ERR) {
  58. RedisModule_ReplyWithError(ctx,
  59. "Failed to convert string to long double");
  60. goto final;
  61. }
  62. if (ld2 != ld) {
  63. char err[4096];
  64. snprintf(err, 4096,
  65. "Failed to convert string to long double (%.40Lf != %.40Lf)",
  66. ld2,
  67. ld);
  68. RedisModule_ReplyWithError(ctx, err);
  69. goto final;
  70. }
  71. /* Make sure we can't convert a string that has \0 in it */
  72. char buf[4] = "123";
  73. buf[1] = '\0';
  74. RedisModuleString *s3 = RedisModule_CreateString(ctx, buf, 3);
  75. long double ld3;
  76. if (RedisModule_StringToLongDouble(s3, &ld3) == REDISMODULE_OK) {
  77. RedisModule_ReplyWithError(ctx, "Invalid string successfully converted to long double");
  78. RedisModule_FreeString(ctx, s3);
  79. goto final;
  80. }
  81. RedisModule_FreeString(ctx, s3);
  82. RedisModule_ReplyWithLongDouble(ctx, ld2);
  83. final:
  84. RedisModule_FreeString(ctx, s1);
  85. RedisModule_FreeString(ctx, s2);
  86. return REDISMODULE_OK;
  87. }
  88. int test_flushall(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  89. {
  90. REDISMODULE_NOT_USED(argv);
  91. REDISMODULE_NOT_USED(argc);
  92. RedisModule_ResetDataset(1, 0);
  93. RedisModule_ReplyWithCString(ctx, "Ok");
  94. return REDISMODULE_OK;
  95. }
  96. int test_dbsize(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  97. {
  98. REDISMODULE_NOT_USED(argv);
  99. REDISMODULE_NOT_USED(argc);
  100. long long ll = RedisModule_DbSize(ctx);
  101. RedisModule_ReplyWithLongLong(ctx, ll);
  102. return REDISMODULE_OK;
  103. }
  104. int test_randomkey(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  105. {
  106. REDISMODULE_NOT_USED(argv);
  107. REDISMODULE_NOT_USED(argc);
  108. RedisModuleString *str = RedisModule_RandomKey(ctx);
  109. RedisModule_ReplyWithString(ctx, str);
  110. RedisModule_FreeString(ctx, str);
  111. return REDISMODULE_OK;
  112. }
  113. RedisModuleKey *open_key_or_reply(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode) {
  114. RedisModuleKey *key = RedisModule_OpenKey(ctx, keyname, mode);
  115. if (!key) {
  116. RedisModule_ReplyWithError(ctx, "key not found");
  117. return NULL;
  118. }
  119. return key;
  120. }
  121. int test_getlru(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  122. {
  123. if (argc<2) {
  124. RedisModule_WrongArity(ctx);
  125. return REDISMODULE_OK;
  126. }
  127. RedisModuleKey *key = open_key_or_reply(ctx, argv[1], REDISMODULE_READ|REDISMODULE_OPEN_KEY_NOTOUCH);
  128. mstime_t lru;
  129. RedisModule_GetLRU(key, &lru);
  130. RedisModule_ReplyWithLongLong(ctx, lru);
  131. RedisModule_CloseKey(key);
  132. return REDISMODULE_OK;
  133. }
  134. int test_setlru(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  135. {
  136. if (argc<3) {
  137. RedisModule_WrongArity(ctx);
  138. return REDISMODULE_OK;
  139. }
  140. RedisModuleKey *key = open_key_or_reply(ctx, argv[1], REDISMODULE_READ|REDISMODULE_OPEN_KEY_NOTOUCH);
  141. mstime_t lru;
  142. if (RedisModule_StringToLongLong(argv[2], &lru) != REDISMODULE_OK) {
  143. RedisModule_ReplyWithError(ctx, "invalid idle time");
  144. return REDISMODULE_OK;
  145. }
  146. int was_set = RedisModule_SetLRU(key, lru)==REDISMODULE_OK;
  147. RedisModule_ReplyWithLongLong(ctx, was_set);
  148. RedisModule_CloseKey(key);
  149. return REDISMODULE_OK;
  150. }
  151. int test_getlfu(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  152. {
  153. if (argc<2) {
  154. RedisModule_WrongArity(ctx);
  155. return REDISMODULE_OK;
  156. }
  157. RedisModuleKey *key = open_key_or_reply(ctx, argv[1], REDISMODULE_READ|REDISMODULE_OPEN_KEY_NOTOUCH);
  158. mstime_t lfu;
  159. RedisModule_GetLFU(key, &lfu);
  160. RedisModule_ReplyWithLongLong(ctx, lfu);
  161. RedisModule_CloseKey(key);
  162. return REDISMODULE_OK;
  163. }
  164. int test_setlfu(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  165. {
  166. if (argc<3) {
  167. RedisModule_WrongArity(ctx);
  168. return REDISMODULE_OK;
  169. }
  170. RedisModuleKey *key = open_key_or_reply(ctx, argv[1], REDISMODULE_READ|REDISMODULE_OPEN_KEY_NOTOUCH);
  171. mstime_t lfu;
  172. if (RedisModule_StringToLongLong(argv[2], &lfu) != REDISMODULE_OK) {
  173. RedisModule_ReplyWithError(ctx, "invalid freq");
  174. return REDISMODULE_OK;
  175. }
  176. int was_set = RedisModule_SetLFU(key, lfu)==REDISMODULE_OK;
  177. RedisModule_ReplyWithLongLong(ctx, was_set);
  178. RedisModule_CloseKey(key);
  179. return REDISMODULE_OK;
  180. }
  181. int test_redisversion(RedisModuleCtx *ctx, RedisModuleString **argv, int argc){
  182. (void) argv;
  183. (void) argc;
  184. int version = RedisModule_GetServerVersion();
  185. int patch = version & 0x000000ff;
  186. int minor = (version & 0x0000ff00) >> 8;
  187. int major = (version & 0x00ff0000) >> 16;
  188. RedisModuleString* vStr = RedisModule_CreateStringPrintf(ctx, "%d.%d.%d", major, minor, patch);
  189. RedisModule_ReplyWithString(ctx, vStr);
  190. RedisModule_FreeString(ctx, vStr);
  191. return REDISMODULE_OK;
  192. }
  193. int test_getclientcert(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  194. {
  195. (void) argv;
  196. (void) argc;
  197. RedisModuleString *cert = RedisModule_GetClientCertificate(ctx,
  198. RedisModule_GetClientId(ctx));
  199. if (!cert) {
  200. RedisModule_ReplyWithNull(ctx);
  201. } else {
  202. RedisModule_ReplyWithString(ctx, cert);
  203. RedisModule_FreeString(ctx, cert);
  204. }
  205. return REDISMODULE_OK;
  206. }
  207. int test_clientinfo(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  208. {
  209. (void) argv;
  210. (void) argc;
  211. RedisModuleClientInfo ci = { .version = REDISMODULE_CLIENTINFO_VERSION };
  212. if (RedisModule_GetClientInfoById(&ci, RedisModule_GetClientId(ctx)) == REDISMODULE_ERR) {
  213. RedisModule_ReplyWithError(ctx, "failed to get client info");
  214. return REDISMODULE_OK;
  215. }
  216. RedisModule_ReplyWithArray(ctx, 10);
  217. char flags[512];
  218. snprintf(flags, sizeof(flags) - 1, "%s:%s:%s:%s:%s:%s",
  219. ci.flags & REDISMODULE_CLIENTINFO_FLAG_SSL ? "ssl" : "",
  220. ci.flags & REDISMODULE_CLIENTINFO_FLAG_PUBSUB ? "pubsub" : "",
  221. ci.flags & REDISMODULE_CLIENTINFO_FLAG_BLOCKED ? "blocked" : "",
  222. ci.flags & REDISMODULE_CLIENTINFO_FLAG_TRACKING ? "tracking" : "",
  223. ci.flags & REDISMODULE_CLIENTINFO_FLAG_UNIXSOCKET ? "unixsocket" : "",
  224. ci.flags & REDISMODULE_CLIENTINFO_FLAG_MULTI ? "multi" : "");
  225. RedisModule_ReplyWithCString(ctx, "flags");
  226. RedisModule_ReplyWithCString(ctx, flags);
  227. RedisModule_ReplyWithCString(ctx, "id");
  228. RedisModule_ReplyWithLongLong(ctx, ci.id);
  229. RedisModule_ReplyWithCString(ctx, "addr");
  230. RedisModule_ReplyWithCString(ctx, ci.addr);
  231. RedisModule_ReplyWithCString(ctx, "port");
  232. RedisModule_ReplyWithLongLong(ctx, ci.port);
  233. RedisModule_ReplyWithCString(ctx, "db");
  234. RedisModule_ReplyWithLongLong(ctx, ci.db);
  235. return REDISMODULE_OK;
  236. }
  237. int test_log_tsctx(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
  238. {
  239. RedisModuleCtx *tsctx = RedisModule_GetDetachedThreadSafeContext(ctx);
  240. if (argc != 3) {
  241. RedisModule_WrongArity(ctx);
  242. return REDISMODULE_OK;
  243. }
  244. char level[50];
  245. size_t level_len;
  246. const char *level_str = RedisModule_StringPtrLen(argv[1], &level_len);
  247. snprintf(level, sizeof(level) - 1, "%.*s", (int) level_len, level_str);
  248. size_t msg_len;
  249. const char *msg_str = RedisModule_StringPtrLen(argv[2], &msg_len);
  250. RedisModule_Log(tsctx, level, "%.*s", (int) msg_len, msg_str);
  251. RedisModule_FreeThreadSafeContext(tsctx);
  252. RedisModule_ReplyWithSimpleString(ctx, "OK");
  253. return REDISMODULE_OK;
  254. }
  255. int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  256. REDISMODULE_NOT_USED(argv);
  257. REDISMODULE_NOT_USED(argc);
  258. if (RedisModule_Init(ctx,"misc",1,REDISMODULE_APIVER_1)== REDISMODULE_ERR)
  259. return REDISMODULE_ERR;
  260. if (RedisModule_CreateCommand(ctx,"test.call_generic", test_call_generic,"",0,0,0) == REDISMODULE_ERR)
  261. return REDISMODULE_ERR;
  262. if (RedisModule_CreateCommand(ctx,"test.call_info", test_call_info,"",0,0,0) == REDISMODULE_ERR)
  263. return REDISMODULE_ERR;
  264. if (RedisModule_CreateCommand(ctx,"test.ld_conversion", test_ld_conv, "",0,0,0) == REDISMODULE_ERR)
  265. return REDISMODULE_ERR;
  266. if (RedisModule_CreateCommand(ctx,"test.flushall", test_flushall,"",0,0,0) == REDISMODULE_ERR)
  267. return REDISMODULE_ERR;
  268. if (RedisModule_CreateCommand(ctx,"test.dbsize", test_dbsize,"",0,0,0) == REDISMODULE_ERR)
  269. return REDISMODULE_ERR;
  270. if (RedisModule_CreateCommand(ctx,"test.randomkey", test_randomkey,"",0,0,0) == REDISMODULE_ERR)
  271. return REDISMODULE_ERR;
  272. if (RedisModule_CreateCommand(ctx,"test.setlru", test_setlru,"",0,0,0) == REDISMODULE_ERR)
  273. return REDISMODULE_ERR;
  274. if (RedisModule_CreateCommand(ctx,"test.getlru", test_getlru,"",0,0,0) == REDISMODULE_ERR)
  275. return REDISMODULE_ERR;
  276. if (RedisModule_CreateCommand(ctx,"test.setlfu", test_setlfu,"",0,0,0) == REDISMODULE_ERR)
  277. return REDISMODULE_ERR;
  278. if (RedisModule_CreateCommand(ctx,"test.getlfu", test_getlfu,"",0,0,0) == REDISMODULE_ERR)
  279. return REDISMODULE_ERR;
  280. if (RedisModule_CreateCommand(ctx,"test.clientinfo", test_clientinfo,"",0,0,0) == REDISMODULE_ERR)
  281. return REDISMODULE_ERR;
  282. if (RedisModule_CreateCommand(ctx,"test.redisversion", test_redisversion,"",0,0,0) == REDISMODULE_ERR)
  283. return REDISMODULE_ERR;
  284. if (RedisModule_CreateCommand(ctx,"test.getclientcert", test_getclientcert,"",0,0,0) == REDISMODULE_ERR)
  285. return REDISMODULE_ERR;
  286. if (RedisModule_CreateCommand(ctx,"test.log_tsctx", test_log_tsctx,"",0,0,0) == REDISMODULE_ERR)
  287. return REDISMODULE_ERR;
  288. return REDISMODULE_OK;
  289. }