summaryrefslogtreecommitdiff
path: root/examples/redis-unstable/src/module.c
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-01-21 22:40:55 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-01-21 22:40:55 +0100
commit5d8dfe892a2ea89f706ee140c3bdcfd89fe03fda (patch)
tree1acdfa5220cd13b7be43a2a01368e80d306473ca /examples/redis-unstable/src/module.c
parentc7ab12bba64d9c20ccd79b132dac475f7bc3923e (diff)
downloadcrep-5d8dfe892a2ea89f706ee140c3bdcfd89fe03fda.tar.gz
Add Redis source code for testing
Diffstat (limited to 'examples/redis-unstable/src/module.c')
-rw-r--r--examples/redis-unstable/src/module.c15545
1 files changed, 15545 insertions, 0 deletions
diff --git a/examples/redis-unstable/src/module.c b/examples/redis-unstable/src/module.c
new file mode 100644
index 0000000..3cabd9c
--- /dev/null
+++ b/examples/redis-unstable/src/module.c
@@ -0,0 +1,15545 @@
1/*
2 * Copyright (c) 2016-Present, Redis Ltd.
3 * All rights reserved.
4 *
5 * Copyright (c) 2024-present, Valkey contributors.
6 * All rights reserved.
7 *
8 * Licensed under your choice of (a) the Redis Source Available License 2.0
9 * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the
10 * GNU Affero General Public License v3 (AGPLv3).
11 *
12 * Portions of this file are available under BSD3 terms; see REDISCONTRIBUTIONS for more information.
13 */
14
15/* --------------------------------------------------------------------------
16 * Modules API documentation information
17 *
18 * The comments in this file are used to generate the API documentation on the
19 * Redis website.
20 *
21 * Each function starting with RM_ and preceded by a block comment is included
22 * in the API documentation. To hide an RM_ function, put a blank line between
23 * the comment and the function definition or put the comment inside the
24 * function body.
25 *
26 * The functions are divided into sections. Each section is preceded by a
27 * documentation block, which is comment block starting with a markdown level 2
28 * heading, i.e. a line starting with ##, on the first line of the comment block
29 * (with the exception of a ----- line which can appear first). Other comment
30 * blocks, which are not intended for the modules API user, such as this comment
31 * block, do NOT start with a markdown level 2 heading, so they are included in
32 * the generated a API documentation.
33 *
34 * The documentation comments may contain markdown formatting. Some automatic
35 * replacements are done, such as the replacement of RM with RedisModule in
36 * function names. For details, see the script src/modules/gendoc.rb.
37 * -------------------------------------------------------------------------- */
38
39#include "server.h"
40#include "cluster.h"
41#include "cluster_asm.h"
42#include "slowlog.h"
43#include "rdb.h"
44#include "monotonic.h"
45#include "script.h"
46#include "call_reply.h"
47#include "hdr_histogram.h"
48#include "crc16_slottable.h"
49#include <dlfcn.h>
50#include <sys/stat.h>
51#include <sys/wait.h>
52#include <fcntl.h>
53#include <string.h>
54
55/* --------------------------------------------------------------------------
56 * Private data structures used by the modules system. Those are data
57 * structures that are never exposed to Redis Modules, if not as void
58 * pointers that have an API the module can call with them)
59 * -------------------------------------------------------------------------- */
60
61struct RedisModuleInfoCtx {
62 struct RedisModule *module;
63 dict *requested_sections;
64 sds info; /* info string we collected so far */
65 int sections; /* number of sections we collected so far */
66 int in_section; /* indication if we're in an active section or not */
67 int in_dict_field; /* indication that we're currently appending to a dict */
68};
69
70/* This represents a shared API. Shared APIs will be used to populate
71 * the server.sharedapi dictionary, mapping names of APIs exported by
72 * modules for other modules to use, to their structure specifying the
73 * function pointer that can be called. */
74struct RedisModuleSharedAPI {
75 void *func;
76 RedisModule *module;
77};
78typedef struct RedisModuleSharedAPI RedisModuleSharedAPI;
79typedef struct RedisModuleKeyOptCtx RedisModuleKeyOptCtx;
80
81dict *modules; /* Hash table of modules. SDS -> RedisModule ptr.*/
82
83/* Entries in the context->amqueue array, representing objects to free
84 * when the callback returns. */
85struct AutoMemEntry {
86 void *ptr;
87 int type;
88};
89
90/* AutoMemEntry type field values. */
91#define REDISMODULE_AM_KEY 0
92#define REDISMODULE_AM_STRING 1
93#define REDISMODULE_AM_REPLY 2
94#define REDISMODULE_AM_FREED 3 /* Explicitly freed by user already. */
95#define REDISMODULE_AM_DICT 4
96#define REDISMODULE_AM_INFO 5
97#define REDISMODULE_AM_CONFIG 6
98#define REDISMODULE_AM_SLOTRANGEARRAY 7
99
100/* The pool allocator block. Redis Modules can allocate memory via this special
101 * allocator that will automatically release it all once the callback returns.
102 * This means that it can only be used for ephemeral allocations. However
103 * there are two advantages for modules to use this API:
104 *
105 * 1) The memory is automatically released when the callback returns.
106 * 2) This allocator is faster for many small allocations since whole blocks
107 * are allocated, and small pieces returned to the caller just advancing
108 * the index of the allocation.
109 *
110 * Allocations are always rounded to the size of the void pointer in order
111 * to always return aligned memory chunks. */
112
113#define REDISMODULE_POOL_ALLOC_MIN_SIZE (1024*8)
114#define REDISMODULE_POOL_ALLOC_ALIGN (sizeof(void*))
115
116typedef struct RedisModulePoolAllocBlock {
117 uint32_t size;
118 uint32_t used;
119 struct RedisModulePoolAllocBlock *next;
120 char memory[];
121} RedisModulePoolAllocBlock;
122
123/* This structure represents the context in which Redis modules operate.
124 * Most APIs module can access, get a pointer to the context, so that the API
125 * implementation can hold state across calls, or remember what to free after
126 * the call and so forth.
127 *
128 * Note that not all the context structure is always filled with actual values
129 * but only the fields needed in a given context. */
130
131struct RedisModuleBlockedClient;
132struct RedisModuleUser;
133
134struct RedisModuleCtx {
135 void *getapifuncptr; /* NOTE: Must be the first field. */
136 struct RedisModule *module; /* Module reference. */
137 client *client; /* Client calling a command. */
138 struct RedisModuleBlockedClient *blocked_client; /* Blocked client for
139 thread safe context. */
140 struct AutoMemEntry *amqueue; /* Auto memory queue of objects to free. */
141 int amqueue_len; /* Number of slots in amqueue. */
142 int amqueue_used; /* Number of used slots in amqueue. */
143 int flags; /* REDISMODULE_CTX_... flags. */
144 void **postponed_arrays; /* To set with RM_ReplySetArrayLength(). */
145 int postponed_arrays_count; /* Number of entries in postponed_arrays. */
146 void *blocked_privdata; /* Privdata set when unblocking a client. */
147 RedisModuleString *blocked_ready_key; /* Key ready when the reply callback
148 gets called for clients blocked
149 on keys. */
150
151 /* Used if there is the REDISMODULE_CTX_KEYS_POS_REQUEST or
152 * REDISMODULE_CTX_CHANNEL_POS_REQUEST flag set. */
153 getKeysResult *keys_result;
154
155 struct RedisModulePoolAllocBlock *pa_head;
156 long long next_yield_time;
157
158 const struct RedisModuleUser *user; /* RedisModuleUser commands executed via
159 RM_Call should be executed as, if set */
160};
161typedef struct RedisModuleCtx RedisModuleCtx;
162
163#define REDISMODULE_CTX_NONE (0)
164#define REDISMODULE_CTX_AUTO_MEMORY (1<<0)
165#define REDISMODULE_CTX_KEYS_POS_REQUEST (1<<1)
166#define REDISMODULE_CTX_BLOCKED_REPLY (1<<2)
167#define REDISMODULE_CTX_BLOCKED_TIMEOUT (1<<3)
168#define REDISMODULE_CTX_THREAD_SAFE (1<<4)
169#define REDISMODULE_CTX_BLOCKED_DISCONNECTED (1<<5)
170#define REDISMODULE_CTX_TEMP_CLIENT (1<<6) /* Return client object to the pool
171 when the context is destroyed */
172#define REDISMODULE_CTX_NEW_CLIENT (1<<7) /* Free client object when the
173 context is destroyed */
174#define REDISMODULE_CTX_CHANNELS_POS_REQUEST (1<<8)
175#define REDISMODULE_CTX_COMMAND (1<<9) /* Context created to serve a command from call() or AOF (which calls cmd->proc directly) */
176
177
178/* This represents a Redis key opened with RM_OpenKey(). */
179struct RedisModuleKey {
180 RedisModuleCtx *ctx;
181 redisDb *db;
182 robj *key; /* Key name object. */
183 kvobj *kv; /* Key-Value object, or NULL if the key was not found. */
184 void *iter; /* Iterator. */
185 int mode; /* Opening mode. */
186
187 union {
188 struct {
189 /* List, use only if value->type == OBJ_LIST */
190 listTypeEntry entry; /* Current entry in iteration. */
191 long index; /* Current 0-based index in iteration. */
192 } list;
193 struct {
194 /* Zset iterator, use only if value->type == OBJ_ZSET */
195 uint32_t type; /* REDISMODULE_ZSET_RANGE_* */
196 zrangespec rs; /* Score range. */
197 zlexrangespec lrs; /* Lex range. */
198 uint32_t start; /* Start pos for positional ranges. */
199 uint32_t end; /* End pos for positional ranges. */
200 void *current; /* Zset iterator current node. */
201 int er; /* Zset iterator end reached flag
202 (true if end was reached). */
203 } zset;
204 struct {
205 /* Stream, use only if value->type == OBJ_STREAM */
206 streamID currentid; /* Current entry while iterating. */
207 int64_t numfieldsleft; /* Fields left to fetch for current entry. */
208 int signalready; /* Flag that signalKeyAsReady() is needed. */
209 } stream;
210 } u;
211};
212
213/* RedisModuleKey 'ztype' values. */
214#define REDISMODULE_ZSET_RANGE_NONE 0 /* This must always be 0. */
215#define REDISMODULE_ZSET_RANGE_LEX 1
216#define REDISMODULE_ZSET_RANGE_SCORE 2
217#define REDISMODULE_ZSET_RANGE_POS 3
218
219/* Function pointer type of a function representing a command inside
220 * a Redis module. */
221struct RedisModuleBlockedClient;
222typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, void **argv, int argc);
223typedef int (*RedisModuleAuthCallback)(RedisModuleCtx *ctx, void *username, void *password, RedisModuleString **err);
224typedef void (*RedisModuleDisconnectFunc) (RedisModuleCtx *ctx, struct RedisModuleBlockedClient *bc);
225
226/* This struct holds the information about a command registered by a module.*/
227struct RedisModuleCommand {
228 struct RedisModule *module;
229 RedisModuleCmdFunc func;
230 struct redisCommand *rediscmd;
231};
232typedef struct RedisModuleCommand RedisModuleCommand;
233
234#define REDISMODULE_REPLYFLAG_NONE 0
235#define REDISMODULE_REPLYFLAG_TOPARSE (1<<0) /* Protocol must be parsed. */
236#define REDISMODULE_REPLYFLAG_NESTED (1<<1) /* Nested reply object. No proto
237 or struct free. */
238
239/* Reply of RM_Call() function. The function is filled in a lazy
240 * way depending on the function called on the reply structure. By default
241 * only the type, proto and protolen are filled. */
242typedef struct CallReply RedisModuleCallReply;
243
244/* Structure to hold the module auth callback & the Module implementing it. */
245typedef struct RedisModuleAuthCtx {
246 struct RedisModule *module;
247 RedisModuleAuthCallback auth_cb;
248} RedisModuleAuthCtx;
249
250/* Structure representing a blocked client. We get a pointer to such
251 * an object when blocking from modules. */
252typedef struct RedisModuleBlockedClient {
253 client *client; /* Pointer to the blocked client. or NULL if the client
254 was destroyed during the life of this object. */
255 RedisModule *module; /* Module blocking the client. */
256 RedisModuleCmdFunc reply_callback; /* Reply callback on normal completion.*/
257 RedisModuleAuthCallback auth_reply_cb; /* Reply callback on completing blocking
258 module authentication. */
259 RedisModuleCmdFunc timeout_callback; /* Reply callback on timeout. */
260 RedisModuleDisconnectFunc disconnect_callback; /* Called on disconnection.*/
261 void (*free_privdata)(RedisModuleCtx*,void*);/* privdata cleanup callback.*/
262 void *privdata; /* Module private data that may be used by the reply
263 or timeout callback. It is set via the
264 RedisModule_UnblockClient() API. */
265 client *thread_safe_ctx_client; /* Fake client to be used for thread safe
266 context so that no lock is required. */
267 client *reply_client; /* Fake client used to accumulate replies
268 in thread safe contexts. */
269 int dbid; /* Database number selected by the original client. */
270 int blocked_on_keys; /* If blocked via RM_BlockClientOnKeys(). */
271 int unblocked; /* Already on the moduleUnblocked list. */
272 monotime background_timer; /* Timer tracking the start of background work */
273 uint64_t background_duration; /* Current command background time duration.
274 Used for measuring latency of blocking cmds */
275 int blocked_on_keys_explicit_unblock; /* Set to 1 only in the case of an explicit RM_Unblock on
276 * a client that is blocked on keys. In this case we will
277 * call the timeout call back from within
278 * moduleHandleBlockedClients which runs from the main thread */
279} RedisModuleBlockedClient;
280
281/* This is a list of Module Auth Contexts. Each time a Module registers a callback, a new ctx is
282 * added to this list. Multiple modules can register auth callbacks and the same Module can have
283 * multiple auth callbacks. */
284static list *moduleAuthCallbacks;
285
286static pthread_mutex_t moduleUnblockedClientsMutex = PTHREAD_MUTEX_INITIALIZER;
287static list *moduleUnblockedClients;
288
289/* Pool for temporary client objects. Creating and destroying a client object is
290 * costly. We manage a pool of clients to avoid this cost. Pool expands when
291 * more clients are needed and shrinks when unused. Please see modulesCron()
292 * for more details. */
293static client **moduleTempClients;
294static size_t moduleTempClientCap = 0;
295static size_t moduleTempClientCount = 0; /* Client count in pool */
296static size_t moduleTempClientMinCount = 0; /* Min client count in pool since
297 the last cron. */
298
299/* We need a mutex that is unlocked / relocked in beforeSleep() in order to
300 * allow thread safe contexts to execute commands at a safe moment. */
301static pthread_mutex_t moduleGIL = PTHREAD_MUTEX_INITIALIZER;
302
303/* Function pointer type for keyspace event notification subscriptions from modules. */
304typedef int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key);
305
306/* Function pointer type for post jobs */
307typedef void (*RedisModulePostNotificationJobFunc) (RedisModuleCtx *ctx, void *pd);
308
309/* Keyspace notification subscriber information.
310 * See RM_SubscribeToKeyspaceEvents() for more information. */
311typedef struct RedisModuleKeyspaceSubscriber {
312 /* The module subscribed to the event */
313 RedisModule *module;
314 /* Notification callback in the module*/
315 RedisModuleNotificationFunc notify_callback;
316 /* A bit mask of the events the module is interested in */
317 int event_mask;
318 /* Active flag set on entry, to avoid reentrant subscribers
319 * calling themselves */
320 int active;
321} RedisModuleKeyspaceSubscriber;
322
323typedef struct RedisModulePostExecUnitJob {
324 /* The module subscribed to the event */
325 RedisModule *module;
326 RedisModulePostNotificationJobFunc callback;
327 void *pd;
328 void (*free_pd)(void*);
329 int dbid;
330} RedisModulePostExecUnitJob;
331
332/* The module keyspace notification subscribers list */
333static list *moduleKeyspaceSubscribers;
334
335/* The module post keyspace jobs list */
336static list *modulePostExecUnitJobs;
337
338/* Data structures related to the exported dictionary data structure. */
339typedef struct RedisModuleDict {
340 rax *rax; /* The radix tree. */
341} RedisModuleDict;
342
343typedef struct RedisModuleDictIter {
344 RedisModuleDict *dict;
345 raxIterator ri;
346} RedisModuleDictIter;
347
348typedef struct RedisModuleCommandFilterCtx {
349 RedisModuleString **argv;
350 int argv_len;
351 int argc;
352 client *c;
353} RedisModuleCommandFilterCtx;
354
355typedef void (*RedisModuleCommandFilterFunc) (RedisModuleCommandFilterCtx *filter);
356
357typedef struct RedisModuleCommandFilter {
358 /* The module that registered the filter */
359 RedisModule *module;
360 /* Filter callback function */
361 RedisModuleCommandFilterFunc callback;
362 /* REDISMODULE_CMDFILTER_* flags */
363 int flags;
364} RedisModuleCommandFilter;
365
366/* Registered filters */
367static list *moduleCommandFilters;
368
369typedef void (*RedisModuleForkDoneHandler) (int exitcode, int bysignal, void *user_data);
370
371static struct RedisModuleForkInfo {
372 RedisModuleForkDoneHandler done_handler;
373 void* done_handler_user_data;
374} moduleForkInfo = {0};
375
376typedef struct RedisModuleServerInfoData {
377 rax *rax; /* parsed info data. */
378} RedisModuleServerInfoData;
379
380typedef struct RedisModuleConfigIterator {
381 dictIterator *di; /* Iterator for the configs dict. */
382 sds pattern; /* Pattern to filter configs by name. */
383 int is_glob; /* Is the pattern a glob-pattern or a fixed string? */
384} RedisModuleConfigIterator;
385
386/* Flags for moduleCreateArgvFromUserFormat(). */
387#define REDISMODULE_ARGV_REPLICATE (1<<0)
388#define REDISMODULE_ARGV_NO_AOF (1<<1)
389#define REDISMODULE_ARGV_NO_REPLICAS (1<<2)
390#define REDISMODULE_ARGV_RESP_3 (1<<3)
391#define REDISMODULE_ARGV_RESP_AUTO (1<<4)
392#define REDISMODULE_ARGV_RUN_AS_USER (1<<5)
393#define REDISMODULE_ARGV_SCRIPT_MODE (1<<6)
394#define REDISMODULE_ARGV_NO_WRITES (1<<7)
395#define REDISMODULE_ARGV_CALL_REPLIES_AS_ERRORS (1<<8)
396#define REDISMODULE_ARGV_RESPECT_DENY_OOM (1<<9)
397#define REDISMODULE_ARGV_DRY_RUN (1<<10)
398#define REDISMODULE_ARGV_ALLOW_BLOCK (1<<11)
399
400/* Determine whether Redis should signal modified key implicitly.
401 * In case 'ctx' has no 'module' member (and therefore no module->options),
402 * we assume default behavior, that is, Redis signals.
403 * (see RM_GetThreadSafeContext) */
404#define SHOULD_SIGNAL_MODIFIED_KEYS(ctx) \
405 ((ctx)->module? !((ctx)->module->options & REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED) : 1)
406
407/* Server events hooks data structures and defines: this modules API
408 * allow modules to subscribe to certain events in Redis, such as
409 * the start and end of an RDB or AOF save, the change of role in replication,
410 * and similar other events. */
411
412typedef struct RedisModuleEventListener {
413 RedisModule *module;
414 RedisModuleEvent event;
415 RedisModuleEventCallback callback;
416} RedisModuleEventListener;
417
418list *RedisModule_EventListeners; /* Global list of all the active events. */
419
420/* Data structures related to the redis module users */
421
422/* This is the object returned by RM_CreateModuleUser(). The module API is
423 * able to create users, set ACLs to such users, and later authenticate
424 * clients using such newly created users. */
425typedef struct RedisModuleUser {
426 user *user; /* Reference to the real redis user */
427 int free_user; /* Indicates that user should also be freed when this object is freed */
428} RedisModuleUser;
429
430/* Data structures related to redis module configurations */
431/* The function signatures for module config get callbacks. These are identical to the ones exposed in redismodule.h. */
432typedef RedisModuleString * (*RedisModuleConfigGetStringFunc)(const char *name, void *privdata);
433typedef long long (*RedisModuleConfigGetNumericFunc)(const char *name, void *privdata);
434typedef int (*RedisModuleConfigGetBoolFunc)(const char *name, void *privdata);
435typedef int (*RedisModuleConfigGetEnumFunc)(const char *name, void *privdata);
436/* The function signatures for module config set callbacks. These are identical to the ones exposed in redismodule.h. */
437typedef int (*RedisModuleConfigSetStringFunc)(const char *name, RedisModuleString *val, void *privdata, RedisModuleString **err);
438typedef int (*RedisModuleConfigSetNumericFunc)(const char *name, long long val, void *privdata, RedisModuleString **err);
439typedef int (*RedisModuleConfigSetBoolFunc)(const char *name, int val, void *privdata, RedisModuleString **err);
440typedef int (*RedisModuleConfigSetEnumFunc)(const char *name, int val, void *privdata, RedisModuleString **err);
441/* Apply signature, identical to redismodule.h */
442typedef int (*RedisModuleConfigApplyFunc)(RedisModuleCtx *ctx, void *privdata, RedisModuleString **err);
443
444/* Struct representing a module config. These are stored in a list in the module struct */
445struct ModuleConfig {
446 sds name; /* Fullname of the config (as it appears in the config file) */
447 sds alias; /* Optional alias for the configuration. NULL if none exists */
448
449 int unprefixedFlag; /* Indicates if the REDISMODULE_CONFIG_UNPREFIXED flag was set.
450 * If the configuration name was prefixed,during get_fn/set_fn
451 * callbacks, it should be reported without the prefix */
452
453 void *privdata; /* Optional data passed into the module config callbacks */
454 union get_fn { /* The get callback specified by the module */
455 RedisModuleConfigGetStringFunc get_string;
456 RedisModuleConfigGetNumericFunc get_numeric;
457 RedisModuleConfigGetBoolFunc get_bool;
458 RedisModuleConfigGetEnumFunc get_enum;
459 } get_fn;
460 union set_fn { /* The set callback specified by the module */
461 RedisModuleConfigSetStringFunc set_string;
462 RedisModuleConfigSetNumericFunc set_numeric;
463 RedisModuleConfigSetBoolFunc set_bool;
464 RedisModuleConfigSetEnumFunc set_enum;
465 } set_fn;
466 RedisModuleConfigApplyFunc apply_fn;
467 RedisModule *module;
468};
469
470typedef struct RedisModuleAsyncRMCallPromise{
471 size_t ref_count;
472 void *private_data;
473 RedisModule *module;
474 RedisModuleOnUnblocked on_unblocked;
475 client *c;
476 RedisModuleCtx *ctx;
477} RedisModuleAsyncRMCallPromise;
478
479/* --------------------------------------------------------------------------
480 * Prototypes
481 * -------------------------------------------------------------------------- */
482
483void RM_FreeCallReply(RedisModuleCallReply *reply);
484void RM_CloseKey(RedisModuleKey *key);
485void autoMemoryCollect(RedisModuleCtx *ctx);
486robj **moduleCreateArgvFromUserFormat(const char *cmdname, const char *fmt, int *argcp, int *flags, va_list ap);
487void RM_ZsetRangeStop(RedisModuleKey *kp);
488static void zsetKeyReset(RedisModuleKey *key);
489static void moduleInitKeyTypeSpecific(RedisModuleKey *key);
490void RM_FreeDict(RedisModuleCtx *ctx, RedisModuleDict *d);
491void RM_FreeServerInfo(RedisModuleCtx *ctx, RedisModuleServerInfoData *data);
492void RM_ConfigIteratorRelease(RedisModuleCtx *ctx, RedisModuleConfigIterator *iter);
493void RM_ClusterFreeSlotRanges(RedisModuleCtx *ctx, RedisModuleSlotRangeArray *slots);
494
495/* Helpers for RM_SetCommandInfo. */
496static int moduleValidateCommandInfo(const RedisModuleCommandInfo *info);
497static int64_t moduleConvertKeySpecsFlags(int64_t flags, int from_api);
498static int moduleValidateCommandArgs(RedisModuleCommandArg *args,
499 const RedisModuleCommandInfoVersion *version);
500static struct redisCommandArg *moduleCopyCommandArgs(RedisModuleCommandArg *args,
501 const RedisModuleCommandInfoVersion *version);
502static redisCommandArgType moduleConvertArgType(RedisModuleCommandArgType type, int *error);
503static int moduleConvertArgFlags(int flags);
504void moduleCreateContext(RedisModuleCtx *out_ctx, RedisModule *module, int ctx_flags);
505
506/* Common helper functions. */
507int moduleVerifyResourceName(const char *name);
508
509/* --------------------------------------------------------------------------
510 * ## Heap allocation raw functions
511 *
512 * Memory allocated with these functions are taken into account by Redis key
513 * eviction algorithms and are reported in Redis memory usage information.
514 * -------------------------------------------------------------------------- */
515
516/* Use like malloc(). Memory allocated with this function is reported in
517 * Redis INFO memory, used for keys eviction according to maxmemory settings
518 * and in general is taken into account as memory allocated by Redis.
519 * You should avoid using malloc().
520 * This function panics if unable to allocate enough memory. */
521void *RM_Alloc(size_t bytes) {
522 /* Use 'zmalloc_usable()' instead of 'zmalloc()' to allow the compiler
523 * to recognize the additional memory size, which means that modules can
524 * use the memory reported by 'RM_MallocUsableSize()' safely. In theory this
525 * isn't really needed since this API can't be inlined (not even for embedded
526 * modules like TLS (we use function pointers for module APIs), and the API doesn't
527 * have the malloc_size attribute, but it's hard to predict how smart future compilers
528 * will be, so better safe than sorry. */
529 return zmalloc_usable(bytes,NULL);
530}
531
532/* Similar to RM_Alloc, but returns NULL in case of allocation failure, instead
533 * of panicking. */
534void *RM_TryAlloc(size_t bytes) {
535 return ztrymalloc_usable(bytes,NULL);
536}
537
538/* Use like calloc(). Memory allocated with this function is reported in
539 * Redis INFO memory, used for keys eviction according to maxmemory settings
540 * and in general is taken into account as memory allocated by Redis.
541 * You should avoid using calloc() directly. */
542void *RM_Calloc(size_t nmemb, size_t size) {
543 return zcalloc_usable(nmemb*size,NULL);
544}
545
546/* Similar to RM_Calloc, but returns NULL in case of allocation failure, instead
547 * of panicking. */
548void *RM_TryCalloc(size_t nmemb, size_t size) {
549 return ztrycalloc_usable(nmemb*size,NULL);
550}
551
552/* Use like realloc() for memory obtained with RedisModule_Alloc(). */
553void* RM_Realloc(void *ptr, size_t bytes) {
554 return zrealloc_usable(ptr,bytes,NULL,NULL);
555}
556
557/* Similar to RM_Realloc, but returns NULL in case of allocation failure,
558 * instead of panicking. */
559void *RM_TryRealloc(void *ptr, size_t bytes) {
560 return ztryrealloc_usable(ptr,bytes,NULL,NULL);
561}
562
563/* Use like free() for memory obtained by RedisModule_Alloc() and
564 * RedisModule_Realloc(). However you should never try to free with
565 * RedisModule_Free() memory allocated with malloc() inside your module. */
566void RM_Free(void *ptr) {
567 zfree(ptr);
568}
569
570/* Like strdup() but returns memory allocated with RedisModule_Alloc(). */
571char *RM_Strdup(const char *str) {
572 return zstrdup(str);
573}
574
575/* --------------------------------------------------------------------------
576 * Pool allocator
577 * -------------------------------------------------------------------------- */
578
579/* Release the chain of blocks used for pool allocations. */
580void poolAllocRelease(RedisModuleCtx *ctx) {
581 RedisModulePoolAllocBlock *head = ctx->pa_head, *next;
582
583 while(head != NULL) {
584 next = head->next;
585 zfree(head);
586 head = next;
587 }
588 ctx->pa_head = NULL;
589}
590
591/* Return heap allocated memory that will be freed automatically when the
592 * module callback function returns. Mostly suitable for small allocations
593 * that are short living and must be released when the callback returns
594 * anyway. The returned memory is aligned to the architecture word size
595 * if at least word size bytes are requested, otherwise it is just
596 * aligned to the next power of two, so for example a 3 bytes request is
597 * 4 bytes aligned while a 2 bytes request is 2 bytes aligned.
598 *
599 * There is no realloc style function since when this is needed to use the
600 * pool allocator is not a good idea.
601 *
602 * The function returns NULL if `bytes` is 0. */
603void *RM_PoolAlloc(RedisModuleCtx *ctx, size_t bytes) {
604 if (bytes == 0) return NULL;
605 RedisModulePoolAllocBlock *b = ctx->pa_head;
606 size_t left = b ? b->size - b->used : 0;
607
608 /* Fix alignment. */
609 if (left >= bytes) {
610 size_t alignment = REDISMODULE_POOL_ALLOC_ALIGN;
611 while (bytes < alignment && alignment/2 >= bytes) alignment /= 2;
612 if (b->used % alignment)
613 b->used += alignment - (b->used % alignment);
614 left = (b->used > b->size) ? 0 : b->size - b->used;
615 }
616
617 /* Create a new block if needed. */
618 if (left < bytes) {
619 size_t blocksize = REDISMODULE_POOL_ALLOC_MIN_SIZE;
620 if (blocksize < bytes) blocksize = bytes;
621 b = zmalloc(sizeof(*b) + blocksize);
622 b->size = blocksize;
623 b->used = 0;
624 b->next = ctx->pa_head;
625 ctx->pa_head = b;
626 }
627
628 char *retval = b->memory + b->used;
629 b->used += bytes;
630 return retval;
631}
632
633/* --------------------------------------------------------------------------
634 * Helpers for modules API implementation
635 * -------------------------------------------------------------------------- */
636
637client *moduleAllocTempClient(void) {
638 client *c = NULL;
639
640 if (moduleTempClientCount > 0) {
641 c = moduleTempClients[--moduleTempClientCount];
642 if (moduleTempClientCount < moduleTempClientMinCount)
643 moduleTempClientMinCount = moduleTempClientCount;
644 } else {
645 c = createClient(NULL);
646 c->flags |= CLIENT_MODULE;
647 c->user = NULL; /* Root user */
648 }
649 return c;
650}
651
652static void freeRedisModuleAsyncRMCallPromise(RedisModuleAsyncRMCallPromise *promise) {
653 if (--promise->ref_count > 0) {
654 return;
655 }
656 /* When the promise is finally freed it can not have a client attached to it.
657 * Either releasing the client or RM_CallReplyPromiseAbort would have removed it. */
658 serverAssert(!promise->c);
659 zfree(promise);
660}
661
662void moduleReleaseTempClient(client *c) {
663 if (moduleTempClientCount == moduleTempClientCap) {
664 moduleTempClientCap = moduleTempClientCap ? moduleTempClientCap*2 : 32;
665 moduleTempClients = zrealloc(moduleTempClients, sizeof(c)*moduleTempClientCap);
666 }
667 clearClientConnectionState(c);
668 listEmpty(c->reply);
669 c->reply_bytes = 0;
670 c->duration = 0;
671 resetClient(c, -1);
672 serverAssert(c->all_argv_len_sum == 0);
673 c->bufpos = 0;
674 c->flags = CLIENT_MODULE;
675 c->user = NULL; /* Root user */
676 c->cmd = c->lastcmd = c->realcmd = NULL;
677 if (c->bstate.async_rm_call_handle) {
678 RedisModuleAsyncRMCallPromise *promise = c->bstate.async_rm_call_handle;
679 promise->c = NULL; /* Remove the client from the promise so it will no longer be possible to abort it. */
680 freeRedisModuleAsyncRMCallPromise(promise);
681 c->bstate.async_rm_call_handle = NULL;
682 }
683 moduleTempClients[moduleTempClientCount++] = c;
684}
685
686/* Create an empty key of the specified type. `key` must point to a key object
687 * opened for writing where the `.value` member is set to NULL because the
688 * key was found to be non existing.
689 *
690 * On success REDISMODULE_OK is returned and the key is populated with
691 * the value of the specified type. The function fails and returns
692 * REDISMODULE_ERR if:
693 *
694 * 1. The key is not open for writing.
695 * 2. The key is not empty.
696 * 3. The specified type is unknown.
697 */
698int moduleCreateEmptyKey(RedisModuleKey *key, int type) {
699 robj *obj;
700
701 /* The key must be open for writing and non existing to proceed. */
702 if (!(key->mode & REDISMODULE_WRITE) || key->kv)
703 return REDISMODULE_ERR;
704
705 switch(type) {
706 case REDISMODULE_KEYTYPE_LIST:
707 obj = createListListpackObject();
708 break;
709 case REDISMODULE_KEYTYPE_ZSET:
710 obj = createZsetListpackObject();
711 break;
712 case REDISMODULE_KEYTYPE_HASH:
713 obj = createHashObject();
714 break;
715 case REDISMODULE_KEYTYPE_STREAM:
716 obj = createStreamObject();
717 break;
718 default: return REDISMODULE_ERR;
719 }
720
721 key->kv = dbAdd(key->db, key->key, &obj);
722 moduleInitKeyTypeSpecific(key);
723 return REDISMODULE_OK;
724}
725
726/* Frees key->iter and sets it to NULL. */
727static void moduleFreeKeyIterator(RedisModuleKey *key) {
728 serverAssert(key->iter != NULL);
729 switch (key->kv->type) {
730 case OBJ_LIST:
731 listTypeResetIterator(key->iter);
732 zfree(key->iter);
733 break;
734 case OBJ_STREAM:
735 streamIteratorStop(key->iter);
736 zfree(key->iter);
737 break;
738 default: serverAssert(0); /* No key->iter for other types. */
739 }
740 key->iter = NULL;
741}
742
743/* Callback for listTypeTryConversion().
744 * Frees list iterator and sets it to NULL. */
745static void moduleFreeListIterator(void *data) {
746 RedisModuleKey *key = (RedisModuleKey*)data;
747 serverAssert(key->kv->type == OBJ_LIST);
748 if (key->iter) moduleFreeKeyIterator(key);
749}
750
751/* This function is called in low-level API implementation functions in order
752 * to check if the value associated with the key remained empty after an
753 * operation that removed elements from an aggregate data type.
754 *
755 * If this happens, the key is deleted from the DB and the key object state
756 * is set to the right one in order to be targeted again by write operations
757 * possibly recreating the key if needed.
758 *
759 * The function returns 1 if the key value object is found empty and is
760 * deleted, otherwise 0 is returned. */
761int moduleDelKeyIfEmpty(RedisModuleKey *key) {
762 if (!(key->mode & REDISMODULE_WRITE) || key->kv == NULL) return 0;
763 int isempty;
764 robj *o = key->kv;
765
766 switch(o->type) {
767 case OBJ_LIST: isempty = listTypeLength(o) == 0; break;
768 case OBJ_SET: isempty = setTypeSize(o) == 0; break;
769 case OBJ_ZSET: isempty = zsetLength(o) == 0; break;
770 case OBJ_HASH: isempty = hashTypeLength(o, 0) == 0; break;
771 case OBJ_STREAM: isempty = streamLength(o) == 0; break;
772 default: isempty = 0;
773 }
774
775 if (isempty) {
776 if (key->iter) moduleFreeKeyIterator(key);
777 dbDelete(key->db,key->key);
778 key->kv = NULL;
779 return 1;
780 } else {
781 return 0;
782 }
783}
784
785/* --------------------------------------------------------------------------
786 * Service API exported to modules
787 *
788 * Note that all the exported APIs are called RM_<funcname> in the core
789 * and RedisModule_<funcname> in the module side (defined as function
790 * pointers in redismodule.h). In this way the dynamic linker does not
791 * mess with our global function pointers, overriding it with the symbols
792 * defined in the main executable having the same names.
793 * -------------------------------------------------------------------------- */
794
795int RM_GetApi(const char *funcname, void **targetPtrPtr) {
796 /* Lookup the requested module API and store the function pointer into the
797 * target pointer. The function returns REDISMODULE_ERR if there is no such
798 * named API, otherwise REDISMODULE_OK.
799 *
800 * This function is not meant to be used by modules developer, it is only
801 * used implicitly by including redismodule.h. */
802 dictEntry *he = dictFind(server.moduleapi, funcname);
803 if (!he) return REDISMODULE_ERR;
804 *targetPtrPtr = dictGetVal(he);
805 return REDISMODULE_OK;
806}
807
808void modulePostExecutionUnitOperations(void) {
809 if (server.execution_nesting)
810 return;
811
812 if (server.busy_module_yield_flags) {
813 blockingOperationEnds();
814 server.busy_module_yield_flags = BUSY_MODULE_YIELD_NONE;
815 if (server.current_client)
816 unprotectClient(server.current_client);
817 unblockPostponedClients();
818 }
819}
820
821/* Free the context after the user function was called. */
822void moduleFreeContext(RedisModuleCtx *ctx) {
823 /* See comment in moduleCreateContext */
824 if (!(ctx->flags & (REDISMODULE_CTX_THREAD_SAFE|REDISMODULE_CTX_COMMAND))) {
825 exitExecutionUnit();
826 postExecutionUnitOperations();
827 }
828 autoMemoryCollect(ctx);
829 poolAllocRelease(ctx);
830 if (ctx->postponed_arrays) {
831 zfree(ctx->postponed_arrays);
832 ctx->postponed_arrays_count = 0;
833 serverLog(LL_WARNING,
834 "API misuse detected in module %s: "
835 "RedisModule_ReplyWith*(REDISMODULE_POSTPONED_LEN) "
836 "not matched by the same number of RedisModule_SetReply*Len() "
837 "calls.",
838 ctx->module->name);
839 }
840 /* If this context has a temp client, we return it back to the pool.
841 * If this context created a new client (e.g detached context), we free it.
842 * If the client is assigned manually, e.g ctx->client = someClientInstance,
843 * none of these flags will be set and we do not attempt to free it. */
844 if (ctx->flags & REDISMODULE_CTX_TEMP_CLIENT)
845 moduleReleaseTempClient(ctx->client);
846 else if (ctx->flags & REDISMODULE_CTX_NEW_CLIENT)
847 freeClient(ctx->client);
848}
849
850static CallReply *moduleParseReply(client *c, RedisModuleCtx *ctx) {
851 /* Convert the result of the Redis command into a module reply. */
852 sds proto = sdsnewlen(c->buf,c->bufpos);
853 c->bufpos = 0;
854 while(listLength(c->reply)) {
855 clientReplyBlock *o = listNodeValue(listFirst(c->reply));
856
857 proto = sdscatlen(proto,o->buf,o->used);
858 listDelNode(c->reply,listFirst(c->reply));
859 }
860 CallReply *reply = callReplyCreate(proto, c->deferred_reply_errors, ctx);
861 c->deferred_reply_errors = NULL; /* now the responsibility of the reply object. */
862 return reply;
863}
864
865void moduleCallCommandUnblockedHandler(client *c) {
866 RedisModuleCtx ctx;
867 RedisModuleAsyncRMCallPromise *promise = c->bstate.async_rm_call_handle;
868 serverAssert(promise);
869 RedisModule *module = promise->module;
870 if (!promise->on_unblocked) {
871 moduleReleaseTempClient(c);
872 return; /* module did not set any unblock callback. */
873 }
874 moduleCreateContext(&ctx, module, REDISMODULE_CTX_TEMP_CLIENT);
875 selectDb(ctx.client, c->db->id);
876
877 CallReply *reply = moduleParseReply(c, NULL);
878 module->in_call++;
879 promise->on_unblocked(&ctx, reply, promise->private_data);
880 module->in_call--;
881
882 moduleFreeContext(&ctx);
883 moduleReleaseTempClient(c);
884}
885
886/* Create a module ctx and keep track of the nesting level.
887 *
888 * Note: When creating ctx for threads (RM_GetThreadSafeContext and
889 * RM_GetDetachedThreadSafeContext) we do not bump up the nesting level
890 * because we only need to track of nesting level in the main thread
891 * (only the main thread uses propagatePendingCommands) */
892void moduleCreateContext(RedisModuleCtx *out_ctx, RedisModule *module, int ctx_flags) {
893 memset(out_ctx, 0 ,sizeof(RedisModuleCtx));
894 out_ctx->getapifuncptr = (void*)(unsigned long)&RM_GetApi;
895 out_ctx->module = module;
896 out_ctx->flags = ctx_flags;
897 if (ctx_flags & REDISMODULE_CTX_TEMP_CLIENT)
898 out_ctx->client = moduleAllocTempClient();
899 else if (ctx_flags & REDISMODULE_CTX_NEW_CLIENT)
900 out_ctx->client = createClient(NULL);
901
902 /* Calculate the initial yield time for long blocked contexts.
903 * in loading we depend on the server hz, but in other cases we also wait
904 * for busy_reply_threshold.
905 * Note that in theory we could have started processing BUSY_MODULE_YIELD_EVENTS
906 * sooner, and only delay the processing for clients till the busy_reply_threshold,
907 * but this carries some overheads of frequently marking clients with BLOCKED_POSTPONE
908 * and releasing them, i.e. if modules only block for short periods. */
909 if (server.loading)
910 out_ctx->next_yield_time = getMonotonicUs() + 1000000 / server.hz;
911 else
912 out_ctx->next_yield_time = getMonotonicUs() + server.busy_reply_threshold * 1000;
913
914 /* Increment the execution_nesting counter (module is about to execute some code),
915 * except in the following cases:
916 * 1. We came here from cmd->proc (either call() or AOF load).
917 * In the former, the counter has been already incremented from within
918 * call() and in the latter we don't care about execution_nesting
919 * 2. If we are running in a thread (execution_nesting will be dealt with
920 * when locking/unlocking the GIL) */
921 if (!(ctx_flags & (REDISMODULE_CTX_THREAD_SAFE|REDISMODULE_CTX_COMMAND))) {
922 enterExecutionUnit(1, 0);
923 }
924}
925
926/* This Redis command binds the normal Redis command invocation with commands
927 * exported by modules. */
928void RedisModuleCommandDispatcher(client *c) {
929 RedisModuleCommand *cp = c->cmd->module_cmd;
930 RedisModuleCtx ctx;
931 moduleCreateContext(&ctx, cp->module, REDISMODULE_CTX_COMMAND);
932
933 ctx.client = c;
934 cp->func(&ctx,(void**)c->argv,c->argc);
935 moduleFreeContext(&ctx);
936
937 /* In some cases processMultibulkBuffer uses sdsMakeRoomFor to
938 * expand the query buffer, and in order to avoid a big object copy
939 * the query buffer SDS may be used directly as the SDS string backing
940 * the client argument vectors: sometimes this will result in the SDS
941 * string having unused space at the end. Later if a module takes ownership
942 * of the RedisString, such space will be wasted forever. Inside the
943 * Redis core this is not a problem because tryObjectEncoding() is called
944 * before storing strings in the key space. Here we need to do it
945 * for the module. */
946 for (int i = 0; i < c->argc; i++) {
947 /* Only do the work if the module took ownership of the object:
948 * in that case the refcount is no longer 1. */
949 if (c->argv[i]->refcount > 1)
950 trimStringObjectIfNeeded(c->argv[i], 0);
951 }
952}
953
954/* This function returns the list of keys, with the same interface as the
955 * 'getkeys' function of the native commands, for module commands that exported
956 * the "getkeys-api" flag during the registration. This is done when the
957 * list of keys are not at fixed positions, so that first/last/step cannot
958 * be used.
959 *
960 * In order to accomplish its work, the module command is called, flagging
961 * the context in a way that the command can recognize this is a special
962 * "get keys" call by calling RedisModule_IsKeysPositionRequest(ctx). */
963int moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, getKeysResult *result) {
964 RedisModuleCommand *cp = cmd->module_cmd;
965 RedisModuleCtx ctx;
966 moduleCreateContext(&ctx, cp->module, REDISMODULE_CTX_KEYS_POS_REQUEST);
967
968 /* Initialize getKeysResult */
969 getKeysPrepareResult(result, MAX_KEYS_BUFFER);
970 ctx.keys_result = result;
971
972 cp->func(&ctx,(void**)argv,argc);
973 /* We currently always use the array allocated by RM_KeyAtPos() and don't try
974 * to optimize for the pre-allocated buffer.
975 */
976 moduleFreeContext(&ctx);
977 return result->numkeys;
978}
979
980/* This function returns the list of channels, with the same interface as
981 * moduleGetCommandKeysViaAPI, for modules that declare "getchannels-api"
982 * during registration. Unlike keys, this is the only way to declare channels. */
983int moduleGetCommandChannelsViaAPI(struct redisCommand *cmd, robj **argv, int argc, getKeysResult *result) {
984 RedisModuleCommand *cp = cmd->module_cmd;
985 RedisModuleCtx ctx;
986 moduleCreateContext(&ctx, cp->module, REDISMODULE_CTX_CHANNELS_POS_REQUEST);
987
988 /* Initialize getKeysResult */
989 getKeysPrepareResult(result, MAX_KEYS_BUFFER);
990 ctx.keys_result = result;
991
992 cp->func(&ctx,(void**)argv,argc);
993 /* We currently always use the array allocated by RM_RM_ChannelAtPosWithFlags() and don't try
994 * to optimize for the pre-allocated buffer. */
995 moduleFreeContext(&ctx);
996 return result->numkeys;
997}
998
999/* --------------------------------------------------------------------------
1000 * ## Commands API
1001 *
1002 * These functions are used to implement custom Redis commands.
1003 *
1004 * For examples, see https://redis.io/docs/latest/develop/reference/modules/.
1005 * -------------------------------------------------------------------------- */
1006
1007/* Return non-zero if a module command, that was declared with the
1008 * flag "getkeys-api", is called in a special way to get the keys positions
1009 * and not to get executed. Otherwise zero is returned. */
1010int RM_IsKeysPositionRequest(RedisModuleCtx *ctx) {
1011 return (ctx->flags & REDISMODULE_CTX_KEYS_POS_REQUEST) != 0;
1012}
1013
1014/* When a module command is called in order to obtain the position of
1015 * keys, since it was flagged as "getkeys-api" during the registration,
1016 * the command implementation checks for this special call using the
1017 * RedisModule_IsKeysPositionRequest() API and uses this function in
1018 * order to report keys.
1019 *
1020 * The supported flags are the ones used by RM_SetCommandInfo, see REDISMODULE_CMD_KEY_*.
1021 *
1022 *
1023 * The following is an example of how it could be used:
1024 *
1025 * if (RedisModule_IsKeysPositionRequest(ctx)) {
1026 * RedisModule_KeyAtPosWithFlags(ctx, 2, REDISMODULE_CMD_KEY_RO | REDISMODULE_CMD_KEY_ACCESS);
1027 * RedisModule_KeyAtPosWithFlags(ctx, 1, REDISMODULE_CMD_KEY_RW | REDISMODULE_CMD_KEY_UPDATE | REDISMODULE_CMD_KEY_ACCESS);
1028 * }
1029 *
1030 * Note: in the example above the get keys API could have been handled by key-specs (preferred).
1031 * Implementing the getkeys-api is required only when is it not possible to declare key-specs that cover all keys.
1032 *
1033 */
1034void RM_KeyAtPosWithFlags(RedisModuleCtx *ctx, int pos, int flags) {
1035 if (!(ctx->flags & REDISMODULE_CTX_KEYS_POS_REQUEST) || !ctx->keys_result) return;
1036 if (pos <= 0) return;
1037
1038 getKeysResult *res = ctx->keys_result;
1039
1040 /* Check overflow */
1041 if (res->numkeys == res->size) {
1042 int newsize = res->size + (res->size > 8192 ? 8192 : res->size);
1043 getKeysPrepareResult(res, newsize);
1044 }
1045
1046 res->keys[res->numkeys].pos = pos;
1047 res->keys[res->numkeys].flags = moduleConvertKeySpecsFlags(flags, 1);
1048 res->numkeys++;
1049}
1050
1051/* This API existed before RM_KeyAtPosWithFlags was added, now deprecated and
1052 * can be used for compatibility with older versions, before key-specs and flags
1053 * were introduced. */
1054void RM_KeyAtPos(RedisModuleCtx *ctx, int pos) {
1055 /* Default flags require full access */
1056 int flags = moduleConvertKeySpecsFlags(CMD_KEY_FULL_ACCESS, 0);
1057 RM_KeyAtPosWithFlags(ctx, pos, flags);
1058}
1059
1060/* Return non-zero if a module command, that was declared with the
1061 * flag "getchannels-api", is called in a special way to get the channel positions
1062 * and not to get executed. Otherwise zero is returned. */
1063int RM_IsChannelsPositionRequest(RedisModuleCtx *ctx) {
1064 return (ctx->flags & REDISMODULE_CTX_CHANNELS_POS_REQUEST) != 0;
1065}
1066
1067/* When a module command is called in order to obtain the position of
1068 * channels, since it was flagged as "getchannels-api" during the
1069 * registration, the command implementation checks for this special call
1070 * using the RedisModule_IsChannelsPositionRequest() API and uses this
1071 * function in order to report the channels.
1072 *
1073 * The supported flags are:
1074 * * REDISMODULE_CMD_CHANNEL_SUBSCRIBE: This command will subscribe to the channel.
1075 * * REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE: This command will unsubscribe from this channel.
1076 * * REDISMODULE_CMD_CHANNEL_PUBLISH: This command will publish to this channel.
1077 * * REDISMODULE_CMD_CHANNEL_PATTERN: Instead of acting on a specific channel, will act on any
1078 * channel specified by the pattern. This is the same access
1079 * used by the PSUBSCRIBE and PUNSUBSCRIBE commands available
1080 * in Redis. Not intended to be used with PUBLISH permissions.
1081 *
1082 * The following is an example of how it could be used:
1083 *
1084 * if (RedisModule_IsChannelsPositionRequest(ctx)) {
1085 * RedisModule_ChannelAtPosWithFlags(ctx, 1, REDISMODULE_CMD_CHANNEL_SUBSCRIBE | REDISMODULE_CMD_CHANNEL_PATTERN);
1086 * RedisModule_ChannelAtPosWithFlags(ctx, 1, REDISMODULE_CMD_CHANNEL_PUBLISH);
1087 * }
1088 *
1089 * Note: One usage of declaring channels is for evaluating ACL permissions. In this context,
1090 * unsubscribing is always allowed, so commands will only be checked against subscribe and
1091 * publish permissions. This is preferred over using RM_ACLCheckChannelPermissions, since
1092 * it allows the ACLs to be checked before the command is executed. */
1093void RM_ChannelAtPosWithFlags(RedisModuleCtx *ctx, int pos, int flags) {
1094 if (!(ctx->flags & REDISMODULE_CTX_CHANNELS_POS_REQUEST) || !ctx->keys_result) return;
1095 if (pos <= 0) return;
1096
1097 getKeysResult *res = ctx->keys_result;
1098
1099 /* Check overflow */
1100 if (res->numkeys == res->size) {
1101 int newsize = res->size + (res->size > 8192 ? 8192 : res->size);
1102 getKeysPrepareResult(res, newsize);
1103 }
1104
1105 int new_flags = 0;
1106 if (flags & REDISMODULE_CMD_CHANNEL_SUBSCRIBE) new_flags |= CMD_CHANNEL_SUBSCRIBE;
1107 if (flags & REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE) new_flags |= CMD_CHANNEL_UNSUBSCRIBE;
1108 if (flags & REDISMODULE_CMD_CHANNEL_PUBLISH) new_flags |= CMD_CHANNEL_PUBLISH;
1109 if (flags & REDISMODULE_CMD_CHANNEL_PATTERN) new_flags |= CMD_CHANNEL_PATTERN;
1110
1111 res->keys[res->numkeys].pos = pos;
1112 res->keys[res->numkeys].flags = new_flags;
1113 res->numkeys++;
1114}
1115
1116/* Returns 1 if name is valid, otherwise returns 0.
1117 *
1118 * We want to block some chars in module command names that we know can
1119 * mess things up.
1120 *
1121 * There are these characters:
1122 * ' ' (space) - issues with old inline protocol.
1123 * '\r', '\n' (newline) - can mess up the protocol on acl error replies.
1124 * '|' - sub-commands.
1125 * '@' - ACL categories.
1126 * '=', ',' - info and client list fields (':' handled by getSafeInfoString).
1127 * */
1128int isCommandNameValid(const char *name) {
1129 const char *block_chars = " \r\n|@=,";
1130
1131 if (strpbrk(name, block_chars))
1132 return 0;
1133 return 1;
1134}
1135
1136/* Helper for RM_CreateCommand(). Turns a string representing command
1137 * flags into the command flags used by the Redis core.
1138 *
1139 * It returns the set of flags, or -1 if unknown flags are found. */
1140int64_t commandFlagsFromString(char *s) {
1141 int count, j;
1142 int64_t flags = 0;
1143 sds *tokens = sdssplitlen(s,strlen(s)," ",1,&count);
1144 for (j = 0; j < count; j++) {
1145 char *t = tokens[j];
1146 if (!strcasecmp(t,"write")) flags |= CMD_WRITE;
1147 else if (!strcasecmp(t,"readonly")) flags |= CMD_READONLY;
1148 else if (!strcasecmp(t,"admin")) flags |= CMD_ADMIN;
1149 else if (!strcasecmp(t,"deny-oom")) flags |= CMD_DENYOOM;
1150 else if (!strcasecmp(t,"deny-script")) flags |= CMD_NOSCRIPT;
1151 else if (!strcasecmp(t,"allow-loading")) flags |= CMD_LOADING;
1152 else if (!strcasecmp(t,"pubsub")) flags |= CMD_PUBSUB;
1153 else if (!strcasecmp(t,"random")) { /* Deprecated. Silently ignore. */ }
1154 else if (!strcasecmp(t,"blocking")) flags |= CMD_BLOCKING;
1155 else if (!strcasecmp(t,"allow-stale")) flags |= CMD_STALE;
1156 else if (!strcasecmp(t,"no-monitor")) flags |= CMD_SKIP_MONITOR;
1157 else if (!strcasecmp(t,"no-slowlog")) flags |= CMD_SKIP_SLOWLOG;
1158 else if (!strcasecmp(t,"fast")) flags |= CMD_FAST;
1159 else if (!strcasecmp(t,"no-auth")) flags |= CMD_NO_AUTH;
1160 else if (!strcasecmp(t,"may-replicate")) flags |= CMD_MAY_REPLICATE;
1161 else if (!strcasecmp(t,"getkeys-api")) flags |= CMD_MODULE_GETKEYS;
1162 else if (!strcasecmp(t,"getchannels-api")) flags |= CMD_MODULE_GETCHANNELS;
1163 else if (!strcasecmp(t,"no-cluster")) flags |= CMD_MODULE_NO_CLUSTER;
1164 else if (!strcasecmp(t,"no-mandatory-keys")) flags |= CMD_NO_MANDATORY_KEYS;
1165 else if (!strcasecmp(t,"allow-busy")) flags |= CMD_ALLOW_BUSY;
1166 else if (!strcasecmp(t,"internal")) flags |= (CMD_INTERNAL|CMD_NOSCRIPT); /* We also disallow internal commands in scripts. */
1167 else if (!strcasecmp(t,"touches-arbitrary-keys")) flags |= CMD_TOUCHES_ARBITRARY_KEYS;
1168 else break;
1169 }
1170 sdsfreesplitres(tokens,count);
1171 if (j != count) return -1; /* Some token not processed correctly. */
1172 return flags;
1173}
1174
1175RedisModuleCommand *moduleCreateCommandProxy(struct RedisModule *module, sds declared_name, sds fullname, RedisModuleCmdFunc cmdfunc, int64_t flags, int firstkey, int lastkey, int keystep);
1176
1177/* Register a new command in the Redis server, that will be handled by
1178 * calling the function pointer 'cmdfunc' using the RedisModule calling
1179 * convention.
1180 *
1181 * The function returns REDISMODULE_ERR in these cases:
1182 * - If creation of module command is called outside the RedisModule_OnLoad.
1183 * - The specified command is already busy.
1184 * - The command name contains some chars that are not allowed.
1185 * - A set of invalid flags were passed.
1186 *
1187 * Otherwise REDISMODULE_OK is returned and the new command is registered.
1188 *
1189 * This function must be called during the initialization of the module
1190 * inside the RedisModule_OnLoad() function. Calling this function outside
1191 * of the initialization function is not defined.
1192 *
1193 * The command function type is the following:
1194 *
1195 * int MyCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
1196 *
1197 * And is supposed to always return REDISMODULE_OK.
1198 *
1199 * The set of flags 'strflags' specify the behavior of the command, and should
1200 * be passed as a C string composed of space separated words, like for
1201 * example "write deny-oom". The set of flags are:
1202 *
1203 * * **"write"**: The command may modify the data set (it may also read
1204 * from it).
1205 * * **"readonly"**: The command returns data from keys but never writes.
1206 * * **"admin"**: The command is an administrative command (may change
1207 * replication or perform similar tasks).
1208 * * **"deny-oom"**: The command may use additional memory and should be
1209 * denied during out of memory conditions.
1210 * * **"deny-script"**: Don't allow this command in Lua scripts.
1211 * * **"allow-loading"**: Allow this command while the server is loading data.
1212 * Only commands not interacting with the data set
1213 * should be allowed to run in this mode. If not sure
1214 * don't use this flag.
1215 * * **"pubsub"**: The command publishes things on Pub/Sub channels.
1216 * * **"random"**: The command may have different outputs even starting
1217 * from the same input arguments and key values.
1218 * Starting from Redis 7.0 this flag has been deprecated.
1219 * Declaring a command as "random" can be done using
1220 * command tips, see https://redis.io/docs/latest/develop/reference/command-tips/.
1221 * * **"allow-stale"**: The command is allowed to run on slaves that don't
1222 * serve stale data. Don't use if you don't know what
1223 * this means.
1224 * * **"no-monitor"**: Don't propagate the command on monitor. Use this if
1225 * the command has sensitive data among the arguments.
1226 * * **"no-slowlog"**: Don't log this command in the slowlog. Use this if
1227 * the command has sensitive data among the arguments.
1228 * * **"fast"**: The command time complexity is not greater
1229 * than O(log(N)) where N is the size of the collection or
1230 * anything else representing the normal scalability
1231 * issue with the command.
1232 * * **"getkeys-api"**: The command implements the interface to return
1233 * the arguments that are keys. Used when start/stop/step
1234 * is not enough because of the command syntax.
1235 * * **"no-cluster"**: The command should not register in Redis Cluster
1236 * since is not designed to work with it because, for
1237 * example, is unable to report the position of the
1238 * keys, programmatically creates key names, or any
1239 * other reason.
1240 * * **"no-auth"**: This command can be run by an un-authenticated client.
1241 * Normally this is used by a command that is used
1242 * to authenticate a client.
1243 * * **"may-replicate"**: This command may generate replication traffic, even
1244 * though it's not a write command.
1245 * * **"no-mandatory-keys"**: All the keys this command may take are optional
1246 * * **"blocking"**: The command has the potential to block the client.
1247 * * **"allow-busy"**: Permit the command while the server is blocked either by
1248 * a script or by a slow module command, see
1249 * RM_Yield.
1250 * * **"getchannels-api"**: The command implements the interface to return
1251 * the arguments that are channels.
1252 * * **"internal"**: Internal command, one that should not be exposed to the user connections.
1253 * For example, module commands that are called by the modules,
1254 * commands that do not perform ACL validations (relying on earlier checks)
1255 * * **"touches-arbitrary-keys"**: This command may modify arbitrary keys (i.e. not provided via argv).
1256 * This flag is used so we don't wrap the replicated commands with MULTI/EXEC.
1257 *
1258 * The last three parameters specify which arguments of the new command are
1259 * Redis keys. See https://redis.io/commands/command for more information.
1260 *
1261 * * `firstkey`: One-based index of the first argument that's a key.
1262 * Position 0 is always the command name itself.
1263 * 0 for commands with no keys.
1264 * * `lastkey`: One-based index of the last argument that's a key.
1265 * Negative numbers refer to counting backwards from the last
1266 * argument (-1 means the last argument provided)
1267 * 0 for commands with no keys.
1268 * * `keystep`: Step between first and last key indexes.
1269 * 0 for commands with no keys.
1270 *
1271 * This information is used by ACL, Cluster and the `COMMAND` command.
1272 *
1273 * NOTE: The scheme described above serves a limited purpose and can
1274 * only be used to find keys that exist at constant indices.
1275 * For non-trivial key arguments, you may pass 0,0,0 and use
1276 * RedisModule_SetCommandInfo to set key specs using a more advanced scheme and use
1277 * RedisModule_SetCommandACLCategories to set Redis ACL categories of the commands. */
1278int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) {
1279 if (!ctx->module->onload)
1280 return REDISMODULE_ERR;
1281 int64_t flags = strflags ? commandFlagsFromString((char*)strflags) : 0;
1282 if (flags == -1) return REDISMODULE_ERR;
1283 if ((flags & CMD_MODULE_NO_CLUSTER) && server.cluster_enabled)
1284 return REDISMODULE_ERR;
1285
1286 /* We will encounter an error as above if cluster is enable */
1287 if (flags & CMD_MODULE_NO_CLUSTER)
1288 server.stat_cluster_incompatible_ops++;
1289
1290 /* Check if the command name is valid. */
1291 if (!isCommandNameValid(name))
1292 return REDISMODULE_ERR;
1293
1294 /* Check if the command name is busy. */
1295 if (lookupCommandByCString(name) != NULL)
1296 return REDISMODULE_ERR;
1297
1298 sds declared_name = sdsnew(name);
1299 RedisModuleCommand *cp = moduleCreateCommandProxy(ctx->module, declared_name, sdsdup(declared_name), cmdfunc, flags, firstkey, lastkey, keystep);
1300 cp->rediscmd->arity = cmdfunc ? -1 : -2; /* Default value, can be changed later via dedicated API */
1301
1302 pauseAllIOThreads();
1303 serverAssert(dictAdd(server.commands, sdsdup(declared_name), cp->rediscmd) == DICT_OK);
1304 serverAssert(dictAdd(server.orig_commands, sdsdup(declared_name), cp->rediscmd) == DICT_OK);
1305 resumeAllIOThreads();
1306
1307 cp->rediscmd->id = ACLGetCommandID(declared_name); /* ID used for ACL. */
1308 return REDISMODULE_OK;
1309}
1310
1311/* A proxy that help create a module command / subcommand.
1312 *
1313 * 'declared_name': it contains the sub_name, which is just the fullname for non-subcommands.
1314 * 'fullname': sds string representing the command fullname.
1315 *
1316 * Function will take the ownership of both 'declared_name' and 'fullname' SDS.
1317 */
1318RedisModuleCommand *moduleCreateCommandProxy(struct RedisModule *module, sds declared_name, sds fullname, RedisModuleCmdFunc cmdfunc, int64_t flags, int firstkey, int lastkey, int keystep) {
1319 struct redisCommand *rediscmd;
1320 RedisModuleCommand *cp;
1321
1322 /* Create a command "proxy", which is a structure that is referenced
1323 * in the command table, so that the generic command that works as
1324 * binding between modules and Redis, can know what function to call
1325 * and what the module is. */
1326 cp = zcalloc(sizeof(*cp));
1327 cp->module = module;
1328 cp->func = cmdfunc;
1329 cp->rediscmd = zcalloc(sizeof(*rediscmd));
1330 cp->rediscmd->declared_name = declared_name; /* SDS for module commands */
1331 cp->rediscmd->fullname = fullname;
1332 cp->rediscmd->group = COMMAND_GROUP_MODULE;
1333 cp->rediscmd->proc = RedisModuleCommandDispatcher;
1334 cp->rediscmd->flags = flags | CMD_MODULE;
1335 cp->rediscmd->module_cmd = cp;
1336 if (firstkey != 0) {
1337 cp->rediscmd->key_specs_num = 1;
1338 cp->rediscmd->key_specs = zcalloc(sizeof(keySpec));
1339 cp->rediscmd->key_specs[0].flags = CMD_KEY_FULL_ACCESS;
1340 if (flags & CMD_MODULE_GETKEYS)
1341 cp->rediscmd->key_specs[0].flags |= CMD_KEY_VARIABLE_FLAGS;
1342 cp->rediscmd->key_specs[0].begin_search_type = KSPEC_BS_INDEX;
1343 cp->rediscmd->key_specs[0].bs.index.pos = firstkey;
1344 cp->rediscmd->key_specs[0].find_keys_type = KSPEC_FK_RANGE;
1345 cp->rediscmd->key_specs[0].fk.range.lastkey = lastkey < 0 ? lastkey : (lastkey-firstkey);
1346 cp->rediscmd->key_specs[0].fk.range.keystep = keystep;
1347 cp->rediscmd->key_specs[0].fk.range.limit = 0;
1348 } else {
1349 cp->rediscmd->key_specs_num = 0;
1350 cp->rediscmd->key_specs = NULL;
1351 }
1352 populateCommandLegacyRangeSpec(cp->rediscmd);
1353 cp->rediscmd->microseconds = 0;
1354 cp->rediscmd->calls = 0;
1355 cp->rediscmd->rejected_calls = 0;
1356 cp->rediscmd->failed_calls = 0;
1357 return cp;
1358}
1359
1360/* Get an opaque structure, representing a module command, by command name.
1361 * This structure is used in some of the command-related APIs.
1362 *
1363 * NULL is returned in case of the following errors:
1364 *
1365 * * Command not found
1366 * * The command is not a module command
1367 * * The command doesn't belong to the calling module
1368 */
1369RedisModuleCommand *RM_GetCommand(RedisModuleCtx *ctx, const char *name) {
1370 struct redisCommand *cmd = lookupCommandByCString(name);
1371
1372 if (!cmd || !(cmd->flags & CMD_MODULE))
1373 return NULL;
1374
1375 RedisModuleCommand *cp = cmd->module_cmd;
1376 if (cp->module != ctx->module)
1377 return NULL;
1378
1379 return cp;
1380}
1381
1382/* Very similar to RedisModule_CreateCommand except that it is used to create
1383 * a subcommand, associated with another, container, command.
1384 *
1385 * Example: If a module has a configuration command, MODULE.CONFIG, then
1386 * GET and SET should be individual subcommands, while MODULE.CONFIG is
1387 * a command, but should not be registered with a valid `funcptr`:
1388 *
1389 * if (RedisModule_CreateCommand(ctx,"module.config",NULL,"",0,0,0) == REDISMODULE_ERR)
1390 * return REDISMODULE_ERR;
1391 *
1392 * RedisModuleCommand *parent = RedisModule_GetCommand(ctx,,"module.config");
1393 *
1394 * if (RedisModule_CreateSubcommand(parent,"set",cmd_config_set,"",0,0,0) == REDISMODULE_ERR)
1395 * return REDISMODULE_ERR;
1396 *
1397 * if (RedisModule_CreateSubcommand(parent,"get",cmd_config_get,"",0,0,0) == REDISMODULE_ERR)
1398 * return REDISMODULE_ERR;
1399 *
1400 * Returns REDISMODULE_OK on success and REDISMODULE_ERR in case of the following errors:
1401 *
1402 * * Error while parsing `strflags`
1403 * * Command is marked as `no-cluster` but cluster mode is enabled
1404 * * `parent` is already a subcommand (we do not allow more than one level of command nesting)
1405 * * `parent` is a command with an implementation (RedisModuleCmdFunc) (A parent command should be a pure container of subcommands)
1406 * * `parent` already has a subcommand called `name`
1407 * * Creating a subcommand is called outside of RedisModule_OnLoad.
1408 */
1409int RM_CreateSubcommand(RedisModuleCommand *parent, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) {
1410 if (!parent->module->onload)
1411 return REDISMODULE_ERR;
1412 int64_t flags = strflags ? commandFlagsFromString((char*)strflags) : 0;
1413 if (flags == -1) return REDISMODULE_ERR;
1414 if ((flags & CMD_MODULE_NO_CLUSTER) && server.cluster_enabled)
1415 return REDISMODULE_ERR;
1416
1417 /* We will encounter an error as above if cluster is enable */
1418 if (flags & CMD_MODULE_NO_CLUSTER)
1419 server.stat_cluster_incompatible_ops++;
1420
1421 struct redisCommand *parent_cmd = parent->rediscmd;
1422
1423 if (parent_cmd->parent)
1424 return REDISMODULE_ERR; /* We don't allow more than one level of subcommands */
1425
1426 RedisModuleCommand *parent_cp = parent_cmd->module_cmd;
1427 if (parent_cp->func)
1428 return REDISMODULE_ERR; /* A parent command should be a pure container of subcommands */
1429
1430 /* Check if the command name is valid. */
1431 if (!isCommandNameValid(name))
1432 return REDISMODULE_ERR;
1433
1434 /* Check if the command name is busy within the parent command. */
1435 sds declared_name = sdsnew(name);
1436 if (parent_cmd->subcommands_dict && lookupSubcommand(parent_cmd, declared_name) != NULL) {
1437 sdsfree(declared_name);
1438 return REDISMODULE_ERR;
1439 }
1440
1441 sds fullname = catSubCommandFullname(parent_cmd->fullname, name);
1442 RedisModuleCommand *cp = moduleCreateCommandProxy(parent->module, declared_name, fullname, cmdfunc, flags, firstkey, lastkey, keystep);
1443 cp->rediscmd->arity = -2;
1444
1445 commandAddSubcommand(parent_cmd, cp->rediscmd, name);
1446 return REDISMODULE_OK;
1447}
1448
1449/* Accessors of array elements of structs where the element size is stored
1450 * separately in the version struct. */
1451static RedisModuleCommandHistoryEntry *
1452moduleCmdHistoryEntryAt(const RedisModuleCommandInfoVersion *version,
1453 RedisModuleCommandHistoryEntry *entries, int index) {
1454 off_t offset = index * version->sizeof_historyentry;
1455 return (RedisModuleCommandHistoryEntry *)((char *)(entries) + offset);
1456}
1457static RedisModuleCommandKeySpec *
1458moduleCmdKeySpecAt(const RedisModuleCommandInfoVersion *version,
1459 RedisModuleCommandKeySpec *keyspecs, int index) {
1460 off_t offset = index * version->sizeof_keyspec;
1461 return (RedisModuleCommandKeySpec *)((char *)(keyspecs) + offset);
1462}
1463static RedisModuleCommandArg *
1464moduleCmdArgAt(const RedisModuleCommandInfoVersion *version,
1465 const RedisModuleCommandArg *args, int index) {
1466 off_t offset = index * version->sizeof_arg;
1467 return (RedisModuleCommandArg *)((char *)(args) + offset);
1468}
1469
1470/* Recursively populate the args structure (setting num_args to the number of
1471 * subargs) and return the number of args. */
1472int populateArgsStructure(struct redisCommandArg *args) {
1473 if (!args)
1474 return 0;
1475 int count = 0;
1476 while (args->name) {
1477 serverAssert(count < INT_MAX);
1478 args->num_args = populateArgsStructure(args->subargs);
1479 count++;
1480 args++;
1481 }
1482 return count;
1483}
1484
1485/* RedisModule_AddACLCategory can be used to add new ACL command categories. Category names
1486 * can only contain alphanumeric characters, underscores, or dashes. Categories can only be added
1487 * during the RedisModule_OnLoad function. Once a category has been added, it can not be removed.
1488 * Any module can register a command to any added categories using RedisModule_SetCommandACLCategories.
1489 *
1490 * Returns:
1491 * - REDISMODULE_OK on successfully adding the new ACL category.
1492 * - REDISMODULE_ERR on failure.
1493 *
1494 * On error the errno is set to:
1495 * - EINVAL if the name contains invalid characters.
1496 * - EBUSY if the category name already exists.
1497 * - ENOMEM if the number of categories reached the max limit of 64 categories.
1498 */
1499int RM_AddACLCategory(RedisModuleCtx *ctx, const char *name) {
1500 if (!ctx->module->onload) {
1501 errno = EINVAL;
1502 return REDISMODULE_ERR;
1503 }
1504
1505 if (moduleVerifyResourceName(name) == REDISMODULE_ERR) {
1506 errno = EINVAL;
1507 return REDISMODULE_ERR;
1508 }
1509
1510 if (ACLGetCommandCategoryFlagByName(name)) {
1511 errno = EBUSY;
1512 return REDISMODULE_ERR;
1513 }
1514
1515 if (ACLAddCommandCategory(name, 0)) {
1516 ctx->module->num_acl_categories_added++;
1517 return REDISMODULE_OK;
1518 } else {
1519 errno = ENOMEM;
1520 return REDISMODULE_ERR;
1521 }
1522}
1523
1524/* Helper for categoryFlagsFromString(). Attempts to find an acl flag representing the provided flag string
1525 * and adds that flag to acl_categories_flags if a match is found.
1526 *
1527 * Returns '1' if acl category flag is recognized or
1528 * returns '0' if not recognized */
1529int matchAclCategoryFlag(char *flag, int64_t *acl_categories_flags) {
1530 uint64_t this_flag = ACLGetCommandCategoryFlagByName(flag);
1531 if (this_flag) {
1532 *acl_categories_flags |= (int64_t) this_flag;
1533 return 1;
1534 }
1535 return 0; /* Unrecognized */
1536}
1537
1538/* Helper for RM_SetCommandACLCategories(). Turns a string representing acl category
1539 * flags into the acl category flags used by Redis ACL which allows users to access
1540 * the module commands by acl categories.
1541 *
1542 * It returns the set of acl flags, or -1 if unknown flags are found. */
1543int64_t categoryFlagsFromString(char *aclflags) {
1544 int count, j;
1545 int64_t acl_categories_flags = 0;
1546 sds *tokens = sdssplitlen(aclflags,strlen(aclflags)," ",1,&count);
1547 for (j = 0; j < count; j++) {
1548 char *t = tokens[j];
1549 if (!matchAclCategoryFlag(t, &acl_categories_flags)) {
1550 serverLog(LL_WARNING,"Unrecognized categories flag %s on module load", t);
1551 break;
1552 }
1553 }
1554 sdsfreesplitres(tokens,count);
1555 if (j != count) return -1; /* Some token not processed correctly. */
1556 return acl_categories_flags;
1557}
1558
1559/* RedisModule_SetCommandACLCategories can be used to set ACL categories to module
1560 * commands and subcommands. The set of ACL categories should be passed as
1561 * a space separated C string 'aclflags'.
1562 *
1563 * Example, the acl flags 'write slow' marks the command as part of the write and
1564 * slow ACL categories.
1565 *
1566 * On success REDISMODULE_OK is returned. On error REDISMODULE_ERR is returned.
1567 *
1568 * This function can only be called during the RedisModule_OnLoad function. If called
1569 * outside of this function, an error is returned.
1570 */
1571int RM_SetCommandACLCategories(RedisModuleCommand *command, const char *aclflags) {
1572 if (!command || !command->module || !command->module->onload) return REDISMODULE_ERR;
1573 int64_t categories_flags = aclflags ? categoryFlagsFromString((char*)aclflags) : 0;
1574 if (categories_flags == -1) return REDISMODULE_ERR;
1575 struct redisCommand *rcmd = command->rediscmd;
1576 rcmd->acl_categories = categories_flags; /* ACL categories flags for module command */
1577 command->module->num_commands_with_acl_categories++;
1578 return REDISMODULE_OK;
1579}
1580
1581/* Set additional command information.
1582 *
1583 * Affects the output of `COMMAND`, `COMMAND INFO` and `COMMAND DOCS`, Cluster,
1584 * ACL and is used to filter commands with the wrong number of arguments before
1585 * the call reaches the module code.
1586 *
1587 * This function can be called after creating a command using RM_CreateCommand
1588 * and fetching the command pointer using RM_GetCommand. The information can
1589 * only be set once for each command and has the following structure:
1590 *
1591 * typedef struct RedisModuleCommandInfo {
1592 * const RedisModuleCommandInfoVersion *version;
1593 * const char *summary;
1594 * const char *complexity;
1595 * const char *since;
1596 * RedisModuleCommandHistoryEntry *history;
1597 * const char *tips;
1598 * int arity;
1599 * RedisModuleCommandKeySpec *key_specs;
1600 * RedisModuleCommandArg *args;
1601 * } RedisModuleCommandInfo;
1602 *
1603 * All fields except `version` are optional. Explanation of the fields:
1604 *
1605 * - `version`: This field enables compatibility with different Redis versions.
1606 * Always set this field to REDISMODULE_COMMAND_INFO_VERSION.
1607 *
1608 * - `summary`: A short description of the command (optional).
1609 *
1610 * - `complexity`: Complexity description (optional).
1611 *
1612 * - `since`: The version where the command was introduced (optional).
1613 * Note: The version specified should be the module's, not Redis version.
1614 *
1615 * - `history`: An array of RedisModuleCommandHistoryEntry (optional), which is
1616 * a struct with the following fields:
1617 *
1618 * const char *since;
1619 * const char *changes;
1620 *
1621 * `since` is a version string and `changes` is a string describing the
1622 * changes. The array is terminated by a zeroed entry, i.e. an entry with
1623 * both strings set to NULL.
1624 *
1625 * - `tips`: A string of space-separated tips regarding this command, meant for
1626 * clients and proxies. See https://redis.io/docs/latest/develop/reference/command-tips/.
1627 *
1628 * - `arity`: Number of arguments, including the command name itself. A positive
1629 * number specifies an exact number of arguments and a negative number
1630 * specifies a minimum number of arguments, so use -N to say >= N. Redis
1631 * validates a call before passing it to a module, so this can replace an
1632 * arity check inside the module command implementation. A value of 0 (or an
1633 * omitted arity field) is equivalent to -2 if the command has sub commands
1634 * and -1 otherwise.
1635 *
1636 * - `key_specs`: An array of RedisModuleCommandKeySpec, terminated by an
1637 * element memset to zero. This is a scheme that tries to describe the
1638 * positions of key arguments better than the old RM_CreateCommand arguments
1639 * `firstkey`, `lastkey`, `keystep` and is needed if those three are not
1640 * enough to describe the key positions. There are two steps to retrieve key
1641 * positions: *begin search* (BS) in which index should find the first key and
1642 * *find keys* (FK) which, relative to the output of BS, describes how can we
1643 * will which arguments are keys. Additionally, there are key specific flags.
1644 *
1645 * Key-specs cause the triplet (firstkey, lastkey, keystep) given in
1646 * RM_CreateCommand to be recomputed, but it is still useful to provide
1647 * these three parameters in RM_CreateCommand, to better support old Redis
1648 * versions where RM_SetCommandInfo is not available.
1649 *
1650 * Note that key-specs don't fully replace the "getkeys-api" (see
1651 * RM_CreateCommand, RM_IsKeysPositionRequest and RM_KeyAtPosWithFlags) so
1652 * it may be a good idea to supply both key-specs and implement the
1653 * getkeys-api.
1654 *
1655 * A key-spec has the following structure:
1656 *
1657 * typedef struct RedisModuleCommandKeySpec {
1658 * const char *notes;
1659 * uint64_t flags;
1660 * RedisModuleKeySpecBeginSearchType begin_search_type;
1661 * union {
1662 * struct {
1663 * int pos;
1664 * } index;
1665 * struct {
1666 * const char *keyword;
1667 * int startfrom;
1668 * } keyword;
1669 * } bs;
1670 * RedisModuleKeySpecFindKeysType find_keys_type;
1671 * union {
1672 * struct {
1673 * int lastkey;
1674 * int keystep;
1675 * int limit;
1676 * } range;
1677 * struct {
1678 * int keynumidx;
1679 * int firstkey;
1680 * int keystep;
1681 * } keynum;
1682 * } fk;
1683 * } RedisModuleCommandKeySpec;
1684 *
1685 * Explanation of the fields of RedisModuleCommandKeySpec:
1686 *
1687 * * `notes`: Optional notes or clarifications about this key spec.
1688 *
1689 * * `flags`: A bitwise or of key-spec flags described below.
1690 *
1691 * * `begin_search_type`: This describes how the first key is discovered.
1692 * There are two ways to determine the first key:
1693 *
1694 * * `REDISMODULE_KSPEC_BS_UNKNOWN`: There is no way to tell where the
1695 * key args start.
1696 * * `REDISMODULE_KSPEC_BS_INDEX`: Key args start at a constant index.
1697 * * `REDISMODULE_KSPEC_BS_KEYWORD`: Key args start just after a
1698 * specific keyword.
1699 *
1700 * * `bs`: This is a union in which the `index` or `keyword` branch is used
1701 * depending on the value of the `begin_search_type` field.
1702 *
1703 * * `bs.index.pos`: The index from which we start the search for keys.
1704 * (`REDISMODULE_KSPEC_BS_INDEX` only.)
1705 *
1706 * * `bs.keyword.keyword`: The keyword (string) that indicates the
1707 * beginning of key arguments. (`REDISMODULE_KSPEC_BS_KEYWORD` only.)
1708 *
1709 * * `bs.keyword.startfrom`: An index in argv from which to start
1710 * searching. Can be negative, which means start search from the end,
1711 * in reverse. Example: -2 means to start in reverse from the
1712 * penultimate argument. (`REDISMODULE_KSPEC_BS_KEYWORD` only.)
1713 *
1714 * * `find_keys_type`: After the "begin search", this describes which
1715 * arguments are keys. The strategies are:
1716 *
1717 * * `REDISMODULE_KSPEC_BS_UNKNOWN`: There is no way to tell where the
1718 * key args are located.
1719 * * `REDISMODULE_KSPEC_FK_RANGE`: Keys end at a specific index (or
1720 * relative to the last argument).
1721 * * `REDISMODULE_KSPEC_FK_KEYNUM`: There's an argument that contains
1722 * the number of key args somewhere before the keys themselves.
1723 *
1724 * `find_keys_type` and `fk` can be omitted if this keyspec describes
1725 * exactly one key.
1726 *
1727 * * `fk`: This is a union in which the `range` or `keynum` branch is used
1728 * depending on the value of the `find_keys_type` field.
1729 *
1730 * * `fk.range` (for `REDISMODULE_KSPEC_FK_RANGE`): A struct with the
1731 * following fields:
1732 *
1733 * * `lastkey`: Index of the last key relative to the result of the
1734 * begin search step. Can be negative, in which case it's not
1735 * relative. -1 indicates the last argument, -2 one before the
1736 * last and so on.
1737 *
1738 * * `keystep`: How many arguments should we skip after finding a
1739 * key, in order to find the next one?
1740 *
1741 * * `limit`: If `lastkey` is -1, we use `limit` to stop the search
1742 * by a factor. 0 and 1 mean no limit. 2 means 1/2 of the
1743 * remaining args, 3 means 1/3, and so on.
1744 *
1745 * * `fk.keynum` (for `REDISMODULE_KSPEC_FK_KEYNUM`): A struct with the
1746 * following fields:
1747 *
1748 * * `keynumidx`: Index of the argument containing the number of
1749 * keys to come, relative to the result of the begin search step.
1750 *
1751 * * `firstkey`: Index of the fist key relative to the result of the
1752 * begin search step. (Usually it's just after `keynumidx`, in
1753 * which case it should be set to `keynumidx + 1`.)
1754 *
1755 * * `keystep`: How many arguments should we skip after finding a
1756 * key, in order to find the next one?
1757 *
1758 * Key-spec flags:
1759 *
1760 * The first four refer to what the command actually does with the *value or
1761 * metadata of the key*, and not necessarily the user data or how it affects
1762 * it. Each key-spec may must have exactly one of these. Any operation
1763 * that's not distinctly deletion, overwrite or read-only would be marked as
1764 * RW.
1765 *
1766 * * `REDISMODULE_CMD_KEY_RO`: Read-Only. Reads the value of the key, but
1767 * doesn't necessarily return it.
1768 *
1769 * * `REDISMODULE_CMD_KEY_RW`: Read-Write. Modifies the data stored in the
1770 * value of the key or its metadata.
1771 *
1772 * * `REDISMODULE_CMD_KEY_OW`: Overwrite. Overwrites the data stored in the
1773 * value of the key.
1774 *
1775 * * `REDISMODULE_CMD_KEY_RM`: Deletes the key.
1776 *
1777 * The next four refer to *user data inside the value of the key*, not the
1778 * metadata like LRU, type, cardinality. It refers to the logical operation
1779 * on the user's data (actual input strings or TTL), being
1780 * used/returned/copied/changed. It doesn't refer to modification or
1781 * returning of metadata (like type, count, presence of data). ACCESS can be
1782 * combined with one of the write operations INSERT, DELETE or UPDATE. Any
1783 * write that's not an INSERT or a DELETE would be UPDATE.
1784 *
1785 * * `REDISMODULE_CMD_KEY_ACCESS`: Returns, copies or uses the user data
1786 * from the value of the key.
1787 *
1788 * * `REDISMODULE_CMD_KEY_UPDATE`: Updates data to the value, new value may
1789 * depend on the old value.
1790 *
1791 * * `REDISMODULE_CMD_KEY_INSERT`: Adds data to the value with no chance of
1792 * modification or deletion of existing data.
1793 *
1794 * * `REDISMODULE_CMD_KEY_DELETE`: Explicitly deletes some content from the
1795 * value of the key.
1796 *
1797 * Other flags:
1798 *
1799 * * `REDISMODULE_CMD_KEY_NOT_KEY`: The key is not actually a key, but
1800 * should be routed in cluster mode as if it was a key.
1801 *
1802 * * `REDISMODULE_CMD_KEY_INCOMPLETE`: The keyspec might not point out all
1803 * the keys it should cover.
1804 *
1805 * * `REDISMODULE_CMD_KEY_VARIABLE_FLAGS`: Some keys might have different
1806 * flags depending on arguments.
1807 *
1808 * - `args`: An array of RedisModuleCommandArg, terminated by an element memset
1809 * to zero. RedisModuleCommandArg is a structure with at the fields described
1810 * below.
1811 *
1812 * typedef struct RedisModuleCommandArg {
1813 * const char *name;
1814 * RedisModuleCommandArgType type;
1815 * int key_spec_index;
1816 * const char *token;
1817 * const char *summary;
1818 * const char *since;
1819 * int flags;
1820 * struct RedisModuleCommandArg *subargs;
1821 * } RedisModuleCommandArg;
1822 *
1823 * Explanation of the fields:
1824 *
1825 * * `name`: Name of the argument.
1826 *
1827 * * `type`: The type of the argument. See below for details. The types
1828 * `REDISMODULE_ARG_TYPE_ONEOF` and `REDISMODULE_ARG_TYPE_BLOCK` require
1829 * an argument to have sub-arguments, i.e. `subargs`.
1830 *
1831 * * `key_spec_index`: If the `type` is `REDISMODULE_ARG_TYPE_KEY` you must
1832 * provide the index of the key-spec associated with this argument. See
1833 * `key_specs` above. If the argument is not a key, you may specify -1.
1834 *
1835 * * `token`: The token preceding the argument (optional). Example: the
1836 * argument `seconds` in `SET` has a token `EX`. If the argument consists
1837 * of only a token (for example `NX` in `SET`) the type should be
1838 * `REDISMODULE_ARG_TYPE_PURE_TOKEN` and `value` should be NULL.
1839 *
1840 * * `summary`: A short description of the argument (optional).
1841 *
1842 * * `since`: The first version which included this argument (optional).
1843 *
1844 * * `flags`: A bitwise or of the macros `REDISMODULE_CMD_ARG_*`. See below.
1845 *
1846 * * `value`: The display-value of the argument. This string is what should
1847 * be displayed when creating the command syntax from the output of
1848 * `COMMAND`. If `token` is not NULL, it should also be displayed.
1849 *
1850 * Explanation of `RedisModuleCommandArgType`:
1851 *
1852 * * `REDISMODULE_ARG_TYPE_STRING`: String argument.
1853 * * `REDISMODULE_ARG_TYPE_INTEGER`: Integer argument.
1854 * * `REDISMODULE_ARG_TYPE_DOUBLE`: Double-precision float argument.
1855 * * `REDISMODULE_ARG_TYPE_KEY`: String argument representing a keyname.
1856 * * `REDISMODULE_ARG_TYPE_PATTERN`: String, but regex pattern.
1857 * * `REDISMODULE_ARG_TYPE_UNIX_TIME`: Integer, but Unix timestamp.
1858 * * `REDISMODULE_ARG_TYPE_PURE_TOKEN`: Argument doesn't have a placeholder.
1859 * It's just a token without a value. Example: the `KEEPTTL` option of the
1860 * `SET` command.
1861 * * `REDISMODULE_ARG_TYPE_ONEOF`: Used when the user can choose only one of
1862 * a few sub-arguments. Requires `subargs`. Example: the `NX` and `XX`
1863 * options of `SET`.
1864 * * `REDISMODULE_ARG_TYPE_BLOCK`: Used when one wants to group together
1865 * several sub-arguments, usually to apply something on all of them, like
1866 * making the entire group "optional". Requires `subargs`. Example: the
1867 * `LIMIT offset count` parameters in `ZRANGE`.
1868 *
1869 * Explanation of the command argument flags:
1870 *
1871 * * `REDISMODULE_CMD_ARG_OPTIONAL`: The argument is optional (like GET in
1872 * the SET command).
1873 * * `REDISMODULE_CMD_ARG_MULTIPLE`: The argument may repeat itself (like
1874 * key in DEL).
1875 * * `REDISMODULE_CMD_ARG_MULTIPLE_TOKEN`: The argument may repeat itself,
1876 * and so does its token (like `GET pattern` in SORT).
1877 *
1878 * On success REDISMODULE_OK is returned. On error REDISMODULE_ERR is returned
1879 * and `errno` is set to EINVAL if invalid info was provided or EEXIST if info
1880 * has already been set. If the info is invalid, a warning is logged explaining
1881 * which part of the info is invalid and why. */
1882int RM_SetCommandInfo(RedisModuleCommand *command, const RedisModuleCommandInfo *info) {
1883 if (!moduleValidateCommandInfo(info)) {
1884 errno = EINVAL;
1885 return REDISMODULE_ERR;
1886 }
1887
1888 struct redisCommand *cmd = command->rediscmd;
1889
1890 /* Check if any info has already been set. Overwriting info involves freeing
1891 * the old info, which is not implemented. */
1892 if (cmd->summary || cmd->complexity || cmd->since || cmd->history ||
1893 cmd->tips || cmd->args ||
1894 !(cmd->key_specs_num == 0 ||
1895 /* Allow key spec populated from legacy (first,last,step) to exist. */
1896 (cmd->key_specs_num == 1 &&
1897 cmd->key_specs[0].begin_search_type == KSPEC_BS_INDEX &&
1898 cmd->key_specs[0].find_keys_type == KSPEC_FK_RANGE))) {
1899 errno = EEXIST;
1900 return REDISMODULE_ERR;
1901 }
1902
1903 if (info->summary) cmd->summary = zstrdup(info->summary);
1904 if (info->complexity) cmd->complexity = zstrdup(info->complexity);
1905 if (info->since) cmd->since = zstrdup(info->since);
1906
1907 const RedisModuleCommandInfoVersion *version = info->version;
1908 if (info->history) {
1909 size_t count = 0;
1910 while (moduleCmdHistoryEntryAt(version, info->history, count)->since)
1911 count++;
1912 serverAssert(count < SIZE_MAX / sizeof(commandHistory));
1913 cmd->history = zmalloc(sizeof(commandHistory) * (count + 1));
1914 for (size_t j = 0; j < count; j++) {
1915 RedisModuleCommandHistoryEntry *entry =
1916 moduleCmdHistoryEntryAt(version, info->history, j);
1917 cmd->history[j].since = zstrdup(entry->since);
1918 cmd->history[j].changes = zstrdup(entry->changes);
1919 }
1920 cmd->history[count].since = NULL;
1921 cmd->history[count].changes = NULL;
1922 cmd->num_history = count;
1923 }
1924
1925 if (info->tips) {
1926 int count;
1927 sds *tokens = sdssplitlen(info->tips, strlen(info->tips), " ", 1, &count);
1928 if (tokens) {
1929 cmd->tips = zmalloc(sizeof(char *) * (count + 1));
1930 for (int j = 0; j < count; j++) {
1931 cmd->tips[j] = zstrdup(tokens[j]);
1932 }
1933 cmd->tips[count] = NULL;
1934 cmd->num_tips = count;
1935 sdsfreesplitres(tokens, count);
1936 }
1937 }
1938
1939 if (info->arity) cmd->arity = info->arity;
1940
1941 if (info->key_specs) {
1942 /* Count and allocate the key specs. */
1943 size_t count = 0;
1944 while (moduleCmdKeySpecAt(version, info->key_specs, count)->begin_search_type)
1945 count++;
1946 serverAssert(count < INT_MAX);
1947 zfree(cmd->key_specs);
1948 cmd->key_specs = zmalloc(sizeof(keySpec) * count);
1949
1950 /* Copy the contents of the RedisModuleCommandKeySpec array. */
1951 cmd->key_specs_num = count;
1952 for (size_t j = 0; j < count; j++) {
1953 RedisModuleCommandKeySpec *spec =
1954 moduleCmdKeySpecAt(version, info->key_specs, j);
1955 cmd->key_specs[j].notes = spec->notes ? zstrdup(spec->notes) : NULL;
1956 cmd->key_specs[j].flags = moduleConvertKeySpecsFlags(spec->flags, 1);
1957 switch (spec->begin_search_type) {
1958 case REDISMODULE_KSPEC_BS_UNKNOWN:
1959 cmd->key_specs[j].begin_search_type = KSPEC_BS_UNKNOWN;
1960 break;
1961 case REDISMODULE_KSPEC_BS_INDEX:
1962 cmd->key_specs[j].begin_search_type = KSPEC_BS_INDEX;
1963 cmd->key_specs[j].bs.index.pos = spec->bs.index.pos;
1964 break;
1965 case REDISMODULE_KSPEC_BS_KEYWORD:
1966 cmd->key_specs[j].begin_search_type = KSPEC_BS_KEYWORD;
1967 cmd->key_specs[j].bs.keyword.keyword = zstrdup(spec->bs.keyword.keyword);
1968 cmd->key_specs[j].bs.keyword.startfrom = spec->bs.keyword.startfrom;
1969 break;
1970 default:
1971 /* Can't happen; stopped in moduleValidateCommandInfo(). */
1972 serverPanic("Unknown begin_search_type");
1973 }
1974
1975 switch (spec->find_keys_type) {
1976 case REDISMODULE_KSPEC_FK_OMITTED:
1977 /* Omitted field is shorthand to say that it's a single key. */
1978 cmd->key_specs[j].find_keys_type = KSPEC_FK_RANGE;
1979 cmd->key_specs[j].fk.range.lastkey = 0;
1980 cmd->key_specs[j].fk.range.keystep = 1;
1981 cmd->key_specs[j].fk.range.limit = 0;
1982 break;
1983 case REDISMODULE_KSPEC_FK_UNKNOWN:
1984 cmd->key_specs[j].find_keys_type = KSPEC_FK_UNKNOWN;
1985 break;
1986 case REDISMODULE_KSPEC_FK_RANGE:
1987 cmd->key_specs[j].find_keys_type = KSPEC_FK_RANGE;
1988 cmd->key_specs[j].fk.range.lastkey = spec->fk.range.lastkey;
1989 cmd->key_specs[j].fk.range.keystep = spec->fk.range.keystep;
1990 cmd->key_specs[j].fk.range.limit = spec->fk.range.limit;
1991 break;
1992 case REDISMODULE_KSPEC_FK_KEYNUM:
1993 cmd->key_specs[j].find_keys_type = KSPEC_FK_KEYNUM;
1994 cmd->key_specs[j].fk.keynum.keynumidx = spec->fk.keynum.keynumidx;
1995 cmd->key_specs[j].fk.keynum.firstkey = spec->fk.keynum.firstkey;
1996 cmd->key_specs[j].fk.keynum.keystep = spec->fk.keynum.keystep;
1997 break;
1998 default:
1999 /* Can't happen; stopped in moduleValidateCommandInfo(). */
2000 serverPanic("Unknown find_keys_type");
2001 }
2002 }
2003
2004 /* Update the legacy (first,last,step) spec and "movablekeys" flag used by the COMMAND command,
2005 * by trying to "glue" consecutive range key specs. */
2006 populateCommandLegacyRangeSpec(cmd);
2007 }
2008
2009 if (info->args) {
2010 cmd->args = moduleCopyCommandArgs(info->args, version);
2011 /* Populate arg.num_args with the number of subargs, recursively */
2012 cmd->num_args = populateArgsStructure(cmd->args);
2013 }
2014
2015 /* Fields added in future versions to be added here, under conditions like
2016 * `if (info->version >= 2) { access version 2 fields here }` */
2017
2018 return REDISMODULE_OK;
2019}
2020
2021/* Returns 1 if v is a power of two, 0 otherwise. */
2022static inline int isPowerOfTwo(uint64_t v) {
2023 return v && !(v & (v - 1));
2024}
2025
2026/* Returns 1 if the command info is valid and 0 otherwise. */
2027static int moduleValidateCommandInfo(const RedisModuleCommandInfo *info) {
2028 const RedisModuleCommandInfoVersion *version = info->version;
2029 if (!version) {
2030 serverLog(LL_WARNING, "Invalid command info: version missing");
2031 return 0;
2032 }
2033
2034 /* No validation for the fields summary, complexity, since, tips (strings or
2035 * NULL) and arity (any integer). */
2036
2037 /* History: If since is set, changes must also be set. */
2038 if (info->history) {
2039 for (size_t j = 0;
2040 moduleCmdHistoryEntryAt(version, info->history, j)->since;
2041 j++)
2042 {
2043 if (!moduleCmdHistoryEntryAt(version, info->history, j)->changes) {
2044 serverLog(LL_WARNING, "Invalid command info: history[%zd].changes missing", j);
2045 return 0;
2046 }
2047 }
2048 }
2049
2050 /* Key specs. */
2051 if (info->key_specs) {
2052 for (size_t j = 0;
2053 moduleCmdKeySpecAt(version, info->key_specs, j)->begin_search_type;
2054 j++)
2055 {
2056 RedisModuleCommandKeySpec *spec =
2057 moduleCmdKeySpecAt(version, info->key_specs, j);
2058 if (j >= INT_MAX) {
2059 serverLog(LL_WARNING, "Invalid command info: Too many key specs");
2060 return 0; /* redisCommand.key_specs_num is an int. */
2061 }
2062
2063 /* Flags. Exactly one flag in a group is set if and only if the
2064 * masked bits is a power of two. */
2065 uint64_t key_flags =
2066 REDISMODULE_CMD_KEY_RO | REDISMODULE_CMD_KEY_RW |
2067 REDISMODULE_CMD_KEY_OW | REDISMODULE_CMD_KEY_RM;
2068 uint64_t write_flags =
2069 REDISMODULE_CMD_KEY_INSERT | REDISMODULE_CMD_KEY_DELETE |
2070 REDISMODULE_CMD_KEY_UPDATE;
2071 if (!isPowerOfTwo(spec->flags & key_flags)) {
2072 serverLog(LL_WARNING,
2073 "Invalid command info: key_specs[%zd].flags: "
2074 "Exactly one of the flags RO, RW, OW, RM required", j);
2075 return 0;
2076 }
2077 if ((spec->flags & write_flags) != 0 &&
2078 !isPowerOfTwo(spec->flags & write_flags))
2079 {
2080 serverLog(LL_WARNING,
2081 "Invalid command info: key_specs[%zd].flags: "
2082 "INSERT, DELETE and UPDATE are mutually exclusive", j);
2083 return 0;
2084 }
2085
2086 switch (spec->begin_search_type) {
2087 case REDISMODULE_KSPEC_BS_UNKNOWN: break;
2088 case REDISMODULE_KSPEC_BS_INDEX: break;
2089 case REDISMODULE_KSPEC_BS_KEYWORD:
2090 if (spec->bs.keyword.keyword == NULL) {
2091 serverLog(LL_WARNING,
2092 "Invalid command info: key_specs[%zd].bs.keyword.keyword "
2093 "required when begin_search_type is KEYWORD", j);
2094 return 0;
2095 }
2096 break;
2097 default:
2098 serverLog(LL_WARNING,
2099 "Invalid command info: key_specs[%zd].begin_search_type: "
2100 "Invalid value %d", j, spec->begin_search_type);
2101 return 0;
2102 }
2103
2104 /* Validate find_keys_type. */
2105 switch (spec->find_keys_type) {
2106 case REDISMODULE_KSPEC_FK_OMITTED: break; /* short for RANGE {0,1,0} */
2107 case REDISMODULE_KSPEC_FK_UNKNOWN: break;
2108 case REDISMODULE_KSPEC_FK_RANGE: break;
2109 case REDISMODULE_KSPEC_FK_KEYNUM: break;
2110 default:
2111 serverLog(LL_WARNING,
2112 "Invalid command info: key_specs[%zd].find_keys_type: "
2113 "Invalid value %d", j, spec->find_keys_type);
2114 return 0;
2115 }
2116 }
2117 }
2118
2119 /* Args, subargs (recursive) */
2120 return moduleValidateCommandArgs(info->args, version);
2121}
2122
2123/* When from_api is true, converts from REDISMODULE_CMD_KEY_* flags to CMD_KEY_* flags.
2124 * When from_api is false, converts from CMD_KEY_* flags to REDISMODULE_CMD_KEY_* flags. */
2125static int64_t moduleConvertKeySpecsFlags(int64_t flags, int from_api) {
2126 int64_t out = 0;
2127 int64_t map[][2] = {
2128 {REDISMODULE_CMD_KEY_RO, CMD_KEY_RO},
2129 {REDISMODULE_CMD_KEY_RW, CMD_KEY_RW},
2130 {REDISMODULE_CMD_KEY_OW, CMD_KEY_OW},
2131 {REDISMODULE_CMD_KEY_RM, CMD_KEY_RM},
2132 {REDISMODULE_CMD_KEY_ACCESS, CMD_KEY_ACCESS},
2133 {REDISMODULE_CMD_KEY_INSERT, CMD_KEY_INSERT},
2134 {REDISMODULE_CMD_KEY_UPDATE, CMD_KEY_UPDATE},
2135 {REDISMODULE_CMD_KEY_DELETE, CMD_KEY_DELETE},
2136 {REDISMODULE_CMD_KEY_NOT_KEY, CMD_KEY_NOT_KEY},
2137 {REDISMODULE_CMD_KEY_INCOMPLETE, CMD_KEY_INCOMPLETE},
2138 {REDISMODULE_CMD_KEY_VARIABLE_FLAGS, CMD_KEY_VARIABLE_FLAGS},
2139 {0,0}};
2140
2141 int from_idx = from_api ? 0 : 1, to_idx = !from_idx;
2142 for (int i=0; map[i][0]; i++)
2143 if (flags & map[i][from_idx]) out |= map[i][to_idx];
2144 return out;
2145}
2146
2147/* Validates an array of RedisModuleCommandArg. Returns 1 if it's valid and 0 if
2148 * it's invalid. */
2149static int moduleValidateCommandArgs(RedisModuleCommandArg *args,
2150 const RedisModuleCommandInfoVersion *version) {
2151 if (args == NULL) return 1; /* Missing args is OK. */
2152 for (size_t j = 0; moduleCmdArgAt(version, args, j)->name != NULL; j++) {
2153 RedisModuleCommandArg *arg = moduleCmdArgAt(version, args, j);
2154 int arg_type_error = 0;
2155 moduleConvertArgType(arg->type, &arg_type_error);
2156 if (arg_type_error) {
2157 serverLog(LL_WARNING,
2158 "Invalid command info: Argument \"%s\": Undefined type %d",
2159 arg->name, arg->type);
2160 return 0;
2161 }
2162 if (arg->type == REDISMODULE_ARG_TYPE_PURE_TOKEN && !arg->token) {
2163 serverLog(LL_WARNING,
2164 "Invalid command info: Argument \"%s\": "
2165 "token required when type is PURE_TOKEN", args[j].name);
2166 return 0;
2167 }
2168
2169 if (arg->type == REDISMODULE_ARG_TYPE_KEY) {
2170 if (arg->key_spec_index < 0) {
2171 serverLog(LL_WARNING,
2172 "Invalid command info: Argument \"%s\": "
2173 "key_spec_index required when type is KEY",
2174 arg->name);
2175 return 0;
2176 }
2177 } else if (arg->key_spec_index != -1 && arg->key_spec_index != 0) {
2178 /* 0 is allowed for convenience, to allow it to be omitted in
2179 * compound struct literals on the form `.field = value`. */
2180 serverLog(LL_WARNING,
2181 "Invalid command info: Argument \"%s\": "
2182 "key_spec_index specified but type isn't KEY",
2183 arg->name);
2184 return 0;
2185 }
2186
2187 if (arg->flags & ~(_REDISMODULE_CMD_ARG_NEXT - 1)) {
2188 serverLog(LL_WARNING,
2189 "Invalid command info: Argument \"%s\": Invalid flags",
2190 arg->name);
2191 return 0;
2192 }
2193
2194 if (arg->type == REDISMODULE_ARG_TYPE_ONEOF ||
2195 arg->type == REDISMODULE_ARG_TYPE_BLOCK)
2196 {
2197 if (arg->subargs == NULL) {
2198 serverLog(LL_WARNING,
2199 "Invalid command info: Argument \"%s\": "
2200 "subargs required when type is ONEOF or BLOCK",
2201 arg->name);
2202 return 0;
2203 }
2204 if (!moduleValidateCommandArgs(arg->subargs, version)) return 0;
2205 } else {
2206 if (arg->subargs != NULL) {
2207 serverLog(LL_WARNING,
2208 "Invalid command info: Argument \"%s\": "
2209 "subargs specified but type isn't ONEOF nor BLOCK",
2210 arg->name);
2211 return 0;
2212 }
2213 }
2214 }
2215 return 1;
2216}
2217
2218/* Converts an array of RedisModuleCommandArg into a freshly allocated array of
2219 * struct redisCommandArg. */
2220static struct redisCommandArg *moduleCopyCommandArgs(RedisModuleCommandArg *args,
2221 const RedisModuleCommandInfoVersion *version) {
2222 size_t count = 0;
2223 while (moduleCmdArgAt(version, args, count)->name) count++;
2224 serverAssert(count < SIZE_MAX / sizeof(struct redisCommandArg));
2225 struct redisCommandArg *realargs = zcalloc((count+1) * sizeof(redisCommandArg));
2226
2227 for (size_t j = 0; j < count; j++) {
2228 RedisModuleCommandArg *arg = moduleCmdArgAt(version, args, j);
2229 realargs[j].name = zstrdup(arg->name);
2230 realargs[j].type = moduleConvertArgType(arg->type, NULL);
2231 if (arg->type == REDISMODULE_ARG_TYPE_KEY)
2232 realargs[j].key_spec_index = arg->key_spec_index;
2233 else
2234 realargs[j].key_spec_index = -1;
2235 if (arg->token) realargs[j].token = zstrdup(arg->token);
2236 if (arg->summary) realargs[j].summary = zstrdup(arg->summary);
2237 if (arg->since) realargs[j].since = zstrdup(arg->since);
2238 if (arg->deprecated_since) realargs[j].deprecated_since = zstrdup(arg->deprecated_since);
2239 if (arg->display_text) realargs[j].display_text = zstrdup(arg->display_text);
2240 realargs[j].flags = moduleConvertArgFlags(arg->flags);
2241 if (arg->subargs) realargs[j].subargs = moduleCopyCommandArgs(arg->subargs, version);
2242 }
2243 return realargs;
2244}
2245
2246static redisCommandArgType moduleConvertArgType(RedisModuleCommandArgType type, int *error) {
2247 if (error) *error = 0;
2248 switch (type) {
2249 case REDISMODULE_ARG_TYPE_STRING: return ARG_TYPE_STRING;
2250 case REDISMODULE_ARG_TYPE_INTEGER: return ARG_TYPE_INTEGER;
2251 case REDISMODULE_ARG_TYPE_DOUBLE: return ARG_TYPE_DOUBLE;
2252 case REDISMODULE_ARG_TYPE_KEY: return ARG_TYPE_KEY;
2253 case REDISMODULE_ARG_TYPE_PATTERN: return ARG_TYPE_PATTERN;
2254 case REDISMODULE_ARG_TYPE_UNIX_TIME: return ARG_TYPE_UNIX_TIME;
2255 case REDISMODULE_ARG_TYPE_PURE_TOKEN: return ARG_TYPE_PURE_TOKEN;
2256 case REDISMODULE_ARG_TYPE_ONEOF: return ARG_TYPE_ONEOF;
2257 case REDISMODULE_ARG_TYPE_BLOCK: return ARG_TYPE_BLOCK;
2258 default:
2259 if (error) *error = 1;
2260 return -1;
2261 }
2262}
2263
2264static int moduleConvertArgFlags(int flags) {
2265 int realflags = 0;
2266 if (flags & REDISMODULE_CMD_ARG_OPTIONAL) realflags |= CMD_ARG_OPTIONAL;
2267 if (flags & REDISMODULE_CMD_ARG_MULTIPLE) realflags |= CMD_ARG_MULTIPLE;
2268 if (flags & REDISMODULE_CMD_ARG_MULTIPLE_TOKEN) realflags |= CMD_ARG_MULTIPLE_TOKEN;
2269 return realflags;
2270}
2271
2272/* Return `struct RedisModule *` as `void *` to avoid exposing it outside of module.c. */
2273void *moduleGetHandleByName(char *modulename) {
2274 return dictFetchValue(modules,modulename);
2275}
2276
2277/* Returns 1 if `cmd` is a command of the module `modulename`. 0 otherwise. */
2278int moduleIsModuleCommand(void *module_handle, struct redisCommand *cmd) {
2279 if (cmd->proc != RedisModuleCommandDispatcher)
2280 return 0;
2281 if (module_handle == NULL)
2282 return 0;
2283 RedisModuleCommand *cp = cmd->module_cmd;
2284 return (cp->module == module_handle);
2285}
2286
2287/* --------------------------------------------------------------------------
2288 * ## Module information and time measurement
2289 * -------------------------------------------------------------------------- */
2290
2291int moduleListConfigMatch(void *config, void *name) {
2292 ModuleConfig *mc = (ModuleConfig *) config;
2293 /* Compare the provided name with the config's name and alias if it exists */
2294 return strcasecmp(mc->name, (char *) name) == 0 ||
2295 ((mc->alias) && strcasecmp(mc->alias, (char *) name) == 0);
2296}
2297
2298void moduleListFree(void *config) {
2299 ModuleConfig *module_config = (ModuleConfig *) config;
2300 sdsfree(module_config->name);
2301 sdsfree(module_config->alias);
2302 zfree(config);
2303}
2304
2305void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int apiver) {
2306 /* Called by RM_Init() to setup the `ctx->module` structure.
2307 *
2308 * This is an internal function, Redis modules developers don't need
2309 * to use it. */
2310 RedisModule *module;
2311
2312 if (ctx->module != NULL) return;
2313 module = zmalloc(sizeof(*module));
2314 module->name = sdsnew(name);
2315 module->ver = ver;
2316 module->apiver = apiver;
2317 module->types = listCreate();
2318 module->usedby = listCreate();
2319 module->using = listCreate();
2320 module->filters = listCreate();
2321 module->module_configs = listCreate();
2322 listSetMatchMethod(module->module_configs, moduleListConfigMatch);
2323 listSetFreeMethod(module->module_configs, moduleListFree);
2324 module->in_call = 0;
2325 module->configs_initialized = 0;
2326 module->in_hook = 0;
2327 module->options = 0;
2328 module->info_cb = 0;
2329 module->defrag_cb = 0;
2330 module->defrag_cb_2 = 0;
2331 module->defrag_start_cb = 0;
2332 module->defrag_end_cb = 0;
2333 module->loadmod = NULL;
2334 module->num_commands_with_acl_categories = 0;
2335 module->onload = 1;
2336 module->num_acl_categories_added = 0;
2337 ctx->module = module;
2338}
2339
2340/* Return non-zero if the module name is busy.
2341 * Otherwise zero is returned. */
2342int RM_IsModuleNameBusy(const char *name) {
2343 sds modulename = sdsnew(name);
2344 dictEntry *de = dictFind(modules,modulename);
2345 sdsfree(modulename);
2346 return de != NULL;
2347}
2348
2349/* Return the current UNIX time in milliseconds. */
2350mstime_t RM_Milliseconds(void) {
2351 return mstime();
2352}
2353
2354/* Return counter of micro-seconds relative to an arbitrary point in time. */
2355uint64_t RM_MonotonicMicroseconds(void) {
2356 return getMonotonicUs();
2357}
2358
2359/* Return the current UNIX time in microseconds */
2360ustime_t RM_Microseconds(void) {
2361 return ustime();
2362}
2363
2364/* Return the cached UNIX time in microseconds.
2365 * It is updated in the server cron job and before executing a command.
2366 * It is useful for complex call stacks, such as a command causing a
2367 * key space notification, causing a module to execute a RedisModule_Call,
2368 * causing another notification, etc.
2369 * It makes sense that all this callbacks would use the same clock. */
2370ustime_t RM_CachedMicroseconds(void) {
2371 return server.ustime;
2372}
2373
2374/* Mark a point in time that will be used as the start time to calculate
2375 * the elapsed execution time when RM_BlockedClientMeasureTimeEnd() is called.
2376 * Within the same command, you can call multiple times
2377 * RM_BlockedClientMeasureTimeStart() and RM_BlockedClientMeasureTimeEnd()
2378 * to accumulate independent time intervals to the background duration.
2379 * This method always return REDISMODULE_OK.
2380 *
2381 * This function is not thread safe, If used in module thread and blocked callback (possibly main thread)
2382 * simultaneously, it's recommended to protect them with lock owned by caller instead of GIL. */
2383int RM_BlockedClientMeasureTimeStart(RedisModuleBlockedClient *bc) {
2384 elapsedStart(&(bc->background_timer));
2385 return REDISMODULE_OK;
2386}
2387
2388/* Mark a point in time that will be used as the end time
2389 * to calculate the elapsed execution time.
2390 * On success REDISMODULE_OK is returned.
2391 * This method only returns REDISMODULE_ERR if no start time was
2392 * previously defined ( meaning RM_BlockedClientMeasureTimeStart was not called ).
2393 *
2394 * This function is not thread safe, If used in module thread and blocked callback (possibly main thread)
2395 * simultaneously, it's recommended to protect them with lock owned by caller instead of GIL. */
2396int RM_BlockedClientMeasureTimeEnd(RedisModuleBlockedClient *bc) {
2397 // If the counter is 0 then we haven't called RM_BlockedClientMeasureTimeStart
2398 if (!bc->background_timer)
2399 return REDISMODULE_ERR;
2400 bc->background_duration += elapsedUs(bc->background_timer);
2401 return REDISMODULE_OK;
2402}
2403
2404/* This API allows modules to let Redis process background tasks, and some
2405 * commands during long blocking execution of a module command.
2406 * The module can call this API periodically.
2407 * The flags is a bit mask of these:
2408 *
2409 * - `REDISMODULE_YIELD_FLAG_NONE`: No special flags, can perform some background
2410 * operations, but not process client commands.
2411 * - `REDISMODULE_YIELD_FLAG_CLIENTS`: Redis can also process client commands.
2412 *
2413 * The `busy_reply` argument is optional, and can be used to control the verbose
2414 * error string after the `-BUSY` error code.
2415 *
2416 * When the `REDISMODULE_YIELD_FLAG_CLIENTS` is used, Redis will only start
2417 * processing client commands after the time defined by the
2418 * `busy-reply-threshold` config, in which case Redis will start rejecting most
2419 * commands with `-BUSY` error, but allow the ones marked with the `allow-busy`
2420 * flag to be executed.
2421 * This API can also be used in thread safe context (while locked), and during
2422 * loading (in the `rdb_load` callback, in which case it'll reject commands with
2423 * the -LOADING error)
2424 */
2425void RM_Yield(RedisModuleCtx *ctx, int flags, const char *busy_reply) {
2426 static int yield_nesting = 0;
2427 /* Avoid nested calls to RM_Yield */
2428 if (yield_nesting)
2429 return;
2430 yield_nesting++;
2431
2432 long long now = getMonotonicUs();
2433 if (now >= ctx->next_yield_time) {
2434 /* In loading mode, there's no need to handle busy_module_yield_reply,
2435 * and busy_module_yield_flags, since redis is anyway rejecting all
2436 * commands with -LOADING. */
2437 if (server.loading) {
2438 /* Let redis process events */
2439 processEventsWhileBlocked();
2440 } else {
2441 const char *prev_busy_module_yield_reply = server.busy_module_yield_reply;
2442 server.busy_module_yield_reply = busy_reply;
2443 /* start the blocking operation if not already started. */
2444 if (!server.busy_module_yield_flags) {
2445 server.busy_module_yield_flags = BUSY_MODULE_YIELD_EVENTS;
2446 blockingOperationStarts();
2447 if (server.current_client)
2448 protectClient(server.current_client);
2449 }
2450 if (flags & REDISMODULE_YIELD_FLAG_CLIENTS)
2451 server.busy_module_yield_flags |= BUSY_MODULE_YIELD_CLIENTS;
2452
2453 /* Let redis process events */
2454 if (!pthread_equal(server.main_thread_id, pthread_self())) {
2455 /* If we are not in the main thread, we defer event loop processing to the main thread
2456 * after the main thread enters acquiring GIL state in order to protect the event
2457 * loop (ae.c) and avoid potential race conditions. */
2458
2459 int acquiring;
2460 atomicGet(server.module_gil_acquring, acquiring);
2461 if (!acquiring) {
2462 /* If the main thread has not yet entered the acquiring GIL state,
2463 * we attempt to wake it up and exit without waiting for it to
2464 * acquire the GIL. This avoids blocking the caller, allowing them to
2465 * continue with unfinished tasks before the next yield.
2466 * We assume the caller keeps the GIL locked. */
2467 if (write(server.module_pipe[1],"A",1) != 1) {
2468 /* Ignore the error, this is best-effort. */
2469 }
2470 } else {
2471 /* Release the GIL, yielding CPU to give the main thread an opportunity to start
2472 * event processing, and then acquire the GIL again until the main thread releases it. */
2473 moduleReleaseGIL();
2474 usleep(0);
2475 moduleAcquireGIL();
2476 }
2477 } else {
2478 /* If we are in the main thread, we can safely process events. */
2479 processEventsWhileBlocked();
2480 }
2481
2482 server.busy_module_yield_reply = prev_busy_module_yield_reply;
2483 /* Possibly restore the previous flags in case of two nested contexts
2484 * that use this API with different flags, but keep the first bit
2485 * (PROCESS_EVENTS) set, so we know to call blockingOperationEnds on time. */
2486 server.busy_module_yield_flags &= ~BUSY_MODULE_YIELD_CLIENTS;
2487 }
2488
2489 /* decide when the next event should fire. */
2490 ctx->next_yield_time = now + 1000000 / server.hz;
2491 }
2492 yield_nesting--;
2493}
2494
2495/* Set flags defining capabilities or behavior bit flags.
2496 *
2497 * REDISMODULE_OPTIONS_HANDLE_IO_ERRORS:
2498 * Generally, modules don't need to bother with this, as the process will just
2499 * terminate if a read error happens, however, setting this flag would allow
2500 * repl-diskless-load to work if enabled.
2501 * The module should use RedisModule_IsIOError after reads, before using the
2502 * data that was read, and in case of error, propagate it upwards, and also be
2503 * able to release the partially populated value and all it's allocations.
2504 *
2505 * REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED:
2506 * See RM_SignalModifiedKey().
2507 *
2508 * REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD:
2509 * Setting this flag indicates module awareness of diskless async replication (repl-diskless-load=swapdb)
2510 * and that redis could be serving reads during replication instead of blocking with LOADING status.
2511 *
2512 * REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS:
2513 * Declare that the module wants to get nested key-space notifications.
2514 * By default, Redis will not fire key-space notifications that happened inside
2515 * a key-space notification callback. This flag allows to change this behavior
2516 * and fire nested key-space notifications. Notice: if enabled, the module
2517 * should protected itself from infinite recursion. */
2518void RM_SetModuleOptions(RedisModuleCtx *ctx, int options) {
2519 ctx->module->options = options;
2520}
2521
2522/* Signals that the key is modified from user's perspective (i.e. invalidate WATCH
2523 * and client side caching).
2524 *
2525 * This is done automatically when a key opened for writing is closed, unless
2526 * the option REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED has been set using
2527 * RM_SetModuleOptions().
2528*/
2529int RM_SignalModifiedKey(RedisModuleCtx *ctx, RedisModuleString *keyname) {
2530 kvobj *kv = lookupKeyReadWithFlags(ctx->client->db, keyname, LOOKUP_NOTOUCH);
2531 keyModified(ctx->client,ctx->client->db,keyname,kv,1);
2532 return REDISMODULE_OK;
2533}
2534
2535/* --------------------------------------------------------------------------
2536 * ## Automatic memory management for modules
2537 * -------------------------------------------------------------------------- */
2538
2539/* Enable automatic memory management.
2540 *
2541 * The function must be called as the first function of a command implementation
2542 * that wants to use automatic memory.
2543 *
2544 * When enabled, automatic memory management tracks and automatically frees
2545 * keys, call replies and Redis string objects once the command returns. In most
2546 * cases this eliminates the need of calling the following functions:
2547 *
2548 * 1. RedisModule_CloseKey()
2549 * 2. RedisModule_FreeCallReply()
2550 * 3. RedisModule_FreeString()
2551 *
2552 * These functions can still be used with automatic memory management enabled,
2553 * to optimize loops that make numerous allocations for example. */
2554void RM_AutoMemory(RedisModuleCtx *ctx) {
2555 ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
2556}
2557
2558/* Add a new object to release automatically when the callback returns. */
2559void autoMemoryAdd(RedisModuleCtx *ctx, int type, void *ptr) {
2560 if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
2561 if (ctx->amqueue_used == ctx->amqueue_len) {
2562 ctx->amqueue_len *= 2;
2563 if (ctx->amqueue_len < 16) ctx->amqueue_len = 16;
2564 ctx->amqueue = zrealloc(ctx->amqueue,sizeof(struct AutoMemEntry)*ctx->amqueue_len);
2565 }
2566 ctx->amqueue[ctx->amqueue_used].type = type;
2567 ctx->amqueue[ctx->amqueue_used].ptr = ptr;
2568 ctx->amqueue_used++;
2569}
2570
2571/* Mark an object as freed in the auto release queue, so that users can still
2572 * free things manually if they want.
2573 *
2574 * The function returns 1 if the object was actually found in the auto memory
2575 * pool, otherwise 0 is returned. */
2576int autoMemoryFreed(RedisModuleCtx *ctx, int type, void *ptr) {
2577 if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return 0;
2578
2579 int count = (ctx->amqueue_used+1)/2;
2580 for (int j = 0; j < count; j++) {
2581 for (int side = 0; side < 2; side++) {
2582 /* For side = 0 check right side of the array, for
2583 * side = 1 check the left side instead (zig-zag scanning). */
2584 int i = (side == 0) ? (ctx->amqueue_used - 1 - j) : j;
2585 if (ctx->amqueue[i].type == type &&
2586 ctx->amqueue[i].ptr == ptr)
2587 {
2588 ctx->amqueue[i].type = REDISMODULE_AM_FREED;
2589
2590 /* Switch the freed element and the last element, to avoid growing
2591 * the queue unnecessarily if we allocate/free in a loop */
2592 if (i != ctx->amqueue_used-1) {
2593 ctx->amqueue[i] = ctx->amqueue[ctx->amqueue_used-1];
2594 }
2595
2596 /* Reduce the size of the queue because we either moved the top
2597 * element elsewhere or freed it */
2598 ctx->amqueue_used--;
2599 return 1;
2600 }
2601 }
2602 }
2603 return 0;
2604}
2605
2606/* Release all the objects in queue. */
2607void autoMemoryCollect(RedisModuleCtx *ctx) {
2608 if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
2609 /* Clear the AUTO_MEMORY flag from the context, otherwise the functions
2610 * we call to free the resources, will try to scan the auto release
2611 * queue to mark the entries as freed. */
2612 ctx->flags &= ~REDISMODULE_CTX_AUTO_MEMORY;
2613 int j;
2614 for (j = 0; j < ctx->amqueue_used; j++) {
2615 void *ptr = ctx->amqueue[j].ptr;
2616 switch(ctx->amqueue[j].type) {
2617 case REDISMODULE_AM_STRING: decrRefCount(ptr); break;
2618 case REDISMODULE_AM_REPLY: RM_FreeCallReply(ptr); break;
2619 case REDISMODULE_AM_KEY: RM_CloseKey(ptr); break;
2620 case REDISMODULE_AM_DICT: RM_FreeDict(NULL,ptr); break;
2621 case REDISMODULE_AM_INFO: RM_FreeServerInfo(NULL,ptr); break;
2622 case REDISMODULE_AM_CONFIG: RM_ConfigIteratorRelease(NULL, ptr); break;
2623 case REDISMODULE_AM_SLOTRANGEARRAY: RM_ClusterFreeSlotRanges(NULL, ptr); break;
2624 }
2625 }
2626 ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
2627 zfree(ctx->amqueue);
2628 ctx->amqueue = NULL;
2629 ctx->amqueue_len = 0;
2630 ctx->amqueue_used = 0;
2631}
2632
2633/* --------------------------------------------------------------------------
2634 * ## String objects APIs
2635 * -------------------------------------------------------------------------- */
2636
2637/* Create a new module string object. The returned string must be freed
2638 * with RedisModule_FreeString(), unless automatic memory is enabled.
2639 *
2640 * The string is created by copying the `len` bytes starting
2641 * at `ptr`. No reference is retained to the passed buffer.
2642 *
2643 * The module context 'ctx' is optional and may be NULL if you want to create
2644 * a string out of the context scope. However in that case, the automatic
2645 * memory management will not be available, and the string memory must be
2646 * managed manually. */
2647RedisModuleString *RM_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len) {
2648 RedisModuleString *o = createStringObject(ptr,len);
2649 if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
2650 return o;
2651}
2652
2653/* Create a new module string object from a printf format and arguments.
2654 * The returned string must be freed with RedisModule_FreeString(), unless
2655 * automatic memory is enabled.
2656 *
2657 * The string is created using the sds formatter function sdscatvprintf().
2658 *
2659 * The passed context 'ctx' may be NULL if necessary, see the
2660 * RedisModule_CreateString() documentation for more info. */
2661RedisModuleString *RM_CreateStringPrintf(RedisModuleCtx *ctx, const char *fmt, ...) {
2662 sds s = sdsempty();
2663
2664 va_list ap;
2665 va_start(ap, fmt);
2666 s = sdscatvprintf(s, fmt, ap);
2667 va_end(ap);
2668
2669 RedisModuleString *o = createObject(OBJ_STRING, s);
2670 if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
2671
2672 return o;
2673}
2674
2675
2676/* Like RedisModule_CreateString(), but creates a string starting from a `long long`
2677 * integer instead of taking a buffer and its length.
2678 *
2679 * The returned string must be released with RedisModule_FreeString() or by
2680 * enabling automatic memory management.
2681 *
2682 * The passed context 'ctx' may be NULL if necessary, see the
2683 * RedisModule_CreateString() documentation for more info. */
2684RedisModuleString *RM_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll) {
2685 char buf[LONG_STR_SIZE];
2686 size_t len = ll2string(buf,sizeof(buf),ll);
2687 return RM_CreateString(ctx,buf,len);
2688}
2689
2690/* Like RedisModule_CreateString(), but creates a string starting from a `unsigned long long`
2691 * integer instead of taking a buffer and its length.
2692 *
2693 * The returned string must be released with RedisModule_FreeString() or by
2694 * enabling automatic memory management.
2695 *
2696 * The passed context 'ctx' may be NULL if necessary, see the
2697 * RedisModule_CreateString() documentation for more info. */
2698RedisModuleString *RM_CreateStringFromULongLong(RedisModuleCtx *ctx, unsigned long long ull) {
2699 char buf[LONG_STR_SIZE];
2700 size_t len = ull2string(buf,sizeof(buf),ull);
2701 return RM_CreateString(ctx,buf,len);
2702}
2703
2704/* Like RedisModule_CreateString(), but creates a string starting from a double
2705 * instead of taking a buffer and its length.
2706 *
2707 * The returned string must be released with RedisModule_FreeString() or by
2708 * enabling automatic memory management. */
2709RedisModuleString *RM_CreateStringFromDouble(RedisModuleCtx *ctx, double d) {
2710 char buf[MAX_D2STRING_CHARS];
2711 size_t len = d2string(buf,sizeof(buf),d);
2712 return RM_CreateString(ctx,buf,len);
2713}
2714
2715/* Like RedisModule_CreateString(), but creates a string starting from a long
2716 * double.
2717 *
2718 * The returned string must be released with RedisModule_FreeString() or by
2719 * enabling automatic memory management.
2720 *
2721 * The passed context 'ctx' may be NULL if necessary, see the
2722 * RedisModule_CreateString() documentation for more info. */
2723RedisModuleString *RM_CreateStringFromLongDouble(RedisModuleCtx *ctx, long double ld, int humanfriendly) {
2724 char buf[MAX_LONG_DOUBLE_CHARS];
2725 size_t len = ld2string(buf,sizeof(buf),ld,
2726 (humanfriendly ? LD_STR_HUMAN : LD_STR_AUTO));
2727 return RM_CreateString(ctx,buf,len);
2728}
2729
2730/* Like RedisModule_CreateString(), but creates a string starting from another
2731 * RedisModuleString.
2732 *
2733 * The returned string must be released with RedisModule_FreeString() or by
2734 * enabling automatic memory management.
2735 *
2736 * The passed context 'ctx' may be NULL if necessary, see the
2737 * RedisModule_CreateString() documentation for more info. */
2738RedisModuleString *RM_CreateStringFromString(RedisModuleCtx *ctx, const RedisModuleString *str) {
2739 RedisModuleString *o = dupStringObject(str);
2740 if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
2741 return o;
2742}
2743
2744/* Creates a string from a stream ID. The returned string must be released with
2745 * RedisModule_FreeString(), unless automatic memory is enabled.
2746 *
2747 * The passed context `ctx` may be NULL if necessary. See the
2748 * RedisModule_CreateString() documentation for more info. */
2749RedisModuleString *RM_CreateStringFromStreamID(RedisModuleCtx *ctx, const RedisModuleStreamID *id) {
2750 streamID streamid = {id->ms, id->seq};
2751 RedisModuleString *o = createObjectFromStreamID(&streamid);
2752 if (ctx != NULL) autoMemoryAdd(ctx, REDISMODULE_AM_STRING, o);
2753 return o;
2754}
2755
2756/* Free a module string object obtained with one of the Redis modules API calls
2757 * that return new string objects.
2758 *
2759 * It is possible to call this function even when automatic memory management
2760 * is enabled. In that case the string will be released ASAP and removed
2761 * from the pool of string to release at the end.
2762 *
2763 * If the string was created with a NULL context 'ctx', it is also possible to
2764 * pass ctx as NULL when releasing the string (but passing a context will not
2765 * create any issue). Strings created with a context should be freed also passing
2766 * the context, so if you want to free a string out of context later, make sure
2767 * to create it using a NULL context.
2768 *
2769 * This API is not thread safe, access to these retained strings (if they originated
2770 * from a client command arguments) must be done with GIL locked. */
2771void RM_FreeString(RedisModuleCtx *ctx, RedisModuleString *str) {
2772 decrRefCount(str);
2773 if (ctx != NULL) autoMemoryFreed(ctx,REDISMODULE_AM_STRING,str);
2774}
2775
2776/* Every call to this function, will make the string 'str' requiring
2777 * an additional call to RedisModule_FreeString() in order to really
2778 * free the string. Note that the automatic freeing of the string obtained
2779 * enabling modules automatic memory management counts for one
2780 * RedisModule_FreeString() call (it is just executed automatically).
2781 *
2782 * Normally you want to call this function when, at the same time
2783 * the following conditions are true:
2784 *
2785 * 1. You have automatic memory management enabled.
2786 * 2. You want to create string objects.
2787 * 3. Those string objects you create need to live *after* the callback
2788 * function(for example a command implementation) creating them returns.
2789 *
2790 * Usually you want this in order to store the created string object
2791 * into your own data structure, for example when implementing a new data
2792 * type.
2793 *
2794 * Note that when memory management is turned off, you don't need
2795 * any call to RetainString() since creating a string will always result
2796 * into a string that lives after the callback function returns, if
2797 * no FreeString() call is performed.
2798 *
2799 * It is possible to call this function with a NULL context.
2800 *
2801 * When strings are going to be retained for an extended duration, it is good
2802 * practice to also call RedisModule_TrimStringAllocation() in order to
2803 * optimize memory usage.
2804 *
2805 * Threaded modules that reference retained strings from other threads *must*
2806 * explicitly trim the allocation as soon as the string is retained. Not doing
2807 * so may result with automatic trimming which is not thread safe.
2808 *
2809 * This API is not thread safe, access to these retained strings (if they originated
2810 * from a client command arguments) must be done with GIL locked. */
2811void RM_RetainString(RedisModuleCtx *ctx, RedisModuleString *str) {
2812 if (ctx == NULL || !autoMemoryFreed(ctx,REDISMODULE_AM_STRING,str)) {
2813 /* Increment the string reference counting only if we can't
2814 * just remove the object from the list of objects that should
2815 * be reclaimed. Why we do that, instead of just incrementing
2816 * the refcount in any case, and let the automatic FreeString()
2817 * call at the end to bring the refcount back at the desired
2818 * value? Because this way we ensure that the object refcount
2819 * value is 1 (instead of going to 2 to be dropped later to 1)
2820 * after the call to this function. This is needed for functions
2821 * like RedisModule_StringAppendBuffer() to work. */
2822 incrRefCount(str);
2823 }
2824}
2825
2826/**
2827* This function can be used instead of RedisModule_RetainString().
2828* The main difference between the two is that this function will always
2829* succeed, whereas RedisModule_RetainString() may fail because of an
2830* assertion.
2831*
2832* The function returns a pointer to RedisModuleString, which is owned
2833* by the caller. It requires a call to RedisModule_FreeString() to free
2834* the string when automatic memory management is disabled for the context.
2835* When automatic memory management is enabled, you can either call
2836* RedisModule_FreeString() or let the automation free it.
2837*
2838* This function is more efficient than RedisModule_CreateStringFromString()
2839* because whenever possible, it avoids copying the underlying
2840* RedisModuleString. The disadvantage of using this function is that it
2841* might not be possible to use RedisModule_StringAppendBuffer() on the
2842* returned RedisModuleString.
2843*
2844* It is possible to call this function with a NULL context.
2845*
2846 * When strings are going to be held for an extended duration, it is good
2847 * practice to also call RedisModule_TrimStringAllocation() in order to
2848 * optimize memory usage.
2849 *
2850 * Threaded modules that reference held strings from other threads *must*
2851 * explicitly trim the allocation as soon as the string is held. Not doing
2852 * so may result with automatic trimming which is not thread safe.
2853 *
2854 * This API is not thread safe, access to these retained strings (if they originated
2855 * from a client command arguments) must be done with GIL locked. */
2856RedisModuleString* RM_HoldString(RedisModuleCtx *ctx, RedisModuleString *str) {
2857 if (str->refcount == OBJ_STATIC_REFCOUNT) {
2858 return RM_CreateStringFromString(ctx, str);
2859 }
2860
2861 incrRefCount(str);
2862 if (ctx != NULL) {
2863 /*
2864 * Put the str in the auto memory management of the ctx.
2865 * It might already be there, in this case, the ref count will
2866 * be 2 and we will decrease the ref count twice and free the
2867 * object in the auto memory free function.
2868 *
2869 * Why we can not do the same trick of just remove the object
2870 * from the auto memory (like in RM_RetainString)?
2871 * This code shows the issue:
2872 *
2873 * RM_AutoMemory(ctx);
2874 * str1 = RM_CreateString(ctx, "test", 4);
2875 * str2 = RM_HoldString(ctx, str1);
2876 * RM_FreeString(str1);
2877 * RM_FreeString(str2);
2878 *
2879 * If after the RM_HoldString we would just remove the string from
2880 * the auto memory, this example will cause access to a freed memory
2881 * on 'RM_FreeString(str2);' because the String will be free
2882 * on 'RM_FreeString(str1);'.
2883 *
2884 * So it's safer to just increase the ref count
2885 * and add the String to auto memory again.
2886 *
2887 * The limitation is that it is not possible to use RedisModule_StringAppendBuffer
2888 * on the String.
2889 */
2890 autoMemoryAdd(ctx,REDISMODULE_AM_STRING,str);
2891 }
2892 return str;
2893}
2894
2895/* Given a string module object, this function returns the string pointer
2896 * and length of the string. The returned pointer and length should only
2897 * be used for read only accesses and never modified. */
2898const char *RM_StringPtrLen(const RedisModuleString *str, size_t *len) {
2899 if (str == NULL) {
2900 const char *errmsg = "(NULL string reply referenced in module)";
2901 if (len) *len = strlen(errmsg);
2902 return errmsg;
2903 }
2904 if (len) *len = sdslen(str->ptr);
2905 return str->ptr;
2906}
2907
2908/* --------------------------------------------------------------------------
2909 * Higher level string operations
2910 * ------------------------------------------------------------------------- */
2911
2912/* Convert the string into a `long long` integer, storing it at `*ll`.
2913 * Returns REDISMODULE_OK on success. If the string can't be parsed
2914 * as a valid, strict `long long` (no spaces before/after), REDISMODULE_ERR
2915 * is returned. */
2916int RM_StringToLongLong(const RedisModuleString *str, long long *ll) {
2917 return string2ll(str->ptr,sdslen(str->ptr),ll) ? REDISMODULE_OK :
2918 REDISMODULE_ERR;
2919}
2920
2921/* Convert the string into a `unsigned long long` integer, storing it at `*ull`.
2922 * Returns REDISMODULE_OK on success. If the string can't be parsed
2923 * as a valid, strict `unsigned long long` (no spaces before/after), REDISMODULE_ERR
2924 * is returned. */
2925int RM_StringToULongLong(const RedisModuleString *str, unsigned long long *ull) {
2926 return string2ull(str->ptr,ull) ? REDISMODULE_OK : REDISMODULE_ERR;
2927}
2928
2929/* Convert the string into a double, storing it at `*d`.
2930 * Returns REDISMODULE_OK on success or REDISMODULE_ERR if the string is
2931 * not a valid string representation of a double value. */
2932int RM_StringToDouble(const RedisModuleString *str, double *d) {
2933 int retval = getDoubleFromObject(str,d);
2934 return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
2935}
2936
2937/* Convert the string into a long double, storing it at `*ld`.
2938 * Returns REDISMODULE_OK on success or REDISMODULE_ERR if the string is
2939 * not a valid string representation of a double value. */
2940int RM_StringToLongDouble(const RedisModuleString *str, long double *ld) {
2941 int retval = string2ld(str->ptr,sdslen(str->ptr),ld);
2942 return retval ? REDISMODULE_OK : REDISMODULE_ERR;
2943}
2944
2945/* Convert the string into a stream ID, storing it at `*id`.
2946 * Returns REDISMODULE_OK on success and returns REDISMODULE_ERR if the string
2947 * is not a valid string representation of a stream ID. The special IDs "+" and
2948 * "-" are allowed.
2949 */
2950int RM_StringToStreamID(const RedisModuleString *str, RedisModuleStreamID *id) {
2951 streamID streamid;
2952 if (streamParseID(str, &streamid) == C_OK) {
2953 id->ms = streamid.ms;
2954 id->seq = streamid.seq;
2955 return REDISMODULE_OK;
2956 } else {
2957 return REDISMODULE_ERR;
2958 }
2959}
2960
2961/* Compare two string objects, returning -1, 0 or 1 respectively if
2962 * a < b, a == b, a > b. Strings are compared byte by byte as two
2963 * binary blobs without any encoding care / collation attempt. */
2964int RM_StringCompare(const RedisModuleString *a, const RedisModuleString *b) {
2965 return compareStringObjects(a,b);
2966}
2967
2968/* Return the (possibly modified in encoding) input 'str' object if
2969 * the string is unshared, otherwise NULL is returned. */
2970RedisModuleString *moduleAssertUnsharedString(RedisModuleString *str) {
2971 if (str->refcount != 1) {
2972 serverLog(LL_WARNING,
2973 "Module attempted to use an in-place string modify operation "
2974 "with a string referenced multiple times. Please check the code "
2975 "for API usage correctness.");
2976 return NULL;
2977 }
2978 if (str->encoding == OBJ_ENCODING_EMBSTR) {
2979 /* Note: here we "leak" the additional allocation that was
2980 * used in order to store the embedded string in the object. */
2981 str->ptr = sdsnewlen(str->ptr,sdslen(str->ptr));
2982 str->encoding = OBJ_ENCODING_RAW;
2983 } else if (str->encoding == OBJ_ENCODING_INT) {
2984 /* Convert the string from integer to raw encoding. */
2985 str->ptr = sdsfromlonglong((long)str->ptr);
2986 str->encoding = OBJ_ENCODING_RAW;
2987 }
2988 return str;
2989}
2990
2991/* Append the specified buffer to the string 'str'. The string must be a
2992 * string created by the user that is referenced only a single time, otherwise
2993 * REDISMODULE_ERR is returned and the operation is not performed. */
2994int RM_StringAppendBuffer(RedisModuleCtx *ctx, RedisModuleString *str, const char *buf, size_t len) {
2995 UNUSED(ctx);
2996 str = moduleAssertUnsharedString(str);
2997 if (str == NULL) return REDISMODULE_ERR;
2998 str->ptr = sdscatlen(str->ptr,buf,len);
2999 return REDISMODULE_OK;
3000}
3001
3002/* Trim possible excess memory allocated for a RedisModuleString.
3003 *
3004 * Sometimes a RedisModuleString may have more memory allocated for
3005 * it than required, typically for argv arguments that were constructed
3006 * from network buffers. This function optimizes such strings by reallocating
3007 * their memory, which is useful for strings that are not short lived but
3008 * retained for an extended duration.
3009 *
3010 * This operation is *not thread safe* and should only be called when
3011 * no concurrent access to the string is guaranteed. Using it for an argv
3012 * string in a module command before the string is potentially available
3013 * to other threads is generally safe.
3014 *
3015 * Currently, Redis may also automatically trim retained strings when a
3016 * module command returns. However, doing this explicitly should still be
3017 * a preferred option:
3018 *
3019 * 1. Future versions of Redis may abandon auto-trimming.
3020 * 2. Auto-trimming as currently implemented is *not thread safe*.
3021 * A background thread manipulating a recently retained string may end up
3022 * in a race condition with the auto-trim, which could result with
3023 * data corruption.
3024 */
3025void RM_TrimStringAllocation(RedisModuleString *str) {
3026 if (!str) return;
3027 trimStringObjectIfNeeded(str, 1);
3028}
3029
3030/* --------------------------------------------------------------------------
3031 * ## Reply APIs
3032 *
3033 * These functions are used for sending replies to the client.
3034 *
3035 * Most functions always return REDISMODULE_OK so you can use it with
3036 * 'return' in order to return from the command implementation with:
3037 *
3038 * if (... some condition ...)
3039 * return RedisModule_ReplyWithLongLong(ctx,mycount);
3040 *
3041 * ### Reply with collection functions
3042 *
3043 * After starting a collection reply, the module must make calls to other
3044 * `ReplyWith*` style functions in order to emit the elements of the collection.
3045 * Collection types include: Array, Map, Set and Attribute.
3046 *
3047 * When producing collections with a number of elements that is not known
3048 * beforehand, the function can be called with a special flag
3049 * REDISMODULE_POSTPONED_LEN (REDISMODULE_POSTPONED_ARRAY_LEN in the past),
3050 * and the actual number of elements can be later set with RM_ReplySet*Length()
3051 * call (which will set the latest "open" count if there are multiple ones).
3052 * -------------------------------------------------------------------------- */
3053
3054/* Send an error about the number of arguments given to the command,
3055 * citing the command name in the error message. Returns REDISMODULE_OK.
3056 *
3057 * Example:
3058 *
3059 * if (argc != 3) return RedisModule_WrongArity(ctx);
3060 */
3061int RM_WrongArity(RedisModuleCtx *ctx) {
3062 addReplyErrorArity(ctx->client);
3063 return REDISMODULE_OK;
3064}
3065
3066/* Return the client object the `RM_Reply*` functions should target.
3067 * Normally this is just `ctx->client`, that is the client that called
3068 * the module command, however in the case of thread safe contexts there
3069 * is no directly associated client (since it would not be safe to access
3070 * the client from a thread), so instead the blocked client object referenced
3071 * in the thread safe context, has a fake client that we just use to accumulate
3072 * the replies. Later, when the client is unblocked, the accumulated replies
3073 * are appended to the actual client.
3074 *
3075 * The function returns the client pointer depending on the context, or
3076 * NULL if there is no potential client. This happens when we are in the
3077 * context of a thread safe context that was not initialized with a blocked
3078 * client object. Other contexts without associated clients are the ones
3079 * initialized to run the timers callbacks. */
3080client *moduleGetReplyClient(RedisModuleCtx *ctx) {
3081 if (ctx->flags & REDISMODULE_CTX_THREAD_SAFE) {
3082 if (ctx->blocked_client)
3083 return ctx->blocked_client->reply_client;
3084 else
3085 return NULL;
3086 } else {
3087 /* If this is a non thread safe context, just return the client
3088 * that is running the command if any. This may be NULL as well
3089 * in the case of contexts that are not executed with associated
3090 * clients, like timer contexts. */
3091 return ctx->client;
3092 }
3093}
3094
3095/* Send an integer reply to the client, with the specified `long long` value.
3096 * The function always returns REDISMODULE_OK. */
3097int RM_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll) {
3098 client *c = moduleGetReplyClient(ctx);
3099 if (c == NULL) return REDISMODULE_OK;
3100 addReplyLongLong(c,ll);
3101 return REDISMODULE_OK;
3102}
3103
3104/* Reply with the error 'err'.
3105 *
3106 * Note that 'err' must contain all the error, including
3107 * the initial error code. The function only provides the initial "-", so
3108 * the usage is, for example:
3109 *
3110 * RedisModule_ReplyWithError(ctx,"ERR Wrong Type");
3111 *
3112 * and not just:
3113 *
3114 * RedisModule_ReplyWithError(ctx,"Wrong Type");
3115 *
3116 * The function always returns REDISMODULE_OK.
3117 */
3118int RM_ReplyWithError(RedisModuleCtx *ctx, const char *err) {
3119 client *c = moduleGetReplyClient(ctx);
3120 if (c == NULL) return REDISMODULE_OK;
3121 addReplyErrorFormat(c,"-%s",err);
3122 return REDISMODULE_OK;
3123}
3124
3125/* Reply with the error create from a printf format and arguments.
3126 *
3127 * Note that 'fmt' must contain all the error, including
3128 * the initial error code. The function only provides the initial "-", so
3129 * the usage is, for example:
3130 *
3131 * RedisModule_ReplyWithErrorFormat(ctx,"ERR Wrong Type: %s",type);
3132 *
3133 * and not just:
3134 *
3135 * RedisModule_ReplyWithErrorFormat(ctx,"Wrong Type: %s",type);
3136 *
3137 * The function always returns REDISMODULE_OK.
3138 */
3139int RM_ReplyWithErrorFormat(RedisModuleCtx *ctx, const char *fmt, ...) {
3140 client *c = moduleGetReplyClient(ctx);
3141 if (c == NULL) return REDISMODULE_OK;
3142
3143 int len = strlen(fmt) + 2; /* 1 for the \0 and 1 for the hyphen */
3144 char *hyphenfmt = zmalloc(len);
3145 snprintf(hyphenfmt, len, "-%s", fmt);
3146
3147 va_list ap;
3148 va_start(ap, fmt);
3149 addReplyErrorFormatInternal(c, 0, hyphenfmt, ap);
3150 va_end(ap);
3151
3152 zfree(hyphenfmt);
3153
3154 return REDISMODULE_OK;
3155}
3156
3157/* Reply with a simple string (`+... \r\n` in RESP protocol). This replies
3158 * are suitable only when sending a small non-binary string with small
3159 * overhead, like "OK" or similar replies.
3160 *
3161 * The function always returns REDISMODULE_OK. */
3162int RM_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg) {
3163 client *c = moduleGetReplyClient(ctx);
3164 if (c == NULL) return REDISMODULE_OK;
3165 addReplyProto(c,"+",1);
3166 addReplyProto(c,msg,strlen(msg));
3167 addReplyProto(c,"\r\n",2);
3168 return REDISMODULE_OK;
3169}
3170
3171#define COLLECTION_REPLY_ARRAY 1
3172#define COLLECTION_REPLY_MAP 2
3173#define COLLECTION_REPLY_SET 3
3174#define COLLECTION_REPLY_ATTRIBUTE 4
3175
3176int moduleReplyWithCollection(RedisModuleCtx *ctx, long len, int type) {
3177 client *c = moduleGetReplyClient(ctx);
3178 if (c == NULL) return REDISMODULE_OK;
3179 if (len == REDISMODULE_POSTPONED_LEN) {
3180 ctx->postponed_arrays = zrealloc(ctx->postponed_arrays,sizeof(void*)*
3181 (ctx->postponed_arrays_count+1));
3182 ctx->postponed_arrays[ctx->postponed_arrays_count] =
3183 addReplyDeferredLen(c);
3184 ctx->postponed_arrays_count++;
3185 } else if (len == 0) {
3186 switch (type) {
3187 case COLLECTION_REPLY_ARRAY:
3188 addReply(c, shared.emptyarray);
3189 break;
3190 case COLLECTION_REPLY_MAP:
3191 addReply(c, shared.emptymap[c->resp]);
3192 break;
3193 case COLLECTION_REPLY_SET:
3194 addReply(c, shared.emptyset[c->resp]);
3195 break;
3196 case COLLECTION_REPLY_ATTRIBUTE:
3197 addReplyAttributeLen(c,len);
3198 break;
3199 default:
3200 serverPanic("Invalid module empty reply type %d", type); }
3201 } else {
3202 switch (type) {
3203 case COLLECTION_REPLY_ARRAY:
3204 addReplyArrayLen(c,len);
3205 break;
3206 case COLLECTION_REPLY_MAP:
3207 addReplyMapLen(c,len);
3208 break;
3209 case COLLECTION_REPLY_SET:
3210 addReplySetLen(c,len);
3211 break;
3212 case COLLECTION_REPLY_ATTRIBUTE:
3213 addReplyAttributeLen(c,len);
3214 break;
3215 default:
3216 serverPanic("Invalid module reply type %d", type);
3217 }
3218 }
3219 return REDISMODULE_OK;
3220}
3221
3222/* Reply with an array type of 'len' elements.
3223 *
3224 * After starting an array reply, the module must make `len` calls to other
3225 * `ReplyWith*` style functions in order to emit the elements of the array.
3226 * See Reply APIs section for more details.
3227 *
3228 * Use RM_ReplySetArrayLength() to set deferred length.
3229 *
3230 * The function always returns REDISMODULE_OK. */
3231int RM_ReplyWithArray(RedisModuleCtx *ctx, long len) {
3232 return moduleReplyWithCollection(ctx, len, COLLECTION_REPLY_ARRAY);
3233}
3234
3235/* Reply with a RESP3 Map type of 'len' pairs.
3236 * Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3.
3237 *
3238 * After starting a map reply, the module must make `len*2` calls to other
3239 * `ReplyWith*` style functions in order to emit the elements of the map.
3240 * See Reply APIs section for more details.
3241 *
3242 * If the connected client is using RESP2, the reply will be converted to a flat
3243 * array.
3244 *
3245 * Use RM_ReplySetMapLength() to set deferred length.
3246 *
3247 * The function always returns REDISMODULE_OK. */
3248int RM_ReplyWithMap(RedisModuleCtx *ctx, long len) {
3249 return moduleReplyWithCollection(ctx, len, COLLECTION_REPLY_MAP);
3250}
3251
3252/* Reply with a RESP3 Set type of 'len' elements.
3253 * Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3.
3254 *
3255 * After starting a set reply, the module must make `len` calls to other
3256 * `ReplyWith*` style functions in order to emit the elements of the set.
3257 * See Reply APIs section for more details.
3258 *
3259 * If the connected client is using RESP2, the reply will be converted to an
3260 * array type.
3261 *
3262 * Use RM_ReplySetSetLength() to set deferred length.
3263 *
3264 * The function always returns REDISMODULE_OK. */
3265int RM_ReplyWithSet(RedisModuleCtx *ctx, long len) {
3266 return moduleReplyWithCollection(ctx, len, COLLECTION_REPLY_SET);
3267}
3268
3269
3270/* Add attributes (metadata) to the reply. Should be done before adding the
3271 * actual reply. see https://github.com/antirez/RESP3/blob/master/spec.md#attribute-type
3272 *
3273 * After starting an attribute's reply, the module must make `len*2` calls to other
3274 * `ReplyWith*` style functions in order to emit the elements of the attribute map.
3275 * See Reply APIs section for more details.
3276 *
3277 * Use RM_ReplySetAttributeLength() to set deferred length.
3278 *
3279 * Not supported by RESP2 and will return REDISMODULE_ERR, otherwise
3280 * the function always returns REDISMODULE_OK. */
3281int RM_ReplyWithAttribute(RedisModuleCtx *ctx, long len) {
3282 if (ctx->client->resp == 2) return REDISMODULE_ERR;
3283
3284 return moduleReplyWithCollection(ctx, len, COLLECTION_REPLY_ATTRIBUTE);
3285}
3286
3287/* Reply to the client with a null array, simply null in RESP3,
3288 * null array in RESP2.
3289 *
3290 * Note: In RESP3 there's no difference between Null reply and
3291 * NullArray reply, so to prevent ambiguity it's better to avoid
3292 * using this API and use RedisModule_ReplyWithNull instead.
3293 *
3294 * The function always returns REDISMODULE_OK. */
3295int RM_ReplyWithNullArray(RedisModuleCtx *ctx) {
3296 client *c = moduleGetReplyClient(ctx);
3297 if (c == NULL) return REDISMODULE_OK;
3298 addReplyNullArray(c);
3299 return REDISMODULE_OK;
3300}
3301
3302/* Reply to the client with an empty array.
3303 *
3304 * The function always returns REDISMODULE_OK. */
3305int RM_ReplyWithEmptyArray(RedisModuleCtx *ctx) {
3306 client *c = moduleGetReplyClient(ctx);
3307 if (c == NULL) return REDISMODULE_OK;
3308 addReply(c,shared.emptyarray);
3309 return REDISMODULE_OK;
3310}
3311
3312void moduleReplySetCollectionLength(RedisModuleCtx *ctx, long len, int type) {
3313 client *c = moduleGetReplyClient(ctx);
3314 if (c == NULL) return;
3315 if (ctx->postponed_arrays_count == 0) {
3316 serverLog(LL_WARNING,
3317 "API misuse detected in module %s: "
3318 "RedisModule_ReplySet*Length() called without previous "
3319 "RedisModule_ReplyWith*(ctx,REDISMODULE_POSTPONED_LEN) "
3320 "call.", ctx->module->name);
3321 return;
3322 }
3323 ctx->postponed_arrays_count--;
3324 switch(type) {
3325 case COLLECTION_REPLY_ARRAY:
3326 setDeferredArrayLen(c,ctx->postponed_arrays[ctx->postponed_arrays_count],len);
3327 break;
3328 case COLLECTION_REPLY_MAP:
3329 setDeferredMapLen(c,ctx->postponed_arrays[ctx->postponed_arrays_count],len);
3330 break;
3331 case COLLECTION_REPLY_SET:
3332 setDeferredSetLen(c,ctx->postponed_arrays[ctx->postponed_arrays_count],len);
3333 break;
3334 case COLLECTION_REPLY_ATTRIBUTE:
3335 setDeferredAttributeLen(c,ctx->postponed_arrays[ctx->postponed_arrays_count],len);
3336 break;
3337 default:
3338 serverPanic("Invalid module reply type %d", type);
3339 }
3340 if (ctx->postponed_arrays_count == 0) {
3341 zfree(ctx->postponed_arrays);
3342 ctx->postponed_arrays = NULL;
3343 }
3344}
3345
3346/* When RedisModule_ReplyWithArray() is used with the argument
3347 * REDISMODULE_POSTPONED_LEN, because we don't know beforehand the number
3348 * of items we are going to output as elements of the array, this function
3349 * will take care to set the array length.
3350 *
3351 * Since it is possible to have multiple array replies pending with unknown
3352 * length, this function guarantees to always set the latest array length
3353 * that was created in a postponed way.
3354 *
3355 * For example in order to output an array like [1,[10,20,30]] we
3356 * could write:
3357 *
3358 * RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN);
3359 * RedisModule_ReplyWithLongLong(ctx,1);
3360 * RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN);
3361 * RedisModule_ReplyWithLongLong(ctx,10);
3362 * RedisModule_ReplyWithLongLong(ctx,20);
3363 * RedisModule_ReplyWithLongLong(ctx,30);
3364 * RedisModule_ReplySetArrayLength(ctx,3); // Set len of 10,20,30 array.
3365 * RedisModule_ReplySetArrayLength(ctx,2); // Set len of top array
3366 *
3367 * Note that in the above example there is no reason to postpone the array
3368 * length, since we produce a fixed number of elements, but in the practice
3369 * the code may use an iterator or other ways of creating the output so
3370 * that is not easy to calculate in advance the number of elements.
3371 */
3372void RM_ReplySetArrayLength(RedisModuleCtx *ctx, long len) {
3373 moduleReplySetCollectionLength(ctx, len, COLLECTION_REPLY_ARRAY);
3374}
3375
3376/* Very similar to RedisModule_ReplySetArrayLength except `len` should
3377 * exactly half of the number of `ReplyWith*` functions called in the
3378 * context of the map.
3379 * Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3. */
3380void RM_ReplySetMapLength(RedisModuleCtx *ctx, long len) {
3381 moduleReplySetCollectionLength(ctx, len, COLLECTION_REPLY_MAP);
3382}
3383
3384/* Very similar to RedisModule_ReplySetArrayLength
3385 * Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3. */
3386void RM_ReplySetSetLength(RedisModuleCtx *ctx, long len) {
3387 moduleReplySetCollectionLength(ctx, len, COLLECTION_REPLY_SET);
3388}
3389
3390/* Very similar to RedisModule_ReplySetMapLength
3391 * Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3.
3392 *
3393 * Must not be called if RM_ReplyWithAttribute returned an error. */
3394void RM_ReplySetAttributeLength(RedisModuleCtx *ctx, long len) {
3395 if (ctx->client->resp == 2) return;
3396 moduleReplySetCollectionLength(ctx, len, COLLECTION_REPLY_ATTRIBUTE);
3397}
3398
3399/* Reply with a bulk string, taking in input a C buffer pointer and length.
3400 *
3401 * The function always returns REDISMODULE_OK. */
3402int RM_ReplyWithStringBuffer(RedisModuleCtx *ctx, const char *buf, size_t len) {
3403 client *c = moduleGetReplyClient(ctx);
3404 if (c == NULL) return REDISMODULE_OK;
3405 addReplyBulkCBuffer(c,(char*)buf,len);
3406 return REDISMODULE_OK;
3407}
3408
3409/* Reply with a bulk string, taking in input a C buffer pointer that is
3410 * assumed to be null-terminated.
3411 *
3412 * The function always returns REDISMODULE_OK. */
3413int RM_ReplyWithCString(RedisModuleCtx *ctx, const char *buf) {
3414 client *c = moduleGetReplyClient(ctx);
3415 if (c == NULL) return REDISMODULE_OK;
3416 addReplyBulkCString(c,(char*)buf);
3417 return REDISMODULE_OK;
3418}
3419
3420/* Reply with a bulk string, taking in input a RedisModuleString object.
3421 *
3422 * The function always returns REDISMODULE_OK. */
3423int RM_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str) {
3424 client *c = moduleGetReplyClient(ctx);
3425 if (c == NULL) return REDISMODULE_OK;
3426 addReplyBulk(c,str);
3427 return REDISMODULE_OK;
3428}
3429
3430/* Reply with an empty string.
3431 *
3432 * The function always returns REDISMODULE_OK. */
3433int RM_ReplyWithEmptyString(RedisModuleCtx *ctx) {
3434 client *c = moduleGetReplyClient(ctx);
3435 if (c == NULL) return REDISMODULE_OK;
3436 addReply(c,shared.emptybulk);
3437 return REDISMODULE_OK;
3438}
3439
3440/* Reply with a binary safe string, which should not be escaped or filtered
3441 * taking in input a C buffer pointer, length and a 3 character type/extension.
3442 *
3443 * The function always returns REDISMODULE_OK. */
3444int RM_ReplyWithVerbatimStringType(RedisModuleCtx *ctx, const char *buf, size_t len, const char *ext) {
3445 client *c = moduleGetReplyClient(ctx);
3446 if (c == NULL) return REDISMODULE_OK;
3447 addReplyVerbatim(c, buf, len, ext);
3448 return REDISMODULE_OK;
3449}
3450
3451/* Reply with a binary safe string, which should not be escaped or filtered
3452 * taking in input a C buffer pointer and length.
3453 *
3454 * The function always returns REDISMODULE_OK. */
3455int RM_ReplyWithVerbatimString(RedisModuleCtx *ctx, const char *buf, size_t len) {
3456 return RM_ReplyWithVerbatimStringType(ctx, buf, len, "txt");
3457}
3458
3459/* Reply to the client with a NULL.
3460 *
3461 * The function always returns REDISMODULE_OK. */
3462int RM_ReplyWithNull(RedisModuleCtx *ctx) {
3463 client *c = moduleGetReplyClient(ctx);
3464 if (c == NULL) return REDISMODULE_OK;
3465 addReplyNull(c);
3466 return REDISMODULE_OK;
3467}
3468
3469/* Reply with a RESP3 Boolean type.
3470 * Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3.
3471 *
3472 * In RESP3, this is boolean type
3473 * In RESP2, it's a string response of "1" and "0" for true and false respectively.
3474 *
3475 * The function always returns REDISMODULE_OK. */
3476int RM_ReplyWithBool(RedisModuleCtx *ctx, int b) {
3477 client *c = moduleGetReplyClient(ctx);
3478 if (c == NULL) return REDISMODULE_OK;
3479 addReplyBool(c,b);
3480 return REDISMODULE_OK;
3481}
3482
3483/* Reply exactly what a Redis command returned us with RedisModule_Call().
3484 * This function is useful when we use RedisModule_Call() in order to
3485 * execute some command, as we want to reply to the client exactly the
3486 * same reply we obtained by the command.
3487 *
3488 * Return:
3489 * - REDISMODULE_OK on success.
3490 * - REDISMODULE_ERR if the given reply is in RESP3 format but the client expects RESP2.
3491 * In case of an error, it's the module writer responsibility to translate the reply
3492 * to RESP2 (or handle it differently by returning an error). Notice that for
3493 * module writer convenience, it is possible to pass `0` as a parameter to the fmt
3494 * argument of `RM_Call` so that the RedisModuleCallReply will return in the same
3495 * protocol (RESP2 or RESP3) as set in the current client's context. */
3496int RM_ReplyWithCallReply(RedisModuleCtx *ctx, RedisModuleCallReply *reply) {
3497 client *c = moduleGetReplyClient(ctx);
3498 if (c == NULL) return REDISMODULE_OK;
3499 if (c->resp == 2 && callReplyIsResp3(reply)) {
3500 /* The reply is in RESP3 format and the client is RESP2,
3501 * so it isn't possible to send this reply to the client. */
3502 return REDISMODULE_ERR;
3503 }
3504 size_t proto_len;
3505 const char *proto = callReplyGetProto(reply, &proto_len);
3506 addReplyProto(c, proto, proto_len);
3507 /* Propagate the error list from that reply to the other client, to do some
3508 * post error reply handling, like statistics.
3509 * Note that if the original reply had an array with errors, and the module
3510 * replied with just a portion of the original reply, and not the entire
3511 * reply, the errors are currently not propagated and the errors stats
3512 * will not get propagated. */
3513 list *errors = callReplyDeferredErrorList(reply);
3514 if (errors)
3515 deferredAfterErrorReply(c, errors);
3516 return REDISMODULE_OK;
3517}
3518
3519/* Reply with a RESP3 Double type.
3520 * Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3.
3521 *
3522 * Send a string reply obtained converting the double 'd' into a bulk string.
3523 * This function is basically equivalent to converting a double into
3524 * a string into a C buffer, and then calling the function
3525 * RedisModule_ReplyWithStringBuffer() with the buffer and length.
3526 *
3527 * In RESP3 the string is tagged as a double, while in RESP2 it's just a plain string
3528 * that the user will have to parse.
3529 *
3530 * The function always returns REDISMODULE_OK. */
3531int RM_ReplyWithDouble(RedisModuleCtx *ctx, double d) {
3532 client *c = moduleGetReplyClient(ctx);
3533 if (c == NULL) return REDISMODULE_OK;
3534 addReplyDouble(c,d);
3535 return REDISMODULE_OK;
3536}
3537
3538/* Reply with a RESP3 BigNumber type.
3539 * Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3.
3540 *
3541 * In RESP3, this is a string of length `len` that is tagged as a BigNumber,
3542 * however, it's up to the caller to ensure that it's a valid BigNumber.
3543 * In RESP2, this is just a plain bulk string response.
3544 *
3545 * The function always returns REDISMODULE_OK. */
3546int RM_ReplyWithBigNumber(RedisModuleCtx *ctx, const char *bignum, size_t len) {
3547 client *c = moduleGetReplyClient(ctx);
3548 if (c == NULL) return REDISMODULE_OK;
3549 addReplyBigNum(c, bignum, len);
3550 return REDISMODULE_OK;
3551}
3552
3553/* Send a string reply obtained converting the long double 'ld' into a bulk
3554 * string. This function is basically equivalent to converting a long double
3555 * into a string into a C buffer, and then calling the function
3556 * RedisModule_ReplyWithStringBuffer() with the buffer and length.
3557 * The double string uses human readable formatting (see
3558 * `addReplyHumanLongDouble` in networking.c).
3559 *
3560 * The function always returns REDISMODULE_OK. */
3561int RM_ReplyWithLongDouble(RedisModuleCtx *ctx, long double ld) {
3562 client *c = moduleGetReplyClient(ctx);
3563 if (c == NULL) return REDISMODULE_OK;
3564 addReplyHumanLongDouble(c, ld);
3565 return REDISMODULE_OK;
3566}
3567
3568/* --------------------------------------------------------------------------
3569 * ## Commands replication API
3570 * -------------------------------------------------------------------------- */
3571
3572/* Replicate the specified command and arguments to slaves and AOF, as effect
3573 * of execution of the calling command implementation.
3574 *
3575 * The replicated commands are always wrapped into the MULTI/EXEC that
3576 * contains all the commands replicated in a given module command
3577 * execution, in the order they were executed.
3578 *
3579 * Modules should try to use one interface or the other.
3580 *
3581 * This command follows exactly the same interface of RedisModule_Call(),
3582 * so a set of format specifiers must be passed, followed by arguments
3583 * matching the provided format specifiers.
3584 *
3585 * Please refer to RedisModule_Call() for more information.
3586 *
3587 * Using the special "A" and "R" modifiers, the caller can exclude either
3588 * the AOF or the replicas from the propagation of the specified command.
3589 * Otherwise, by default, the command will be propagated in both channels.
3590 *
3591 * #### Note about calling this function from a thread safe context:
3592 *
3593 * Normally when you call this function from the callback implementing a
3594 * module command, or any other callback provided by the Redis Module API,
3595 * Redis will accumulate all the calls to this function in the context of
3596 * the callback, and will propagate all the commands wrapped in a MULTI/EXEC
3597 * transaction. However when calling this function from a threaded safe context
3598 * that can live an undefined amount of time, and can be locked/unlocked in
3599 * at will, it is important to note that this API is not thread-safe and
3600 * must be executed while holding the GIL.
3601 *
3602 * #### Return value
3603 *
3604 * The command returns REDISMODULE_ERR if the format specifiers are invalid
3605 * or the command name does not belong to a known command. */
3606int RM_Replicate(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
3607 struct redisCommand *cmd;
3608 robj **argv = NULL;
3609 int argc = 0, flags = 0, j;
3610 va_list ap;
3611
3612 cmd = lookupCommandByCString((char*)cmdname);
3613 if (!cmd) return REDISMODULE_ERR;
3614
3615 /* Create the client and dispatch the command. */
3616 va_start(ap, fmt);
3617 argv = moduleCreateArgvFromUserFormat(cmdname,fmt,&argc,&flags,ap);
3618 va_end(ap);
3619 if (argv == NULL) return REDISMODULE_ERR;
3620
3621 /* Select the propagation target. Usually is AOF + replicas, however
3622 * the caller can exclude one or the other using the "A" or "R"
3623 * modifiers. */
3624 int target = 0;
3625 if (!(flags & REDISMODULE_ARGV_NO_AOF)) target |= PROPAGATE_AOF;
3626 if (!(flags & REDISMODULE_ARGV_NO_REPLICAS)) target |= PROPAGATE_REPL;
3627
3628 alsoPropagate(ctx->client->db->id,argv,argc,target);
3629
3630 /* Release the argv. */
3631 for (j = 0; j < argc; j++) decrRefCount(argv[j]);
3632 zfree(argv);
3633 server.dirty++;
3634 return REDISMODULE_OK;
3635}
3636
3637/* This function will replicate the command exactly as it was invoked
3638 * by the client. Note that the replicated commands are always wrapped
3639 * into the MULTI/EXEC that contains all the commands replicated in a
3640 * given module command execution, in the order they were executed.
3641 *
3642 * Basically this form of replication is useful when you want to propagate
3643 * the command to the slaves and AOF file exactly as it was called, since
3644 * the command can just be re-executed to deterministically re-create the
3645 * new state starting from the old one.
3646 *
3647 * It is important to note that this API is not thread-safe and
3648 * must be executed while holding the GIL.
3649 *
3650 * The function always returns REDISMODULE_OK. */
3651int RM_ReplicateVerbatim(RedisModuleCtx *ctx) {
3652 alsoPropagate(ctx->client->db->id,
3653 ctx->client->argv,ctx->client->argc,
3654 PROPAGATE_AOF|PROPAGATE_REPL);
3655 server.dirty++;
3656 return REDISMODULE_OK;
3657}
3658
3659/* --------------------------------------------------------------------------
3660 * ## DB and Key APIs -- Generic API
3661 * -------------------------------------------------------------------------- */
3662
3663/* Return the ID of the current client calling the currently active module
3664 * command. The returned ID has a few guarantees:
3665 *
3666 * 1. The ID is different for each different client, so if the same client
3667 * executes a module command multiple times, it can be recognized as
3668 * having the same ID, otherwise the ID will be different.
3669 * 2. The ID increases monotonically. Clients connecting to the server later
3670 * are guaranteed to get IDs greater than any past ID previously seen.
3671 *
3672 * Valid IDs are from 1 to 2^64 - 1. If 0 is returned it means there is no way
3673 * to fetch the ID in the context the function was currently called.
3674 *
3675 * After obtaining the ID, it is possible to check if the command execution
3676 * is actually happening in the context of AOF loading, using this macro:
3677 *
3678 * if (RedisModule_IsAOFClient(RedisModule_GetClientId(ctx)) {
3679 * // Handle it differently.
3680 * }
3681 */
3682unsigned long long RM_GetClientId(RedisModuleCtx *ctx) {
3683 if (ctx->client == NULL) return 0;
3684 return ctx->client->id;
3685}
3686
3687/* Return the ACL user name used by the client with the specified client ID.
3688 * Client ID can be obtained with RM_GetClientId() API. If the client does not
3689 * exist, NULL is returned and errno is set to ENOENT. If the client isn't
3690 * using an ACL user, NULL is returned and errno is set to ENOTSUP */
3691RedisModuleString *RM_GetClientUserNameById(RedisModuleCtx *ctx, uint64_t id) {
3692 client *client = lookupClientByID(id);
3693 if (client == NULL) {
3694 errno = ENOENT;
3695 return NULL;
3696 }
3697
3698 if (client->user == NULL) {
3699 errno = ENOTSUP;
3700 return NULL;
3701 }
3702
3703 sds name = sdsnew(client->user->name);
3704 robj *str = createObject(OBJ_STRING, name);
3705 autoMemoryAdd(ctx, REDISMODULE_AM_STRING, str);
3706 return str;
3707}
3708
3709/* This is a helper for RM_GetClientInfoById() and other functions: given
3710 * a client, it populates the client info structure with the appropriate
3711 * fields depending on the version provided. If the version is not valid
3712 * then REDISMODULE_ERR is returned. Otherwise the function returns
3713 * REDISMODULE_OK and the structure pointed by 'ci' gets populated. */
3714
3715int modulePopulateClientInfoStructure(void *ci, client *client, int structver) {
3716 if (structver != 1) return REDISMODULE_ERR;
3717
3718 RedisModuleClientInfoV1 *ci1 = ci;
3719 memset(ci1,0,sizeof(*ci1));
3720 ci1->version = structver;
3721 if (client->flags & CLIENT_MULTI)
3722 ci1->flags |= REDISMODULE_CLIENTINFO_FLAG_MULTI;
3723 if (client->flags & CLIENT_PUBSUB)
3724 ci1->flags |= REDISMODULE_CLIENTINFO_FLAG_PUBSUB;
3725 if (client->flags & CLIENT_UNIX_SOCKET)
3726 ci1->flags |= REDISMODULE_CLIENTINFO_FLAG_UNIXSOCKET;
3727 if (client->flags & CLIENT_TRACKING)
3728 ci1->flags |= REDISMODULE_CLIENTINFO_FLAG_TRACKING;
3729 if (client->flags & CLIENT_BLOCKED)
3730 ci1->flags |= REDISMODULE_CLIENTINFO_FLAG_BLOCKED;
3731 if (client->conn->type == connectionTypeTls())
3732 ci1->flags |= REDISMODULE_CLIENTINFO_FLAG_SSL;
3733
3734 int port;
3735 connAddrPeerName(client->conn,ci1->addr,sizeof(ci1->addr),&port);
3736 ci1->port = port;
3737 ci1->db = client->db->id;
3738 ci1->id = client->id;
3739 return REDISMODULE_OK;
3740}
3741
3742/* This is a helper for moduleFireServerEvent() and other functions:
3743 * It populates the replication info structure with the appropriate
3744 * fields depending on the version provided. If the version is not valid
3745 * then REDISMODULE_ERR is returned. Otherwise the function returns
3746 * REDISMODULE_OK and the structure pointed by 'ri' gets populated. */
3747int modulePopulateReplicationInfoStructure(void *ri, int structver) {
3748 if (structver != 1) return REDISMODULE_ERR;
3749
3750 RedisModuleReplicationInfoV1 *ri1 = ri;
3751 memset(ri1,0,sizeof(*ri1));
3752 ri1->version = structver;
3753 ri1->master = server.masterhost==NULL;
3754 ri1->masterhost = server.masterhost? server.masterhost: "";
3755 ri1->masterport = server.masterport;
3756 ri1->replid1 = server.replid;
3757 ri1->replid2 = server.replid2;
3758 ri1->repl1_offset = server.master_repl_offset;
3759 ri1->repl2_offset = server.second_replid_offset;
3760 return REDISMODULE_OK;
3761}
3762
3763/* Return information about the client with the specified ID (that was
3764 * previously obtained via the RedisModule_GetClientId() API). If the
3765 * client exists, REDISMODULE_OK is returned, otherwise REDISMODULE_ERR
3766 * is returned.
3767 *
3768 * When the client exist and the `ci` pointer is not NULL, but points to
3769 * a structure of type RedisModuleClientInfoV1, previously initialized with
3770 * the correct REDISMODULE_CLIENTINFO_INITIALIZER_V1, the structure is populated
3771 * with the following fields:
3772 *
3773 * uint64_t flags; // REDISMODULE_CLIENTINFO_FLAG_*
3774 * uint64_t id; // Client ID
3775 * char addr[46]; // IPv4 or IPv6 address.
3776 * uint16_t port; // TCP port.
3777 * uint16_t db; // Selected DB.
3778 *
3779 * Note: the client ID is useless in the context of this call, since we
3780 * already know, however the same structure could be used in other
3781 * contexts where we don't know the client ID, yet the same structure
3782 * is returned.
3783 *
3784 * With flags having the following meaning:
3785 *
3786 * REDISMODULE_CLIENTINFO_FLAG_SSL Client using SSL connection.
3787 * REDISMODULE_CLIENTINFO_FLAG_PUBSUB Client in Pub/Sub mode.
3788 * REDISMODULE_CLIENTINFO_FLAG_BLOCKED Client blocked in command.
3789 * REDISMODULE_CLIENTINFO_FLAG_TRACKING Client with keys tracking on.
3790 * REDISMODULE_CLIENTINFO_FLAG_UNIXSOCKET Client using unix domain socket.
3791 * REDISMODULE_CLIENTINFO_FLAG_MULTI Client in MULTI state.
3792 *
3793 * However passing NULL is a way to just check if the client exists in case
3794 * we are not interested in any additional information.
3795 *
3796 * This is the correct usage when we want the client info structure
3797 * returned:
3798 *
3799 * RedisModuleClientInfo ci = REDISMODULE_CLIENTINFO_INITIALIZER;
3800 * int retval = RedisModule_GetClientInfoById(&ci,client_id);
3801 * if (retval == REDISMODULE_OK) {
3802 * printf("Address: %s\n", ci.addr);
3803 * }
3804 */
3805int RM_GetClientInfoById(void *ci, uint64_t id) {
3806 client *client = lookupClientByID(id);
3807 if (client == NULL) return REDISMODULE_ERR;
3808 if (ci == NULL) return REDISMODULE_OK;
3809
3810 /* Fill the info structure if passed. */
3811 uint64_t structver = ((uint64_t*)ci)[0];
3812 return modulePopulateClientInfoStructure(ci,client,structver);
3813}
3814
3815/* Returns the name of the client connection with the given ID.
3816 *
3817 * If the client ID does not exist or if the client has no name associated with
3818 * it, NULL is returned. */
3819RedisModuleString *RM_GetClientNameById(RedisModuleCtx *ctx, uint64_t id) {
3820 client *client = lookupClientByID(id);
3821 if (client == NULL || client->name == NULL) return NULL;
3822 robj *name = client->name;
3823 incrRefCount(name);
3824 autoMemoryAdd(ctx, REDISMODULE_AM_STRING, name);
3825 return name;
3826}
3827
3828/* Sets the name of the client with the given ID. This is equivalent to the client calling
3829 * `CLIENT SETNAME name`.
3830 *
3831 * Returns REDISMODULE_OK on success. On failure, REDISMODULE_ERR is returned
3832 * and errno is set as follows:
3833 *
3834 * - ENOENT if the client does not exist
3835 * - EINVAL if the name contains invalid characters */
3836int RM_SetClientNameById(uint64_t id, RedisModuleString *name) {
3837 client *client = lookupClientByID(id);
3838 if (client == NULL) {
3839 errno = ENOENT;
3840 return REDISMODULE_ERR;
3841 }
3842 if (clientSetName(client, name, NULL) == C_ERR) {
3843 errno = EINVAL;
3844 return REDISMODULE_ERR;
3845 }
3846 return REDISMODULE_OK;
3847}
3848
3849/* Publish a message to subscribers (see PUBLISH command). */
3850int RM_PublishMessage(RedisModuleCtx *ctx, RedisModuleString *channel, RedisModuleString *message) {
3851 UNUSED(ctx);
3852 return pubsubPublishMessageAndPropagateToCluster(channel, message, 0);
3853}
3854
3855/* Publish a message to shard-subscribers (see SPUBLISH command). */
3856int RM_PublishMessageShard(RedisModuleCtx *ctx, RedisModuleString *channel, RedisModuleString *message) {
3857 UNUSED(ctx);
3858 return pubsubPublishMessageAndPropagateToCluster(channel, message, 1);
3859}
3860
3861/* Return the currently selected DB. */
3862int RM_GetSelectedDb(RedisModuleCtx *ctx) {
3863 return ctx->client->db->id;
3864}
3865
3866
3867/* Return the current context's flags. The flags provide information on the
3868 * current request context (whether the client is a Lua script or in a MULTI),
3869 * and about the Redis instance in general, i.e replication and persistence.
3870 *
3871 * It is possible to call this function even with a NULL context, however
3872 * in this case the following flags will not be reported:
3873 *
3874 * * LUA, MULTI, REPLICATED, DIRTY (see below for more info).
3875 *
3876 * Available flags and their meaning:
3877 *
3878 * * REDISMODULE_CTX_FLAGS_LUA: The command is running in a Lua script
3879 *
3880 * * REDISMODULE_CTX_FLAGS_MULTI: The command is running inside a transaction
3881 *
3882 * * REDISMODULE_CTX_FLAGS_REPLICATED: The command was sent over the replication
3883 * link by the MASTER
3884 *
3885 * * REDISMODULE_CTX_FLAGS_MASTER: The Redis instance is a master
3886 *
3887 * * REDISMODULE_CTX_FLAGS_SLAVE: The Redis instance is a slave
3888 *
3889 * * REDISMODULE_CTX_FLAGS_READONLY: The Redis instance is read-only
3890 *
3891 * * REDISMODULE_CTX_FLAGS_CLUSTER: The Redis instance is in cluster mode
3892 *
3893 * * REDISMODULE_CTX_FLAGS_AOF: The Redis instance has AOF enabled
3894 *
3895 * * REDISMODULE_CTX_FLAGS_RDB: The instance has RDB enabled
3896 *
3897 * * REDISMODULE_CTX_FLAGS_MAXMEMORY: The instance has Maxmemory set
3898 *
3899 * * REDISMODULE_CTX_FLAGS_EVICT: Maxmemory is set and has an eviction
3900 * policy that may delete keys
3901 *
3902 * * REDISMODULE_CTX_FLAGS_OOM: Redis is out of memory according to the
3903 * maxmemory setting.
3904 *
3905 * * REDISMODULE_CTX_FLAGS_OOM_WARNING: Less than 25% of memory remains before
3906 * reaching the maxmemory level.
3907 *
3908 * * REDISMODULE_CTX_FLAGS_LOADING: Server is loading RDB/AOF
3909 *
3910 * * REDISMODULE_CTX_FLAGS_REPLICA_IS_STALE: No active link with the master.
3911 *
3912 * * REDISMODULE_CTX_FLAGS_REPLICA_IS_CONNECTING: The replica is trying to
3913 * connect with the master.
3914 *
3915 * * REDISMODULE_CTX_FLAGS_REPLICA_IS_TRANSFERRING: Master -> Replica RDB
3916 * transfer is in progress.
3917 *
3918 * * REDISMODULE_CTX_FLAGS_REPLICA_IS_ONLINE: The replica has an active link
3919 * with its master. This is the
3920 * contrary of STALE state.
3921 *
3922 * * REDISMODULE_CTX_FLAGS_ACTIVE_CHILD: There is currently some background
3923 * process active (RDB, AUX or module).
3924 *
3925 * * REDISMODULE_CTX_FLAGS_MULTI_DIRTY: The next EXEC will fail due to dirty
3926 * CAS (touched keys).
3927 *
3928 * * REDISMODULE_CTX_FLAGS_IS_CHILD: Redis is currently running inside
3929 * background child process.
3930 *
3931 * * REDISMODULE_CTX_FLAGS_RESP3: Indicate the that client attached to this
3932 * context is using RESP3.
3933 *
3934 * * REDISMODULE_CTX_FLAGS_SERVER_STARTUP: The Redis instance is starting
3935 *
3936 * * REDISMODULE_CTX_FLAGS_DEBUG_ENABLED: Debug commands are enabled for this
3937 * context.
3938 * * REDISMODULE_CTX_FLAGS_TRIM_IN_PROGRESS: Trim is in progress due to slot
3939 * migration.
3940 */
3941int RM_GetContextFlags(RedisModuleCtx *ctx) {
3942 int flags = 0;
3943
3944 /* Client specific flags */
3945 if (ctx) {
3946 if (ctx->client) {
3947 if (ctx->client->flags & CLIENT_DENY_BLOCKING)
3948 flags |= REDISMODULE_CTX_FLAGS_DENY_BLOCKING;
3949 /* Module command received from MASTER, is replicated. */
3950 if (ctx->client->flags & CLIENT_MASTER)
3951 flags |= REDISMODULE_CTX_FLAGS_REPLICATED;
3952 if (ctx->client->resp == 3) {
3953 flags |= REDISMODULE_CTX_FLAGS_RESP3;
3954 }
3955 }
3956
3957 /* For DIRTY flags, we need the blocked client if used */
3958 client *c = ctx->blocked_client ? ctx->blocked_client->client : ctx->client;
3959 if (c && (c->flags & (CLIENT_DIRTY_CAS|CLIENT_DIRTY_EXEC))) {
3960 flags |= REDISMODULE_CTX_FLAGS_MULTI_DIRTY;
3961 }
3962 if (c && allowProtectedAction(server.enable_debug_cmd, c)) {
3963 flags |= REDISMODULE_CTX_FLAGS_DEBUG_ENABLED;
3964 }
3965 }
3966
3967 if (scriptIsRunning())
3968 flags |= REDISMODULE_CTX_FLAGS_LUA;
3969
3970 if (server.in_exec)
3971 flags |= REDISMODULE_CTX_FLAGS_MULTI;
3972
3973 if (server.cluster_enabled)
3974 flags |= REDISMODULE_CTX_FLAGS_CLUSTER;
3975
3976 if (server.async_loading)
3977 flags |= REDISMODULE_CTX_FLAGS_ASYNC_LOADING;
3978 else if (server.loading)
3979 flags |= REDISMODULE_CTX_FLAGS_LOADING;
3980
3981 /* Maxmemory and eviction policy */
3982 if (server.maxmemory > 0 && (!server.masterhost || !server.repl_slave_ignore_maxmemory)) {
3983 flags |= REDISMODULE_CTX_FLAGS_MAXMEMORY;
3984
3985 if (server.maxmemory_policy != MAXMEMORY_NO_EVICTION)
3986 flags |= REDISMODULE_CTX_FLAGS_EVICT;
3987 }
3988
3989 /* Persistence flags */
3990 if (server.aof_state != AOF_OFF)
3991 flags |= REDISMODULE_CTX_FLAGS_AOF;
3992 if (server.saveparamslen > 0)
3993 flags |= REDISMODULE_CTX_FLAGS_RDB;
3994
3995 /* Replication flags */
3996 if (server.masterhost == NULL) {
3997 flags |= REDISMODULE_CTX_FLAGS_MASTER;
3998 } else {
3999 flags |= REDISMODULE_CTX_FLAGS_SLAVE;
4000 if (server.repl_slave_ro)
4001 flags |= REDISMODULE_CTX_FLAGS_READONLY;
4002
4003 /* Replica state flags. */
4004 if (server.repl_state == REPL_STATE_CONNECT ||
4005 server.repl_state == REPL_STATE_CONNECTING)
4006 {
4007 flags |= REDISMODULE_CTX_FLAGS_REPLICA_IS_CONNECTING;
4008 } else if (server.repl_state == REPL_STATE_TRANSFER) {
4009 flags |= REDISMODULE_CTX_FLAGS_REPLICA_IS_TRANSFERRING;
4010 } else if (server.repl_state == REPL_STATE_CONNECTED) {
4011 flags |= REDISMODULE_CTX_FLAGS_REPLICA_IS_ONLINE;
4012 }
4013
4014 if (server.repl_state != REPL_STATE_CONNECTED)
4015 flags |= REDISMODULE_CTX_FLAGS_REPLICA_IS_STALE;
4016 }
4017
4018 /* OOM flag. */
4019 float level;
4020 int retval = getMaxmemoryState(NULL,NULL,NULL,&level);
4021 if (retval == C_ERR) flags |= REDISMODULE_CTX_FLAGS_OOM;
4022 if (level > 0.75) flags |= REDISMODULE_CTX_FLAGS_OOM_WARNING;
4023
4024 /* Presence of children processes. */
4025 if (hasActiveChildProcess()) flags |= REDISMODULE_CTX_FLAGS_ACTIVE_CHILD;
4026 if (server.in_fork_child) flags |= REDISMODULE_CTX_FLAGS_IS_CHILD;
4027
4028 /* Non-empty server.loadmodule_queue means that Redis is starting. */
4029 if (listLength(server.loadmodule_queue) > 0)
4030 flags |= REDISMODULE_CTX_FLAGS_SERVER_STARTUP;
4031
4032 /* If debug commands are completely enabled */
4033 if (server.enable_debug_cmd == PROTECTED_ACTION_ALLOWED_YES) {
4034 flags |= REDISMODULE_CTX_FLAGS_DEBUG_ENABLED;
4035 }
4036
4037 if (asmIsTrimInProgress())
4038 flags |= REDISMODULE_CTX_FLAGS_TRIM_IN_PROGRESS;
4039
4040 return flags;
4041}
4042
4043/* Returns true if a client sent the CLIENT PAUSE command to the server or
4044 * if Redis Cluster does a manual failover, pausing the clients.
4045 * This is needed when we have a master with replicas, and want to write,
4046 * without adding further data to the replication channel, that the replicas
4047 * replication offset, match the one of the master. When this happens, it is
4048 * safe to failover the master without data loss.
4049 *
4050 * However modules may generate traffic by calling RedisModule_Call() with
4051 * the "!" flag, or by calling RedisModule_Replicate(), in a context outside
4052 * commands execution, for instance in timeout callbacks, threads safe
4053 * contexts, and so forth. When modules will generate too much traffic, it
4054 * will be hard for the master and replicas offset to match, because there
4055 * is more data to send in the replication channel.
4056 *
4057 * So modules may want to try to avoid very heavy background work that has
4058 * the effect of creating data to the replication channel, when this function
4059 * returns true. This is mostly useful for modules that have background
4060 * garbage collection tasks, or that do writes and replicate such writes
4061 * periodically in timer callbacks or other periodic callbacks.
4062 */
4063int RM_AvoidReplicaTraffic(void) {
4064 return !!(isPausedActionsWithUpdate(PAUSE_ACTION_REPLICA));
4065}
4066
4067/* Change the currently selected DB. Returns an error if the id
4068 * is out of range.
4069 *
4070 * Note that the client will retain the currently selected DB even after
4071 * the Redis command implemented by the module calling this function
4072 * returns.
4073 *
4074 * If the module command wishes to change something in a different DB and
4075 * returns back to the original one, it should call RedisModule_GetSelectedDb()
4076 * before in order to restore the old DB number before returning. */
4077int RM_SelectDb(RedisModuleCtx *ctx, int newid) {
4078 int retval = selectDb(ctx->client,newid);
4079 return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
4080}
4081
4082/* Check if a key exists, without affecting its last access time.
4083 *
4084 * This is equivalent to calling RM_OpenKey with the mode REDISMODULE_READ |
4085 * REDISMODULE_OPEN_KEY_NOTOUCH, then checking if NULL was returned and, if not,
4086 * calling RM_CloseKey on the opened key.
4087 */
4088int RM_KeyExists(RedisModuleCtx *ctx, robj *keyname) {
4089 kvobj *kv = lookupKeyReadWithFlags(ctx->client->db, keyname, LOOKUP_NOTOUCH);
4090 return (kv != NULL);
4091}
4092
4093/* Initialize a RedisModuleKey struct */
4094static void moduleInitKey(RedisModuleKey *kp, RedisModuleCtx *ctx, robj *keyname, kvobj *kv, int mode){
4095 kp->ctx = ctx;
4096 kp->db = ctx->client->db;
4097 kp->key = keyname;
4098 incrRefCount(keyname);
4099 kp->kv = kv;
4100 kp->iter = NULL;
4101 kp->mode = mode;
4102 if (kp->kv) moduleInitKeyTypeSpecific(kp);
4103}
4104
4105/* Initialize the type-specific part of the key. Only when key has a value. */
4106static void moduleInitKeyTypeSpecific(RedisModuleKey *key) {
4107 switch (key->kv->type) {
4108 case OBJ_ZSET: zsetKeyReset(key); break;
4109 case OBJ_STREAM: key->u.stream.signalready = 0; break;
4110 }
4111}
4112
4113/* Return a handle representing a Redis key, so that it is possible
4114 * to call other APIs with the key handle as argument to perform
4115 * operations on the key.
4116 *
4117 * The return value is the handle representing the key, that must be
4118 * closed with RM_CloseKey().
4119 *
4120 * If the key does not exist and REDISMODULE_WRITE mode is requested, the handle
4121 * is still returned, since it is possible to perform operations on
4122 * a yet not existing key (that will be created, for example, after
4123 * a list push operation). If the mode is just REDISMODULE_READ instead, and the
4124 * key does not exist, NULL is returned. However it is still safe to
4125 * call RedisModule_CloseKey() and RedisModule_KeyType() on a NULL
4126 * value.
4127 *
4128 * Extra flags that can be pass to the API under the mode argument:
4129 * * REDISMODULE_OPEN_KEY_NOTOUCH - Avoid touching the LRU/LFU of the key when opened.
4130 * * REDISMODULE_OPEN_KEY_NONOTIFY - Don't trigger keyspace event on key misses.
4131 * * REDISMODULE_OPEN_KEY_NOSTATS - Don't update keyspace hits/misses counters.
4132 * * REDISMODULE_OPEN_KEY_NOEXPIRE - Avoid deleting lazy expired keys.
4133 * * REDISMODULE_OPEN_KEY_NOEFFECTS - Avoid any effects from fetching the key.
4134 * * REDISMODULE_OPEN_KEY_ACCESS_EXPIRED - Access expired keys that have not yet been deleted */
4135RedisModuleKey *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
4136 RedisModuleKey *kp;
4137 kvobj *kv;
4138 int flags = 0;
4139 flags |= (mode & REDISMODULE_OPEN_KEY_NOTOUCH? LOOKUP_NOTOUCH: 0);
4140 flags |= (mode & REDISMODULE_OPEN_KEY_NONOTIFY? LOOKUP_NONOTIFY: 0);
4141 flags |= (mode & REDISMODULE_OPEN_KEY_NOSTATS? LOOKUP_NOSTATS: 0);
4142 flags |= (mode & REDISMODULE_OPEN_KEY_NOEXPIRE? LOOKUP_NOEXPIRE: 0);
4143 flags |= (mode & REDISMODULE_OPEN_KEY_NOEFFECTS? LOOKUP_NOEFFECTS: 0);
4144 flags |= (mode & REDISMODULE_OPEN_KEY_ACCESS_EXPIRED ? (LOOKUP_ACCESS_EXPIRED) : 0);
4145 flags |= (mode & REDISMODULE_OPEN_KEY_ACCESS_TRIMMED ? (LOOKUP_ACCESS_TRIMMED) : 0);
4146
4147 if (mode & REDISMODULE_WRITE) {
4148 kv = lookupKeyWriteWithFlags(ctx->client->db,keyname, flags);
4149 } else {
4150 kv = lookupKeyReadWithFlags(ctx->client->db,keyname, flags);
4151 if (kv == NULL) {
4152 return NULL;
4153 }
4154 }
4155
4156 /* Setup the key handle. */
4157 kp = zmalloc(sizeof(*kp));
4158 moduleInitKey(kp, ctx, keyname, kv, mode);
4159 autoMemoryAdd(ctx,REDISMODULE_AM_KEY,kp);
4160 return kp;
4161}
4162
4163/**
4164 * Returns the full OpenKey modes mask, using the return value
4165 * the module can check if a certain set of OpenKey modes are supported
4166 * by the redis server version in use.
4167 * Example:
4168 *
4169 * int supportedMode = RM_GetOpenKeyModesAll();
4170 * if (supportedMode & REDISMODULE_OPEN_KEY_NOTOUCH) {
4171 * // REDISMODULE_OPEN_KEY_NOTOUCH is supported
4172 * } else{
4173 * // REDISMODULE_OPEN_KEY_NOTOUCH is not supported
4174 * }
4175 */
4176int RM_GetOpenKeyModesAll(void) {
4177 return _REDISMODULE_OPEN_KEY_ALL;
4178}
4179
4180/* Destroy a RedisModuleKey struct (freeing is the responsibility of the caller). */
4181static void moduleCloseKey(RedisModuleKey *key) {
4182 int signal = SHOULD_SIGNAL_MODIFIED_KEYS(key->ctx);
4183 if ((key->mode & REDISMODULE_WRITE) && signal)
4184 keyModified(key->ctx->client,key->db,key->key,key->kv,1);
4185 if (key->kv) {
4186 if (key->iter) moduleFreeKeyIterator(key);
4187 switch (key->kv->type) {
4188 case OBJ_ZSET:
4189 RM_ZsetRangeStop(key);
4190 break;
4191 case OBJ_STREAM:
4192 if (key->u.stream.signalready)
4193 /* One or more RM_StreamAdd() have been done. */
4194 signalKeyAsReady(key->db, key->key, OBJ_STREAM);
4195 break;
4196 }
4197 }
4198 serverAssert(key->iter == NULL);
4199 decrRefCount(key->key);
4200}
4201
4202/* Close a key handle. */
4203void RM_CloseKey(RedisModuleKey *key) {
4204 if (key == NULL) return;
4205 moduleCloseKey(key);
4206 autoMemoryFreed(key->ctx,REDISMODULE_AM_KEY,key);
4207 zfree(key);
4208}
4209
4210/* Return the type of the key. If the key pointer is NULL then
4211 * REDISMODULE_KEYTYPE_EMPTY is returned. */
4212int RM_KeyType(RedisModuleKey *key) {
4213 if (key == NULL || key->kv == NULL) return REDISMODULE_KEYTYPE_EMPTY;
4214 /* We map between defines so that we are free to change the internal
4215 * defines as desired. */
4216 switch(key->kv->type) {
4217 case OBJ_STRING: return REDISMODULE_KEYTYPE_STRING;
4218 case OBJ_LIST: return REDISMODULE_KEYTYPE_LIST;
4219 case OBJ_SET: return REDISMODULE_KEYTYPE_SET;
4220 case OBJ_ZSET: return REDISMODULE_KEYTYPE_ZSET;
4221 case OBJ_HASH: return REDISMODULE_KEYTYPE_HASH;
4222 case OBJ_MODULE: return REDISMODULE_KEYTYPE_MODULE;
4223 case OBJ_STREAM: return REDISMODULE_KEYTYPE_STREAM;
4224 default: return REDISMODULE_KEYTYPE_EMPTY;
4225 }
4226}
4227
4228/* Return the length of the value associated with the key.
4229 * For strings this is the length of the string. For all the other types
4230 * is the number of elements (just counting keys for hashes).
4231 *
4232 * If the key pointer is NULL or the key is empty, zero is returned. */
4233size_t RM_ValueLength(RedisModuleKey *key) {
4234 if (key == NULL || key->kv == NULL) return 0;
4235 return getObjectLength(key->kv);
4236}
4237
4238/* If the key is open for writing, remove it, and setup the key to
4239 * accept new writes as an empty key (that will be created on demand).
4240 * On success REDISMODULE_OK is returned. If the key is not open for
4241 * writing REDISMODULE_ERR is returned. */
4242int RM_DeleteKey(RedisModuleKey *key) {
4243 if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
4244 if (key->kv) {
4245 dbDelete(key->db,key->key);
4246 key->kv = NULL;
4247 }
4248 return REDISMODULE_OK;
4249}
4250
4251/* If the key is open for writing, unlink it (that is delete it in a
4252 * non-blocking way, not reclaiming memory immediately) and setup the key to
4253 * accept new writes as an empty key (that will be created on demand).
4254 * On success REDISMODULE_OK is returned. If the key is not open for
4255 * writing REDISMODULE_ERR is returned. */
4256int RM_UnlinkKey(RedisModuleKey *key) {
4257 if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
4258 if (key->kv) {
4259 dbAsyncDelete(key->db,key->key);
4260 key->kv = NULL;
4261 }
4262 return REDISMODULE_OK;
4263}
4264
4265/* Return the key expire value, as milliseconds of remaining TTL.
4266 * If no TTL is associated with the key or if the key is empty,
4267 * REDISMODULE_NO_EXPIRE is returned. */
4268mstime_t RM_GetExpire(RedisModuleKey *key) {
4269 mstime_t expire = kvobjGetExpire(key->kv);
4270 if (expire == -1 || key->kv == NULL)
4271 return REDISMODULE_NO_EXPIRE;
4272 expire -= commandTimeSnapshot();
4273 return expire >= 0 ? expire : 0;
4274}
4275
4276/* Set a new expire for the key. If the special expire
4277 * REDISMODULE_NO_EXPIRE is set, the expire is cancelled if there was
4278 * one (the same as the PERSIST command).
4279 *
4280 * Note that the expire must be provided as a positive integer representing
4281 * the number of milliseconds of TTL the key should have.
4282 *
4283 * The function returns REDISMODULE_OK on success or REDISMODULE_ERR if
4284 * the key was not open for writing or is an empty key. */
4285int RM_SetExpire(RedisModuleKey *key, mstime_t expire) {
4286 if (!(key->mode & REDISMODULE_WRITE) || key->kv == NULL || (expire < 0 && expire != REDISMODULE_NO_EXPIRE))
4287 return REDISMODULE_ERR;
4288 if (expire != REDISMODULE_NO_EXPIRE) {
4289 expire += commandTimeSnapshot();
4290 /* setExpire() might realloc kvobj */
4291 key->kv = setExpire(key->ctx->client,key->db,key->key,expire);
4292 } else {
4293 removeExpire(key->db,key->key);
4294 }
4295 return REDISMODULE_OK;
4296}
4297
4298/* Return the key expire value, as absolute Unix timestamp.
4299 * If no TTL is associated with the key or if the key is empty,
4300 * REDISMODULE_NO_EXPIRE is returned. */
4301mstime_t RM_GetAbsExpire(RedisModuleKey *key) {
4302 mstime_t expire = kvobjGetExpire(key->kv);
4303 if (expire == -1 || key->kv == NULL)
4304 return REDISMODULE_NO_EXPIRE;
4305 return expire;
4306}
4307
4308/* Set a new expire for the key. If the special expire
4309 * REDISMODULE_NO_EXPIRE is set, the expire is cancelled if there was
4310 * one (the same as the PERSIST command).
4311 *
4312 * Note that the expire must be provided as a positive integer representing
4313 * the absolute Unix timestamp the key should have.
4314 *
4315 * The function returns REDISMODULE_OK on success or REDISMODULE_ERR if
4316 * the key was not open for writing or is an empty key. */
4317int RM_SetAbsExpire(RedisModuleKey *key, mstime_t expire) {
4318 if (!(key->mode & REDISMODULE_WRITE) || key->kv == NULL || (expire < 0 && expire != REDISMODULE_NO_EXPIRE))
4319 return REDISMODULE_ERR;
4320 if (expire != REDISMODULE_NO_EXPIRE) {
4321 key->kv = setExpire(key->ctx->client,key->db,key->key,expire);
4322 } else {
4323 removeExpire(key->db,key->key);
4324 }
4325 return REDISMODULE_OK;
4326}
4327
4328/* Register a new key metadata class exported by the module.
4329 *
4330 * Key metadata allows modules to attach up to 8 bytes of metadata to any Redis key,
4331 * regardless of the key's type. This metadata persists across key operations like
4332 * COPY, RENAME, MOVE, and can be saved/loaded from RDB files.
4333 *
4334 * The parameters are the following:
4335 *
4336 * * **metaname**: A 9 characters metadata class name that MUST be unique in the Redis
4337 * Modules ecosystem. Use the charset A-Z a-z 0-9, plus the two "-_" characters.
4338 * A good idea is to use, for example `<metaname>-<vendor>`. For example
4339 * "idx-RediSearch" may mean "Index metadata by RediSearch module". To use both
4340 * lower case and upper case letters helps in order to prevent collisions.
4341 *
4342 * * **metaver**: Encoding version, which is the version of the serialization
4343 * that a module used in order to persist metadata. As long as the "metaname"
4344 * matches, the RDB loading will be dispatched to the metadata class callbacks
4345 * whatever 'metaver' is used, however the module can understand if
4346 * the encoding it must load is of an older version of the module.
4347 * For example the module "idx-RediSearch" initially used metaver=0. Later
4348 * after an upgrade, it started to serialize metadata in a different format
4349 * and to register the class with metaver=1. However this module may
4350 * still load old data produced by an older version if the rdb_load
4351 * callback is able to check the metaver value and act accordingly.
4352 * The metaver must be a positive value between 0 and 1023.
4353 *
4354 * * **confPtr** is a pointer to a RedisModuleKeyMetaClassConfig structure
4355 * that should be populated with the configuration and callbacks, like in
4356 * the following example:
4357 *
4358 * RedisModuleKeyMetaClassConfig config = {
4359 * .version = REDISMODULE_KEY_META_VERSION,
4360 * .flags = 1 << REDISMODULE_META_ALLOW_IGNORE,
4361 * .reset_value = 0,
4362 * .copy = myMeta_CopyCallback,
4363 * .rename = myMeta_RenameCallback,
4364 * .move = myMeta_MoveCallback,
4365 * .unlink = myMeta_UnlinkCallback,
4366 * .free = myMeta_FreeCallback,
4367 * .rdb_load = myMeta_RDBLoadCallback,
4368 * .rdb_save = myMeta_RDBSaveCallback,
4369 * .aof_rewrite = myMeta_AOFRewriteCallback,
4370 * .defrag = myMeta_DefragCallback,
4371 * .mem_usage = myMeta_MemUsageCallback,
4372 * .free_effort = myMeta_FreeEffortCallback
4373 * }
4374 *
4375 * Redis does NOT take ownership of the config structure itself. The `confPtr`
4376 * parameter only needs to remain valid during the RM_CreateKeyMetaClass() call
4377 * and can be freed immediately after.
4378 *
4379 * * **version**: Module must set it to REDISMODULE_KEY_META_VERSION. This field is
4380 * bumped when new fields are added; Redis keeps backward compatibility in
4381 * RM_CreateKeyMetaClass().
4382 *
4383 * * **flags**: Currently supports REDISMODULE_META_ALLOW_IGNORE (value 0).
4384 * When set, metadata will be silently ignored during RDB load if the module
4385 * is not available or if rdb_load callback is NULL. Otherwise, RDB loading
4386 * will fail if metadata is encountered but cannot be loaded.
4387 *
4388 * * **reset_value**: The value to which metadata should be reset when it is being
4389 * "removed" from a key. Typically 0, but can be any 8-byte value. This is
4390 * especially relevant when metadata is a pointer/handler to external resources.
4391 *
4392 * IMPORTANT GUARANTEE: Redis only invokes callbacks when meta != reset_value.
4393 *
4394 * * **copy**: A callback function pointer for COPY command (optional).
4395 * - Return 1 to attach `meta` to the new key, or 0 to skip attaching metadata.
4396 * - If NULL, metadata is ignored during copy.
4397 * - The `meta` value may be modified in-place to produce a different value
4398 * for the new key.
4399 *
4400 * * **rename**: A callback function pointer for RENAME command (optional).
4401 * - If NULL, then metadata is kept during rename.
4402 * - The `meta` value may be modified in-place to produce a different value
4403 * for the new key.
4404 *
4405 * * **move**: A callback function pointer for MOVE command (optional).
4406 * - Return 1 to keep metadata, 0 to drop.
4407 * - If NULL, then metadata is kept during move.
4408 * - The `meta` value may be modified in-place to produce a different value
4409 * for the new key.
4410 *
4411 * * **unlink**: A callback function pointer for unlink operations (optional).
4412 * - If not provided, then metadata is ignored during unlink.
4413 * - Indication that key may soon be freed by background thread.
4414 * - Pointer to meta is provided for modification. If the metadata holds a pointer
4415 * or handle to resources and you free them here, you should set `*meta=reset_value`
4416 * to prevent the free callback from being invoked (Redis skips callbacks when
4417 * meta == reset_value, see reset_value documentation above).
4418 *
4419 * * **free**: A callback function pointer for cleanup (optional).
4420 * Invoked when a key with this metadata is deleted/overwritten/expired,
4421 * or when Redis needs to release per-key metadata during lifecycle operations.
4422 * The module should free any external allocation referenced by `meta`
4423 * if it uses the 8 bytes as a handle/pointer.
4424 * This callback may run in a background thread and is not protected by GIL.
4425 * It also might be called during RDB loading if the load fails after some
4426 * metadata has been successfully loaded. In this case, keyname will be NULL
4427 * since the key hasn't been created yet.
4428 *
4429 * * **rdb_load**: A callback function pointer for RDB loading (optional).
4430 * - Called during RDB loading when metadata for this class is encountered.
4431 * - Behavior when NULL:
4432 * > If rdb_load is NULL AND REDISMODULE_META_ALLOW_IGNORE flag is set,
4433 * the metadata will be silently ignored during RDB load.
4434 * > If rdb_load is NULL AND the flag is NOT set, RDB loading will fail
4435 * if metadata for this class is encountered.
4436 * - Behavior when class is not registered:
4437 * > If the class was saved with REDISMODULE_META_ALLOW_IGNORE flag but
4438 * is not registered at load time, the metadata will be silently ignored.
4439 * > Otherwise, RDB loading will fail.
4440 * - Callback responsibilities:
4441 * > Read custom serialized data from `rdb` using RedisModule_Load*() APIs
4442 * > Deserialize and reconstruct the 8-byte metadata value
4443 * > Write the final 8-byte value into `*meta`
4444 * > Return appropriate status code (see below)
4445 * > Database ID can be derived from `rdb` if needed. The associated key
4446 * will be loaded immediately after this callback returns.
4447 * - Parameters:
4448 * > rdb: RDB I/O context (use RedisModule_Load*() functions to read data)
4449 * > meta: Pointer to 8-byte metadata slot (write your deserialized value here)
4450 * > encver: Encoding version (the metadata class version at save time)
4451 * - Return values:
4452 * > 1: Attach value `*meta` to the key (success)
4453 * > 0: Ignore/skip metadata (don't attach, but continue loading - not an error)
4454 * > -1: Error - abort RDB load (e.g., invalid data, version incompatibility)
4455 * Module MUST clean up any allocated metadata before returning -1.
4456 *
4457 * * **rdb_save**: A callback function pointer for RDB saving (optional).
4458 * - If set to NULL, Redis will not save metadata to RDB.
4459 * - Callback should write data using RDB assisting functions: RedisModule_Save*().
4460 *
4461 * * **aof_rewrite**: A callback function pointer for AOF rewrite (optional).
4462 * Called during AOF rewrite to emit commands that reconstruct the metadata.
4463 * IMPORTANT: For AOF/RDB persistence to work correctly, metadata classes must be
4464 * registered in RedisModule_OnLoad() so they are available when loading persisted
4465 * data on server startup.
4466 *
4467 * * **defrag**: A callback function pointer for active defragmentation (optional).
4468 * If the metadata contains pointers, this callback should defragment them.
4469 *
4470 * * **mem_usage**: A callback function pointer for MEMORY USAGE command (optional).
4471 * Should return the memory used by the metadata in bytes.
4472 *
4473 * * **free_effort**: A callback function pointer for lazy free (optional).
4474 * Should return the complexity of freeing the metadata to determine if
4475 * lazy free should be used.
4476 *
4477 * Note: the metadata class name "AAAAAAAAA" is reserved and produces an error.
4478 *
4479 * If RM_CreateKeyMetaClass() is called outside of RedisModule_OnLoad() function,
4480 * there is already a metadata class registered with the same name,
4481 * or if the metadata class name or metaver is invalid, a negative value is returned.
4482 * Otherwise the new metadata class is registered into Redis, and a reference of
4483 * type RedisModuleKeyMetaClassId is returned: the caller of the function should store
4484 * this reference into a global variable to make future use of it in the
4485 * modules metadata API, since a single module may register multiple metadata classes.
4486 * Example code fragment:
4487 *
4488 * static RedisModuleKeyMetaClassId IndexMetaClass;
4489 *
4490 * int RedisModule_OnLoad(RedisModuleCtx *ctx) {
4491 * // some code here ...
4492 * IndexMetaClass = RM_CreateKeyMetaClass(...);
4493 * }
4494 */
4495RedisModuleKeyMetaClassId RM_CreateKeyMetaClass(RedisModuleCtx *ctx,
4496 const char *metaname,
4497 int metaver,
4498 void *confPtr)
4499{
4500 RedisModuleKeyMetaClassId id;
4501
4502 /* Allow registration only OnLoad (and when debug commands disabled) */
4503 if ((!ctx->module->onload) && (server.enable_debug_cmd == PROTECTED_ACTION_ALLOWED_NO))
4504 return -1;
4505
4506 if (!confPtr)
4507 return -2;
4508
4509 /* This structure supposed to evolve over time and defines the superset of all
4510 * module type methods supported across different Redis module API versions */
4511 struct KeyMetaConfAllVersions {
4512 uint64_t version;
4513 uint64_t flags;
4514 uint64_t reset_value;
4515 KeyMetaCopyFunc copy;
4516 KeyMetaRenameFunc rename;
4517 KeyMetaMoveFunc move;
4518 KeyMetaUnlinkFunc unlink;
4519 KeyMetaFreeFunc free;
4520 /********** TBD: **********/
4521 KeyMetaLoadFunc rdb_load;
4522 KeyMetaSaveFunc rdb_save;
4523 KeyMetaAOFRewriteFunc aof_rewrite;
4524 KeyMetaDefragFunc defrag;
4525 KeyMetaMemUsageFunc mem_usage;
4526 KeyMetaFreeEffortFunc free_effort;
4527 } *legacy = (struct KeyMetaConfAllVersions *)confPtr;
4528
4529 if (legacy->version == 0 || legacy->version > REDISMODULE_KEY_META_VERSION)
4530 return -3;
4531
4532 KeyMetaClassConf conf = {
4533 .flags = legacy->flags,
4534 .reset_value = legacy->reset_value,
4535
4536 .copy = legacy->copy,
4537 .rename = legacy->rename,
4538 .move = legacy->move,
4539 .unlink = legacy->unlink,
4540 .free = legacy->free,
4541
4542 .rdb_load = legacy->rdb_load,
4543 .rdb_save = legacy->rdb_save,
4544 .aof_rewrite = legacy->aof_rewrite,
4545 .defrag = legacy->defrag,
4546 .mem_usage = legacy->mem_usage,
4547 .free_effort = legacy->free_effort
4548 };
4549
4550 id = keyMetaClassCreate(ctx->module, metaname, metaver, &conf);
4551 if (id == 0) return -4;
4552
4553 return id;
4554}
4555
4556/* Release a class by its ID. Returns 1 on success, 0 on failure. */
4557int RM_ReleaseKeyMetaClass(RedisModuleKeyMetaClassId id) {
4558 return (keyMetaClassRelease(id)) ? REDISMODULE_OK : REDISMODULE_ERR;
4559}
4560
4561/* Set metadata of class id on an opened key. If metadata is already attached,
4562 * it will be overwritten. The caller is responsible for retrieving and freeing
4563 * any existing pointer-based metadata before setting a new value. */
4564int RM_SetKeyMeta(RedisModuleKeyMetaClassId id, RedisModuleKey *key, uint64_t metadata) {
4565 if ((!key) || !(key->mode & REDISMODULE_WRITE) || (key->kv == NULL))
4566 return REDISMODULE_ERR;
4567
4568 kvobj *new_kv = keyMetaSetMetadata(key->db, key->kv, id, metadata);
4569 if (new_kv == NULL)
4570 return REDISMODULE_ERR;
4571
4572 /* Update the key->kv pointer in case it was reallocated */
4573 key->kv = new_kv;
4574
4575 return REDISMODULE_OK;
4576}
4577
4578/* Get metadata of class id from an opened key. */
4579int RM_GetKeyMeta(RedisModuleKeyMetaClassId id, RedisModuleKey *key, uint64_t *metadata) {
4580 if ((!key) || (key->kv == NULL) || (!metadata))
4581 return REDISMODULE_ERR;
4582
4583 if (keyMetaGetMetadata(id, key->kv, metadata) == 0)
4584 return REDISMODULE_ERR;
4585
4586 return REDISMODULE_OK;
4587}
4588
4589/* Performs similar operation to FLUSHALL, and optionally start a new AOF file (if enabled)
4590 * If restart_aof is true, you must make sure the command that triggered this call is not
4591 * propagated to the AOF file.
4592 * When async is set to true, db contents will be freed by a background thread. */
4593void RM_ResetDataset(int restart_aof, int async) {
4594 if (restart_aof && server.aof_state != AOF_OFF) stopAppendOnly();
4595 flushAllDataAndResetRDB((async? EMPTYDB_ASYNC: EMPTYDB_NO_FLAGS) | EMPTYDB_NOFUNCTIONS);
4596 if (server.aof_enabled && restart_aof) startAppendOnlyWithRetry();
4597}
4598
4599/* Returns the number of keys in the current db. */
4600unsigned long long RM_DbSize(RedisModuleCtx *ctx) {
4601 return dbSize(ctx->client->db);
4602}
4603
4604/* Returns a name of a random key, or NULL if current db is empty. */
4605RedisModuleString *RM_RandomKey(RedisModuleCtx *ctx) {
4606 robj *key = dbRandomKey(ctx->client->db);
4607 autoMemoryAdd(ctx,REDISMODULE_AM_STRING,key);
4608 return key;
4609}
4610
4611/* Returns the name of the key currently being processed. */
4612const RedisModuleString *RM_GetKeyNameFromOptCtx(RedisModuleKeyOptCtx *ctx) {
4613 return ctx->from_key;
4614}
4615
4616/* Returns the name of the target key currently being processed. */
4617const RedisModuleString *RM_GetToKeyNameFromOptCtx(RedisModuleKeyOptCtx *ctx) {
4618 return ctx->to_key;
4619}
4620
4621/* Returns the dbid currently being processed. */
4622int RM_GetDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx) {
4623 return ctx->from_dbid;
4624}
4625
4626/* Returns the target dbid currently being processed. */
4627int RM_GetToDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx) {
4628 return ctx->to_dbid;
4629}
4630/* --------------------------------------------------------------------------
4631 * ## Key API for String type
4632 *
4633 * See also RM_ValueLength(), which returns the length of a string.
4634 * -------------------------------------------------------------------------- */
4635
4636/* If the key is open for writing, set the specified string 'str' as the
4637 * value of the key, deleting the old value if any.
4638 * On success REDISMODULE_OK is returned. If the key is not open for
4639 * writing or there is an active iterator, REDISMODULE_ERR is returned. */
4640int RM_StringSet(RedisModuleKey *key, RedisModuleString *str) {
4641 if (!(key->mode & REDISMODULE_WRITE) || key->iter) return REDISMODULE_ERR;
4642 RM_DeleteKey(key);
4643 /* Retain str so setKey copies it to db rather than reallocating it. */
4644 incrRefCount(str);
4645 setKey(key->ctx->client,key->db,key->key,&str,SETKEY_NO_SIGNAL);
4646 key->kv = str;
4647 return REDISMODULE_OK;
4648}
4649
4650/* Prepare the key associated string value for DMA access, and returns
4651 * a pointer and size (by reference), that the user can use to read or
4652 * modify the string in-place accessing it directly via pointer.
4653 *
4654 * The 'mode' is composed by bitwise OR-ing the following flags:
4655 *
4656 * REDISMODULE_READ -- Read access
4657 * REDISMODULE_WRITE -- Write access
4658 *
4659 * If the DMA is not requested for writing, the pointer returned should
4660 * only be accessed in a read-only fashion.
4661 *
4662 * On error (wrong type) NULL is returned.
4663 *
4664 * DMA access rules:
4665 *
4666 * 1. No other key writing function should be called since the moment
4667 * the pointer is obtained, for all the time we want to use DMA access
4668 * to read or modify the string.
4669 *
4670 * 2. Each time RM_StringTruncate() is called, to continue with the DMA
4671 * access, RM_StringDMA() should be called again to re-obtain
4672 * a new pointer and length.
4673 *
4674 * 3. If the returned pointer is not NULL, but the length is zero, no
4675 * byte can be touched (the string is empty, or the key itself is empty)
4676 * so a RM_StringTruncate() call should be used if there is to enlarge
4677 * the string, and later call StringDMA() again to get the pointer.
4678 */
4679char *RM_StringDMA(RedisModuleKey *key, size_t *len, int mode) {
4680 /* We need to return *some* pointer for empty keys, we just return
4681 * a string literal pointer, that is the advantage to be mapped into
4682 * a read only memory page, so the module will segfault if a write
4683 * attempt is performed. */
4684 char *emptystring = "<dma-empty-string>";
4685 if (key->kv == NULL) {
4686 *len = 0;
4687 return emptystring;
4688 }
4689
4690 if (key->kv->type != OBJ_STRING) return NULL;
4691
4692 /* For write access, and even for read access if the object is encoded,
4693 * we unshare the string (that has the side effect of decoding it). */
4694 if ((mode & REDISMODULE_WRITE) || key->kv->encoding != OBJ_ENCODING_RAW)
4695 key->kv = dbUnshareStringValue(key->db, key->key, key->kv);
4696
4697 *len = sdslen(key->kv->ptr);
4698 return key->kv->ptr;
4699}
4700
4701/* If the key is open for writing and is of string type, resize it, padding
4702 * with zero bytes if the new length is greater than the old one.
4703 *
4704 * After this call, RM_StringDMA() must be called again to continue
4705 * DMA access with the new pointer.
4706 *
4707 * The function returns REDISMODULE_OK on success, and REDISMODULE_ERR on
4708 * error, that is, the key is not open for writing, is not a string
4709 * or resizing for more than 512 MB is requested.
4710 *
4711 * If the key is empty, a string key is created with the new string value
4712 * unless the new length value requested is zero. */
4713int RM_StringTruncate(RedisModuleKey *key, size_t newlen) {
4714 if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
4715 if (key->kv && key->kv->type != OBJ_STRING) return REDISMODULE_ERR;
4716 if (newlen > 512*1024*1024) return REDISMODULE_ERR;
4717
4718 /* Empty key and new len set to 0. Just return REDISMODULE_OK without
4719 * doing anything. */
4720 if (key->kv == NULL && newlen == 0) return REDISMODULE_OK;
4721
4722 if (key->kv == NULL) {
4723 /* Empty key: create it with the new size. */
4724 robj *o = createObject(OBJ_STRING,sdsnewlen(NULL, newlen));
4725 setKey(key->ctx->client, key->db, key->key, &o, SETKEY_NO_SIGNAL);
4726 key->kv = o;
4727 } else {
4728 /* Unshare and resize. */
4729 key->kv = dbUnshareStringValue(key->db, key->key, key->kv);
4730 size_t curlen = sdslen(key->kv->ptr);
4731 if (newlen > curlen) {
4732 key->kv->ptr = sdsgrowzero(key->kv->ptr,newlen);
4733 } else if (newlen < curlen) {
4734 sdssubstr(key->kv->ptr,0,newlen);
4735 /* If the string is too wasteful, reallocate it. */
4736 if (sdslen(key->kv->ptr) < sdsavail(key->kv->ptr))
4737 key->kv->ptr = sdsRemoveFreeSpace(key->kv->ptr, 0);
4738 }
4739 }
4740 return REDISMODULE_OK;
4741}
4742
4743/* --------------------------------------------------------------------------
4744 * ## Key API for List type
4745 *
4746 * Many of the list functions access elements by index. Since a list is in
4747 * essence a doubly-linked list, accessing elements by index is generally an
4748 * O(N) operation. However, if elements are accessed sequentially or with
4749 * indices close together, the functions are optimized to seek the index from
4750 * the previous index, rather than seeking from the ends of the list.
4751 *
4752 * This enables iteration to be done efficiently using a simple for loop:
4753 *
4754 * long n = RM_ValueLength(key);
4755 * for (long i = 0; i < n; i++) {
4756 * RedisModuleString *elem = RedisModule_ListGet(key, i);
4757 * // Do stuff...
4758 * }
4759 *
4760 * Note that after modifying a list using RM_ListPop, RM_ListSet or
4761 * RM_ListInsert, the internal iterator is invalidated so the next operation
4762 * will require a linear seek.
4763 *
4764 * Modifying a list in any another way, for example using RM_Call(), while a key
4765 * is open will confuse the internal iterator and may cause trouble if the key
4766 * is used after such modifications. The key must be reopened in this case.
4767 *
4768 * See also RM_ValueLength(), which returns the length of a list.
4769 * -------------------------------------------------------------------------- */
4770
4771/* Seeks the key's internal list iterator to the given index. On success, 1 is
4772 * returned and key->iter, key->u.list.entry and key->u.list.index are set. On
4773 * failure, 0 is returned and errno is set as required by the list API
4774 * functions. */
4775int moduleListIteratorSeek(RedisModuleKey *key, long index, int mode) {
4776 if (!key) {
4777 errno = EINVAL;
4778 return 0;
4779 } else if (!key->kv || key->kv->type != OBJ_LIST) {
4780 errno = ENOTSUP;
4781 return 0;
4782 } if (!(key->mode & mode)) {
4783 errno = EBADF;
4784 return 0;
4785 }
4786
4787 long length = listTypeLength(key->kv);
4788 if (index < -length || index >= length) {
4789 errno = EDOM; /* Invalid index */
4790 return 0;
4791 }
4792
4793 if (key->iter == NULL) {
4794 /* No existing iterator. Create one. */
4795 key->iter = zmalloc(sizeof(listTypeIterator));
4796 listTypeInitIterator(key->iter, key->kv, index, LIST_TAIL);
4797 serverAssert(listTypeNext(key->iter, &key->u.list.entry));
4798 key->u.list.index = index;
4799 return 1;
4800 }
4801
4802 /* There's an existing iterator. Make sure the requested index has the same
4803 * sign as the iterator's index. */
4804 if (index < 0 && key->u.list.index >= 0) index += length;
4805 else if (index >= 0 && key->u.list.index < 0) index -= length;
4806
4807 if (index == key->u.list.index) return 1; /* We're done. */
4808
4809 /* Seek the iterator to the requested index. */
4810 unsigned char dir = key->u.list.index < index ? LIST_TAIL : LIST_HEAD;
4811 listTypeSetIteratorDirection(key->iter, &key->u.list.entry, dir);
4812 while (key->u.list.index != index) {
4813 serverAssert(listTypeNext(key->iter, &key->u.list.entry));
4814 key->u.list.index += dir == LIST_HEAD ? -1 : 1;
4815 }
4816 return 1;
4817}
4818
4819/* Push an element into a list, on head or tail depending on 'where' argument
4820 * (REDISMODULE_LIST_HEAD or REDISMODULE_LIST_TAIL). If the key refers to an
4821 * empty key opened for writing, the key is created. On success, REDISMODULE_OK
4822 * is returned. On failure, REDISMODULE_ERR is returned and `errno` is set as
4823 * follows:
4824 *
4825 * - EINVAL if key or ele is NULL.
4826 * - ENOTSUP if the key is of another type than list.
4827 * - EBADF if the key is not opened for writing.
4828 *
4829 * Note: Before Redis 7.0, `errno` was not set by this function. */
4830int RM_ListPush(RedisModuleKey *key, int where, RedisModuleString *ele) {
4831 size_t oldsize = 0;
4832 if (!key || !ele) {
4833 errno = EINVAL;
4834 return REDISMODULE_ERR;
4835 } else if (key->kv != NULL && key->kv->type != OBJ_LIST) {
4836 errno = ENOTSUP;
4837 return REDISMODULE_ERR;
4838 } if (!(key->mode & REDISMODULE_WRITE)) {
4839 errno = EBADF;
4840 return REDISMODULE_ERR;
4841 }
4842
4843 if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
4844 if (key->kv && key->kv->type != OBJ_LIST) return REDISMODULE_ERR;
4845 if (key->iter) moduleFreeKeyIterator(key);
4846 if (key->kv == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_LIST);
4847 if (server.memory_tracking_per_slot)
4848 oldsize = listTypeAllocSize(key->kv);
4849 listTypeTryConversionAppend(key->kv, &ele, 0, 0, moduleFreeListIterator, key);
4850 listTypePush(key->kv, ele,
4851 (where == REDISMODULE_LIST_HEAD) ? LIST_HEAD : LIST_TAIL);
4852 int64_t l = listTypeLength(key->kv);
4853 updateKeysizesHist(key->db, getKeySlot(key->key->ptr), OBJ_LIST, l-1, l);
4854 if (server.memory_tracking_per_slot)
4855 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
4856 return REDISMODULE_OK;
4857}
4858
4859/* Pop an element from the list, and returns it as a module string object
4860 * that the user should be free with RM_FreeString() or by enabling
4861 * automatic memory. The `where` argument specifies if the element should be
4862 * popped from the beginning or the end of the list (REDISMODULE_LIST_HEAD or
4863 * REDISMODULE_LIST_TAIL). On failure, the command returns NULL and sets
4864 * `errno` as follows:
4865 *
4866 * - EINVAL if key is NULL.
4867 * - ENOTSUP if the key is empty or of another type than list.
4868 * - EBADF if the key is not opened for writing.
4869 *
4870 * Note: Before Redis 7.0, `errno` was not set by this function. */
4871RedisModuleString *RM_ListPop(RedisModuleKey *key, int where) {
4872 size_t oldsize = 0;
4873 if (!key) {
4874 errno = EINVAL;
4875 return NULL;
4876 } else if (key->kv == NULL || key->kv->type != OBJ_LIST) {
4877 errno = ENOTSUP;
4878 return NULL;
4879 } else if (!(key->mode & REDISMODULE_WRITE)) {
4880 errno = EBADF;
4881 return NULL;
4882 }
4883 if (key->iter) moduleFreeKeyIterator(key);
4884 if (server.memory_tracking_per_slot)
4885 oldsize = listTypeAllocSize(key->kv);
4886 robj *ele = listTypePop(key->kv,
4887 (where == REDISMODULE_LIST_HEAD) ? LIST_HEAD : LIST_TAIL);
4888 robj *decoded = getDecodedObject(ele);
4889 decrRefCount(ele);
4890 int64_t l = (int64_t) listTypeLength(key->kv);
4891 updateKeysizesHist(key->db, getKeySlot(key->key->ptr), OBJ_LIST, l+1, l);
4892 if (server.memory_tracking_per_slot)
4893 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
4894 if (!moduleDelKeyIfEmpty(key)) {
4895 if (server.memory_tracking_per_slot)
4896 oldsize = listTypeAllocSize(key->kv);
4897 listTypeTryConversion(key->kv, LIST_CONV_SHRINKING, moduleFreeListIterator, key);
4898 if (server.memory_tracking_per_slot)
4899 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
4900 }
4901 autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,decoded);
4902 return decoded;
4903}
4904
4905/* Returns the element at index `index` in the list stored at `key`, like the
4906 * LINDEX command. The element should be free'd using RM_FreeString() or using
4907 * automatic memory management.
4908 *
4909 * The index is zero-based, so 0 means the first element, 1 the second element
4910 * and so on. Negative indices can be used to designate elements starting at the
4911 * tail of the list. Here, -1 means the last element, -2 means the penultimate
4912 * and so forth.
4913 *
4914 * When no value is found at the given key and index, NULL is returned and
4915 * `errno` is set as follows:
4916 *
4917 * - EINVAL if key is NULL.
4918 * - ENOTSUP if the key is not a list.
4919 * - EBADF if the key is not opened for reading.
4920 * - EDOM if the index is not a valid index in the list.
4921 */
4922RedisModuleString *RM_ListGet(RedisModuleKey *key, long index) {
4923 if (moduleListIteratorSeek(key, index, REDISMODULE_READ)) {
4924 robj *elem = listTypeGet(&key->u.list.entry);
4925 robj *decoded = getDecodedObject(elem);
4926 decrRefCount(elem);
4927 autoMemoryAdd(key->ctx, REDISMODULE_AM_STRING, decoded);
4928 return decoded;
4929 } else {
4930 return NULL;
4931 }
4932}
4933
4934/* Replaces the element at index `index` in the list stored at `key`.
4935 *
4936 * The index is zero-based, so 0 means the first element, 1 the second element
4937 * and so on. Negative indices can be used to designate elements starting at the
4938 * tail of the list. Here, -1 means the last element, -2 means the penultimate
4939 * and so forth.
4940 *
4941 * On success, REDISMODULE_OK is returned. On failure, REDISMODULE_ERR is
4942 * returned and `errno` is set as follows:
4943 *
4944 * - EINVAL if key or value is NULL.
4945 * - ENOTSUP if the key is not a list.
4946 * - EBADF if the key is not opened for writing.
4947 * - EDOM if the index is not a valid index in the list.
4948 */
4949int RM_ListSet(RedisModuleKey *key, long index, RedisModuleString *value) {
4950 size_t oldsize = 0;
4951 if (!value) {
4952 errno = EINVAL;
4953 return REDISMODULE_ERR;
4954 }
4955 if (!key->kv || key->kv->type != OBJ_LIST) {
4956 errno = ENOTSUP;
4957 return REDISMODULE_ERR;
4958 }
4959 if (server.memory_tracking_per_slot)
4960 oldsize = listTypeAllocSize(key->kv);
4961 listTypeTryConversionAppend(key->kv, &value, 0, 0, moduleFreeListIterator, key);
4962 if (moduleListIteratorSeek(key, index, REDISMODULE_WRITE)) {
4963 listTypeReplace(&key->u.list.entry, value);
4964 if (server.memory_tracking_per_slot)
4965 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
4966 /* A note in quicklist.c forbids use of iterator after insert, so
4967 * probably also after replace. */
4968 moduleFreeKeyIterator(key);
4969 return REDISMODULE_OK;
4970 } else {
4971 if (server.memory_tracking_per_slot)
4972 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
4973 return REDISMODULE_ERR;
4974 }
4975}
4976
4977/* Inserts an element at the given index.
4978 *
4979 * The index is zero-based, so 0 means the first element, 1 the second element
4980 * and so on. Negative indices can be used to designate elements starting at the
4981 * tail of the list. Here, -1 means the last element, -2 means the penultimate
4982 * and so forth. The index is the element's index after inserting it.
4983 *
4984 * On success, REDISMODULE_OK is returned. On failure, REDISMODULE_ERR is
4985 * returned and `errno` is set as follows:
4986 *
4987 * - EINVAL if key or value is NULL.
4988 * - ENOTSUP if the key of another type than list.
4989 * - EBADF if the key is not opened for writing.
4990 * - EDOM if the index is not a valid index in the list.
4991 */
4992int RM_ListInsert(RedisModuleKey *key, long index, RedisModuleString *value) {
4993 size_t oldsize = 0;
4994 if (!value) {
4995 errno = EINVAL;
4996 return REDISMODULE_ERR;
4997 } else if (key != NULL && key->kv == NULL &&
4998 (index == 0 || index == -1)) {
4999 /* Insert in empty key => push. */
5000 return RM_ListPush(key, REDISMODULE_LIST_TAIL, value);
5001 } else if (key != NULL && key->kv != NULL &&
5002 key->kv->type == OBJ_LIST &&
5003 (index == (long)listTypeLength(key->kv) || index == -1)) {
5004 /* Insert after the last element => push tail. */
5005 return RM_ListPush(key, REDISMODULE_LIST_TAIL, value);
5006 } else if (key != NULL && key->kv != NULL &&
5007 key->kv->type == OBJ_LIST &&
5008 (index == 0 || index == -(long)listTypeLength(key->kv) - 1)) {
5009 /* Insert before the first element => push head. */
5010 return RM_ListPush(key, REDISMODULE_LIST_HEAD, value);
5011 }
5012 if (server.memory_tracking_per_slot)
5013 oldsize = listTypeAllocSize(key->kv);
5014 listTypeTryConversionAppend(key->kv, &value, 0, 0, moduleFreeListIterator, key);
5015 if (moduleListIteratorSeek(key, index, REDISMODULE_WRITE)) {
5016 int where = index < 0 ? LIST_TAIL : LIST_HEAD;
5017 listTypeInsert(&key->u.list.entry, value, where);
5018 int64_t l = (int64_t) listTypeLength(key->kv);
5019 updateKeysizesHist(key->db, getKeySlot(key->key->ptr), OBJ_LIST, l-1, l);
5020 if (server.memory_tracking_per_slot)
5021 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
5022 /* A note in quicklist.c forbids use of iterator after insert. */
5023 moduleFreeKeyIterator(key);
5024 return REDISMODULE_OK;
5025 } else {
5026 if (server.memory_tracking_per_slot)
5027 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
5028 return REDISMODULE_ERR;
5029 }
5030}
5031
5032/* Removes an element at the given index. The index is 0-based. A negative index
5033 * can also be used, counting from the end of the list.
5034 *
5035 * On success, REDISMODULE_OK is returned. On failure, REDISMODULE_ERR is
5036 * returned and `errno` is set as follows:
5037 *
5038 * - EINVAL if key or value is NULL.
5039 * - ENOTSUP if the key is not a list.
5040 * - EBADF if the key is not opened for writing.
5041 * - EDOM if the index is not a valid index in the list.
5042 */
5043int RM_ListDelete(RedisModuleKey *key, long index) {
5044 if (moduleListIteratorSeek(key, index, REDISMODULE_WRITE)) {
5045 size_t oldsize = 0;
5046 if (server.memory_tracking_per_slot)
5047 oldsize = listTypeAllocSize(key->kv);
5048 listTypeDelete(key->iter, &key->u.list.entry);
5049 int64_t l = (int64_t) listTypeLength(key->kv);
5050 updateKeysizesHist(key->db, getKeySlot(key->key->ptr), OBJ_LIST, l+1, l);
5051 if (server.memory_tracking_per_slot)
5052 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
5053 if (moduleDelKeyIfEmpty(key)) return REDISMODULE_OK;
5054 if (server.memory_tracking_per_slot)
5055 oldsize = listTypeAllocSize(key->kv);
5056 listTypeTryConversion(key->kv, LIST_CONV_SHRINKING, moduleFreeListIterator, key);
5057 if (server.memory_tracking_per_slot)
5058 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, listTypeAllocSize(key->kv));
5059 if (!key->iter) return REDISMODULE_OK; /* Return ASAP if iterator has been freed */
5060 if (listTypeNext(key->iter, &key->u.list.entry)) {
5061 /* After delete entry at position 'index', we need to update
5062 * 'key->u.list.index' according to the following cases:
5063 * 1) [1, 2, 3] => dir: forward, index: 0 => [2, 3] => index: still 0
5064 * 2) [1, 2, 3] => dir: forward, index: -3 => [2, 3] => index: -2
5065 * 3) [1, 2, 3] => dir: reverse, index: 2 => [1, 2] => index: 1
5066 * 4) [1, 2, 3] => dir: reverse, index: -1 => [1, 2] => index: still -1 */
5067 listTypeIterator *li = key->iter;
5068 int reverse = li->direction == LIST_HEAD;
5069 if (key->u.list.index < 0)
5070 key->u.list.index += reverse ? 0 : 1;
5071 else
5072 key->u.list.index += reverse ? -1 : 0;
5073 } else {
5074 /* Reset list iterator if the next entry doesn't exist. */
5075 moduleFreeKeyIterator(key);
5076 }
5077 return REDISMODULE_OK;
5078 } else {
5079 return REDISMODULE_ERR;
5080 }
5081}
5082
5083/* --------------------------------------------------------------------------
5084 * ## Key API for Sorted Set type
5085 *
5086 * See also RM_ValueLength(), which returns the length of a sorted set.
5087 * -------------------------------------------------------------------------- */
5088
5089/* Conversion from/to public flags of the Modules API and our private flags,
5090 * so that we have everything decoupled. */
5091int moduleZsetAddFlagsToCoreFlags(int flags) {
5092 int retflags = 0;
5093 if (flags & REDISMODULE_ZADD_XX) retflags |= ZADD_IN_XX;
5094 if (flags & REDISMODULE_ZADD_NX) retflags |= ZADD_IN_NX;
5095 if (flags & REDISMODULE_ZADD_GT) retflags |= ZADD_IN_GT;
5096 if (flags & REDISMODULE_ZADD_LT) retflags |= ZADD_IN_LT;
5097 return retflags;
5098}
5099
5100/* See previous function comment. */
5101int moduleZsetAddFlagsFromCoreFlags(int flags) {
5102 int retflags = 0;
5103 if (flags & ZADD_OUT_ADDED) retflags |= REDISMODULE_ZADD_ADDED;
5104 if (flags & ZADD_OUT_UPDATED) retflags |= REDISMODULE_ZADD_UPDATED;
5105 if (flags & ZADD_OUT_NOP) retflags |= REDISMODULE_ZADD_NOP;
5106 return retflags;
5107}
5108
5109/* Add a new element into a sorted set, with the specified 'score'.
5110 * If the element already exists, the score is updated.
5111 *
5112 * A new sorted set is created at value if the key is an empty open key
5113 * setup for writing.
5114 *
5115 * Additional flags can be passed to the function via a pointer, the flags
5116 * are both used to receive input and to communicate state when the function
5117 * returns. 'flagsptr' can be NULL if no special flags are used.
5118 *
5119 * The input flags are:
5120 *
5121 * REDISMODULE_ZADD_XX: Element must already exist. Do nothing otherwise.
5122 * REDISMODULE_ZADD_NX: Element must not exist. Do nothing otherwise.
5123 * REDISMODULE_ZADD_GT: If element exists, new score must be greater than the current score.
5124 * Do nothing otherwise. Can optionally be combined with XX.
5125 * REDISMODULE_ZADD_LT: If element exists, new score must be less than the current score.
5126 * Do nothing otherwise. Can optionally be combined with XX.
5127 *
5128 * The output flags are:
5129 *
5130 * REDISMODULE_ZADD_ADDED: The new element was added to the sorted set.
5131 * REDISMODULE_ZADD_UPDATED: The score of the element was updated.
5132 * REDISMODULE_ZADD_NOP: No operation was performed because XX or NX flags.
5133 *
5134 * On success the function returns REDISMODULE_OK. On the following errors
5135 * REDISMODULE_ERR is returned:
5136 *
5137 * * The key was not opened for writing.
5138 * * The key is of the wrong type.
5139 * * 'score' double value is not a number (NaN).
5140 */
5141int RM_ZsetAdd(RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr) {
5142 int in_flags = 0, out_flags = 0;
5143 size_t oldsize = 0;
5144 if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
5145 if (key->kv && key->kv->type != OBJ_ZSET) return REDISMODULE_ERR;
5146 if (key->kv == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_ZSET);
5147 if (server.memory_tracking_per_slot)
5148 oldsize = zsetAllocSize(key->kv);
5149 if (flagsptr) in_flags = moduleZsetAddFlagsToCoreFlags(*flagsptr);
5150 if (zsetAdd(key->kv,score,ele->ptr,in_flags,&out_flags,NULL) == 0) {
5151 if (flagsptr) *flagsptr = 0;
5152 if (server.memory_tracking_per_slot)
5153 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, zsetAllocSize(key->kv));
5154 moduleDelKeyIfEmpty(key);
5155 return REDISMODULE_ERR;
5156 }
5157 if (flagsptr) *flagsptr = moduleZsetAddFlagsFromCoreFlags(out_flags);
5158 int64_t l = (int64_t) zsetLength(key->kv);
5159 updateKeysizesHist(key->db, getKeySlot(key->key->ptr), OBJ_ZSET, l-1, l);
5160 if (server.memory_tracking_per_slot)
5161 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, zsetAllocSize(key->kv));
5162 return REDISMODULE_OK;
5163}
5164
5165/* This function works exactly like RM_ZsetAdd(), but instead of setting
5166 * a new score, the score of the existing element is incremented, or if the
5167 * element does not already exist, it is added assuming the old score was
5168 * zero.
5169 *
5170 * The input and output flags, and the return value, have the same exact
5171 * meaning, with the only difference that this function will return
5172 * REDISMODULE_ERR even when 'score' is a valid double number, but adding it
5173 * to the existing score results into a NaN (not a number) condition.
5174 *
5175 * This function has an additional field 'newscore', if not NULL is filled
5176 * with the new score of the element after the increment, if no error
5177 * is returned. */
5178int RM_ZsetIncrby(RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr, double *newscore) {
5179 int in_flags = 0, out_flags = 0;
5180 size_t oldsize = 0;
5181 if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
5182 if (key->kv && key->kv->type != OBJ_ZSET) return REDISMODULE_ERR;
5183 if (key->kv == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_ZSET);
5184 if (server.memory_tracking_per_slot)
5185 oldsize = zsetAllocSize(key->kv);
5186 if (flagsptr) in_flags = moduleZsetAddFlagsToCoreFlags(*flagsptr);
5187 in_flags |= ZADD_IN_INCR;
5188 if (zsetAdd(key->kv,score,ele->ptr,in_flags,&out_flags,newscore) == 0) {
5189 if (flagsptr) *flagsptr = 0;
5190 if (server.memory_tracking_per_slot)
5191 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, zsetAllocSize(key->kv));
5192 moduleDelKeyIfEmpty(key);
5193 return REDISMODULE_ERR;
5194 }
5195 if (server.memory_tracking_per_slot)
5196 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, zsetAllocSize(key->kv));
5197 if (out_flags & ZADD_OUT_ADDED) {
5198 int64_t l = (int64_t) zsetLength(key->kv);
5199 updateKeysizesHist(key->db, getKeySlot(key->key->ptr), OBJ_ZSET, l-1, l);
5200 }
5201 if (flagsptr) *flagsptr = moduleZsetAddFlagsFromCoreFlags(out_flags);
5202 return REDISMODULE_OK;
5203}
5204
5205/* Remove the specified element from the sorted set.
5206 * The function returns REDISMODULE_OK on success, and REDISMODULE_ERR
5207 * on one of the following conditions:
5208 *
5209 * * The key was not opened for writing.
5210 * * The key is of the wrong type.
5211 *
5212 * The return value does NOT indicate the fact the element was really
5213 * removed (since it existed) or not, just if the function was executed
5214 * with success.
5215 *
5216 * In order to know if the element was removed, the additional argument
5217 * 'deleted' must be passed, that populates the integer by reference
5218 * setting it to 1 or 0 depending on the outcome of the operation.
5219 * The 'deleted' argument can be NULL if the caller is not interested
5220 * to know if the element was really removed.
5221 *
5222 * Empty keys will be handled correctly by doing nothing. */
5223int RM_ZsetRem(RedisModuleKey *key, RedisModuleString *ele, int *deleted) {
5224 size_t oldsize = 0;
5225 if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
5226 if (key->kv == NULL) {
5227 if (deleted) *deleted = 0;
5228 return REDISMODULE_OK;
5229 }
5230 if (key->kv->type != OBJ_ZSET) return REDISMODULE_ERR;
5231 if (server.memory_tracking_per_slot)
5232 oldsize = zsetAllocSize(key->kv);
5233 if (zsetDel(key->kv,ele->ptr)) {
5234 if (deleted) *deleted = 1;
5235 int64_t l = (int64_t) zsetLength(key->kv);
5236 updateKeysizesHist(key->db, getKeySlot(key->key->ptr), OBJ_ZSET, l+1, l);
5237 if (server.memory_tracking_per_slot)
5238 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, zsetAllocSize(key->kv));
5239 moduleDelKeyIfEmpty(key);
5240 } else {
5241 if (deleted) *deleted = 0;
5242 if (server.memory_tracking_per_slot)
5243 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, zsetAllocSize(key->kv));
5244 }
5245 return REDISMODULE_OK;
5246}
5247
5248/* On success retrieve the double score associated at the sorted set element
5249 * 'ele' and returns REDISMODULE_OK. Otherwise REDISMODULE_ERR is returned
5250 * to signal one of the following conditions:
5251 *
5252 * * There is no such element 'ele' in the sorted set.
5253 * * The key is not a sorted set.
5254 * * The key is an open empty key.
5255 */
5256int RM_ZsetScore(RedisModuleKey *key, RedisModuleString *ele, double *score) {
5257 if (key->kv == NULL) return REDISMODULE_ERR;
5258 if (key->kv->type != OBJ_ZSET) return REDISMODULE_ERR;
5259 if (zsetScore(key->kv,ele->ptr,score) == C_ERR) return REDISMODULE_ERR;
5260 return REDISMODULE_OK;
5261}
5262
5263/* --------------------------------------------------------------------------
5264 * ## Key API for Sorted Set iterator
5265 * -------------------------------------------------------------------------- */
5266
5267void zsetKeyReset(RedisModuleKey *key) {
5268 key->u.zset.type = REDISMODULE_ZSET_RANGE_NONE;
5269 key->u.zset.current = NULL;
5270 key->u.zset.er = 1;
5271}
5272
5273/* Stop a sorted set iteration. */
5274void RM_ZsetRangeStop(RedisModuleKey *key) {
5275 if (!key->kv || key->kv->type != OBJ_ZSET) return;
5276 /* Free resources if needed. */
5277 if (key->u.zset.type == REDISMODULE_ZSET_RANGE_LEX)
5278 zslFreeLexRange(&key->u.zset.lrs);
5279 /* Setup sensible values so that misused iteration API calls when an
5280 * iterator is not active will result into something more sensible
5281 * than crashing. */
5282 zsetKeyReset(key);
5283}
5284
5285/* Return the "End of range" flag value to signal the end of the iteration. */
5286int RM_ZsetRangeEndReached(RedisModuleKey *key) {
5287 if (!key->kv || key->kv->type != OBJ_ZSET) return 1;
5288 return key->u.zset.er;
5289}
5290
5291/* Helper function for RM_ZsetFirstInScoreRange() and RM_ZsetLastInScoreRange().
5292 * Setup the sorted set iteration according to the specified score range
5293 * (see the functions calling it for more info). If 'first' is true the
5294 * first element in the range is used as a starting point for the iterator
5295 * otherwise the last. Return REDISMODULE_OK on success otherwise
5296 * REDISMODULE_ERR. */
5297int zsetInitScoreRange(RedisModuleKey *key, double min, double max, int minex, int maxex, int first) {
5298 if (!key->kv || key->kv->type != OBJ_ZSET) return REDISMODULE_ERR;
5299
5300 RM_ZsetRangeStop(key);
5301 key->u.zset.type = REDISMODULE_ZSET_RANGE_SCORE;
5302 key->u.zset.er = 0;
5303
5304 /* Setup the range structure used by the sorted set core implementation
5305 * in order to seek at the specified element. */
5306 zrangespec *zrs = &key->u.zset.rs;
5307 zrs->min = min;
5308 zrs->max = max;
5309 zrs->minex = minex;
5310 zrs->maxex = maxex;
5311
5312 if (key->kv->encoding == OBJ_ENCODING_LISTPACK) {
5313 key->u.zset.current = first ? zzlFirstInRange(key->kv->ptr,zrs) :
5314 zzlLastInRange(key->kv->ptr,zrs);
5315 } else if (key->kv->encoding == OBJ_ENCODING_SKIPLIST) {
5316 zset *zs = key->kv->ptr;
5317 zskiplist *zsl = zs->zsl;
5318 key->u.zset.current = first ? zslNthInRange(zsl, zrs, 0, NULL) :
5319 zslNthInRange(zsl, zrs, -1, NULL);
5320 } else {
5321 serverPanic("Unsupported zset encoding");
5322 }
5323 if (key->u.zset.current == NULL) key->u.zset.er = 1;
5324 return REDISMODULE_OK;
5325}
5326
5327/* Setup a sorted set iterator seeking the first element in the specified
5328 * range. Returns REDISMODULE_OK if the iterator was correctly initialized
5329 * otherwise REDISMODULE_ERR is returned in the following conditions:
5330 *
5331 * 1. The value stored at key is not a sorted set or the key is empty.
5332 *
5333 * The range is specified according to the two double values 'min' and 'max'.
5334 * Both can be infinite using the following two macros:
5335 *
5336 * * REDISMODULE_POSITIVE_INFINITE for positive infinite value
5337 * * REDISMODULE_NEGATIVE_INFINITE for negative infinite value
5338 *
5339 * 'minex' and 'maxex' parameters, if true, respectively setup a range
5340 * where the min and max value are exclusive (not included) instead of
5341 * inclusive. */
5342int RM_ZsetFirstInScoreRange(RedisModuleKey *key, double min, double max, int minex, int maxex) {
5343 return zsetInitScoreRange(key,min,max,minex,maxex,1);
5344}
5345
5346/* Exactly like RedisModule_ZsetFirstInScoreRange() but the last element of
5347 * the range is selected for the start of the iteration instead. */
5348int RM_ZsetLastInScoreRange(RedisModuleKey *key, double min, double max, int minex, int maxex) {
5349 return zsetInitScoreRange(key,min,max,minex,maxex,0);
5350}
5351
5352/* Helper function for RM_ZsetFirstInLexRange() and RM_ZsetLastInLexRange().
5353 * Setup the sorted set iteration according to the specified lexicographical
5354 * range (see the functions calling it for more info). If 'first' is true the
5355 * first element in the range is used as a starting point for the iterator
5356 * otherwise the last. Return REDISMODULE_OK on success otherwise
5357 * REDISMODULE_ERR.
5358 *
5359 * Note that this function takes 'min' and 'max' in the same form of the
5360 * Redis ZRANGEBYLEX command. */
5361int zsetInitLexRange(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max, int first) {
5362 if (!key->kv || key->kv->type != OBJ_ZSET) return REDISMODULE_ERR;
5363
5364 RM_ZsetRangeStop(key);
5365 key->u.zset.er = 0;
5366
5367 /* Setup the range structure used by the sorted set core implementation
5368 * in order to seek at the specified element. */
5369 zlexrangespec *zlrs = &key->u.zset.lrs;
5370 if (zslParseLexRange(min, max, zlrs) == C_ERR) return REDISMODULE_ERR;
5371
5372 /* Set the range type to lex only after successfully parsing the range,
5373 * otherwise we don't want the zlexrangespec to be freed. */
5374 key->u.zset.type = REDISMODULE_ZSET_RANGE_LEX;
5375
5376 if (key->kv->encoding == OBJ_ENCODING_LISTPACK) {
5377 key->u.zset.current = first ? zzlFirstInLexRange(key->kv->ptr,zlrs) :
5378 zzlLastInLexRange(key->kv->ptr,zlrs);
5379 } else if (key->kv->encoding == OBJ_ENCODING_SKIPLIST) {
5380 zset *zs = key->kv->ptr;
5381 zskiplist *zsl = zs->zsl;
5382 key->u.zset.current = first ? zslNthInLexRange(zsl,zlrs,0,NULL) :
5383 zslNthInLexRange(zsl,zlrs,-1,NULL);
5384 } else {
5385 serverPanic("Unsupported zset encoding");
5386 }
5387 if (key->u.zset.current == NULL) key->u.zset.er = 1;
5388
5389 return REDISMODULE_OK;
5390}
5391
5392/* Setup a sorted set iterator seeking the first element in the specified
5393 * lexicographical range. Returns REDISMODULE_OK if the iterator was correctly
5394 * initialized otherwise REDISMODULE_ERR is returned in the
5395 * following conditions:
5396 *
5397 * 1. The value stored at key is not a sorted set or the key is empty.
5398 * 2. The lexicographical range 'min' and 'max' format is invalid.
5399 *
5400 * 'min' and 'max' should be provided as two RedisModuleString objects
5401 * in the same format as the parameters passed to the ZRANGEBYLEX command.
5402 * The function does not take ownership of the objects, so they can be released
5403 * ASAP after the iterator is setup. */
5404int RM_ZsetFirstInLexRange(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max) {
5405 return zsetInitLexRange(key,min,max,1);
5406}
5407
5408/* Exactly like RedisModule_ZsetFirstInLexRange() but the last element of
5409 * the range is selected for the start of the iteration instead. */
5410int RM_ZsetLastInLexRange(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max) {
5411 return zsetInitLexRange(key,min,max,0);
5412}
5413
5414/* Return the current sorted set element of an active sorted set iterator
5415 * or NULL if the range specified in the iterator does not include any
5416 * element. */
5417RedisModuleString *RM_ZsetRangeCurrentElement(RedisModuleKey *key, double *score) {
5418 RedisModuleString *str;
5419
5420 if (!key->kv || key->kv->type != OBJ_ZSET) return NULL;
5421 if (key->u.zset.current == NULL) return NULL;
5422 if (key->kv->encoding == OBJ_ENCODING_LISTPACK) {
5423 unsigned char *eptr, *sptr;
5424 eptr = key->u.zset.current;
5425 sds ele = lpGetObject(eptr);
5426 if (score) {
5427 sptr = lpNext(key->kv->ptr,eptr);
5428 *score = zzlGetScore(sptr);
5429 }
5430 str = createObject(OBJ_STRING,ele);
5431 } else if (key->kv->encoding == OBJ_ENCODING_SKIPLIST) {
5432 zskiplistNode *ln = key->u.zset.current;
5433 if (score) *score = ln->score;
5434 sds ele = zslGetNodeElement(ln);
5435 str = createStringObject(ele,sdslen(ele));
5436 } else {
5437 serverPanic("Unsupported zset encoding");
5438 }
5439 autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,str);
5440 return str;
5441}
5442
5443/* Go to the next element of the sorted set iterator. Returns 1 if there was
5444 * a next element, 0 if we are already at the latest element or the range
5445 * does not include any item at all. */
5446int RM_ZsetRangeNext(RedisModuleKey *key) {
5447 if (!key->kv || key->kv->type != OBJ_ZSET) return 0;
5448 if (!key->u.zset.type || !key->u.zset.current) return 0; /* No active iterator. */
5449
5450 if (key->kv->encoding == OBJ_ENCODING_LISTPACK) {
5451 unsigned char *zl = key->kv->ptr;
5452 unsigned char *eptr = key->u.zset.current;
5453 unsigned char *next;
5454 next = lpNext(zl,eptr); /* Skip element. */
5455 if (next) next = lpNext(zl,next); /* Skip score. */
5456 if (next == NULL) {
5457 key->u.zset.er = 1;
5458 return 0;
5459 } else {
5460 /* Are we still within the range? */
5461 if (key->u.zset.type == REDISMODULE_ZSET_RANGE_SCORE) {
5462 /* Fetch the next element score for the
5463 * range check. */
5464 unsigned char *saved_next = next;
5465 next = lpNext(zl,next); /* Skip next element. */
5466 double score = zzlGetScore(next); /* Obtain the next score. */
5467 if (!zslValueLteMax(score,&key->u.zset.rs)) {
5468 key->u.zset.er = 1;
5469 return 0;
5470 }
5471 next = saved_next;
5472 } else if (key->u.zset.type == REDISMODULE_ZSET_RANGE_LEX) {
5473 if (!zzlLexValueLteMax(next,&key->u.zset.lrs)) {
5474 key->u.zset.er = 1;
5475 return 0;
5476 }
5477 }
5478 key->u.zset.current = next;
5479 return 1;
5480 }
5481 } else if (key->kv->encoding == OBJ_ENCODING_SKIPLIST) {
5482 zskiplistNode *ln = key->u.zset.current, *next = ln->level[0].forward;
5483 if (next == NULL) {
5484 key->u.zset.er = 1;
5485 return 0;
5486 } else {
5487 /* Are we still within the range? */
5488 if (key->u.zset.type == REDISMODULE_ZSET_RANGE_SCORE &&
5489 !zslValueLteMax(next->score,&key->u.zset.rs))
5490 {
5491 key->u.zset.er = 1;
5492 return 0;
5493 } else if (key->u.zset.type == REDISMODULE_ZSET_RANGE_LEX) {
5494 if (!zslLexValueLteMax(zslGetNodeElement(next),&key->u.zset.lrs)) {
5495 key->u.zset.er = 1;
5496 return 0;
5497 }
5498 }
5499 key->u.zset.current = next;
5500 return 1;
5501 }
5502 } else {
5503 serverPanic("Unsupported zset encoding");
5504 }
5505}
5506
5507/* Go to the previous element of the sorted set iterator. Returns 1 if there was
5508 * a previous element, 0 if we are already at the first element or the range
5509 * does not include any item at all. */
5510int RM_ZsetRangePrev(RedisModuleKey *key) {
5511 if (!key->kv || key->kv->type != OBJ_ZSET) return 0;
5512 if (!key->u.zset.type || !key->u.zset.current) return 0; /* No active iterator. */
5513
5514 if (key->kv->encoding == OBJ_ENCODING_LISTPACK) {
5515 unsigned char *zl = key->kv->ptr;
5516 unsigned char *eptr = key->u.zset.current;
5517 unsigned char *prev;
5518 prev = lpPrev(zl,eptr); /* Go back to previous score. */
5519 if (prev) prev = lpPrev(zl,prev); /* Back to previous ele. */
5520 if (prev == NULL) {
5521 key->u.zset.er = 1;
5522 return 0;
5523 } else {
5524 /* Are we still within the range? */
5525 if (key->u.zset.type == REDISMODULE_ZSET_RANGE_SCORE) {
5526 /* Fetch the previous element score for the
5527 * range check. */
5528 unsigned char *saved_prev = prev;
5529 prev = lpNext(zl,prev); /* Skip element to get the score.*/
5530 double score = zzlGetScore(prev); /* Obtain the prev score. */
5531 if (!zslValueGteMin(score,&key->u.zset.rs)) {
5532 key->u.zset.er = 1;
5533 return 0;
5534 }
5535 prev = saved_prev;
5536 } else if (key->u.zset.type == REDISMODULE_ZSET_RANGE_LEX) {
5537 if (!zzlLexValueGteMin(prev,&key->u.zset.lrs)) {
5538 key->u.zset.er = 1;
5539 return 0;
5540 }
5541 }
5542 key->u.zset.current = prev;
5543 return 1;
5544 }
5545 } else if (key->kv->encoding == OBJ_ENCODING_SKIPLIST) {
5546 zskiplistNode *ln = key->u.zset.current, *prev = ln->backward;
5547 if (prev == NULL) {
5548 key->u.zset.er = 1;
5549 return 0;
5550 } else {
5551 /* Are we still within the range? */
5552 if (key->u.zset.type == REDISMODULE_ZSET_RANGE_SCORE &&
5553 !zslValueGteMin(prev->score,&key->u.zset.rs))
5554 {
5555 key->u.zset.er = 1;
5556 return 0;
5557 } else if (key->u.zset.type == REDISMODULE_ZSET_RANGE_LEX) {
5558 if (!zslLexValueGteMin(zslGetNodeElement(prev),&key->u.zset.lrs)) {
5559 key->u.zset.er = 1;
5560 return 0;
5561 }
5562 }
5563 key->u.zset.current = prev;
5564 return 1;
5565 }
5566 } else {
5567 serverPanic("Unsupported zset encoding");
5568 }
5569}
5570
5571/* --------------------------------------------------------------------------
5572 * ## Key API for Hash type
5573 *
5574 * See also RM_ValueLength(), which returns the number of fields in a hash.
5575 * -------------------------------------------------------------------------- */
5576
5577/* Set the field of the specified hash field to the specified value.
5578 * If the key is an empty key open for writing, it is created with an empty
5579 * hash value, in order to set the specified field.
5580 *
5581 * The function is variadic and the user must specify pairs of field
5582 * names and values, both as RedisModuleString pointers (unless the
5583 * CFIELD option is set, see later). At the end of the field/value-ptr pairs,
5584 * NULL must be specified as last argument to signal the end of the arguments
5585 * in the variadic function.
5586 *
5587 * Example to set the hash argv[1] to the value argv[2]:
5588 *
5589 * RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],argv[2],NULL);
5590 *
5591 * The function can also be used in order to delete fields (if they exist)
5592 * by setting them to the specified value of REDISMODULE_HASH_DELETE:
5593 *
5594 * RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],
5595 * REDISMODULE_HASH_DELETE,NULL);
5596 *
5597 * The behavior of the command changes with the specified flags, that can be
5598 * set to REDISMODULE_HASH_NONE if no special behavior is needed.
5599 *
5600 * REDISMODULE_HASH_NX: The operation is performed only if the field was not
5601 * already existing in the hash.
5602 * REDISMODULE_HASH_XX: The operation is performed only if the field was
5603 * already existing, so that a new value could be
5604 * associated to an existing filed, but no new fields
5605 * are created.
5606 * REDISMODULE_HASH_CFIELDS: The field names passed are null terminated C
5607 * strings instead of RedisModuleString objects.
5608 * REDISMODULE_HASH_COUNT_ALL: Include the number of inserted fields in the
5609 * returned number, in addition to the number of
5610 * updated and deleted fields. (Added in Redis
5611 * 6.2.)
5612 *
5613 * Unless NX is specified, the command overwrites the old field value with
5614 * the new one.
5615 *
5616 * When using REDISMODULE_HASH_CFIELDS, field names are reported using
5617 * normal C strings, so for example to delete the field "foo" the following
5618 * code can be used:
5619 *
5620 * RedisModule_HashSet(key,REDISMODULE_HASH_CFIELDS,"foo",
5621 * REDISMODULE_HASH_DELETE,NULL);
5622 *
5623 * Return value:
5624 *
5625 * The number of fields existing in the hash prior to the call, which have been
5626 * updated (its old value has been replaced by a new value) or deleted. If the
5627 * flag REDISMODULE_HASH_COUNT_ALL is set, inserted fields not previously
5628 * existing in the hash are also counted.
5629 *
5630 * If the return value is zero, `errno` is set (since Redis 6.2) as follows:
5631 *
5632 * - EINVAL if any unknown flags are set or if key is NULL.
5633 * - ENOTSUP if the key is associated with a non Hash value.
5634 * - EBADF if the key was not opened for writing.
5635 * - ENOENT if no fields were counted as described under Return value above.
5636 * This is not actually an error. The return value can be zero if all fields
5637 * were just created and the COUNT_ALL flag was unset, or if changes were held
5638 * back due to the NX and XX flags.
5639 *
5640 * NOTICE: The return value semantics of this function are very different
5641 * between Redis 6.2 and older versions. Modules that use it should determine
5642 * the Redis version and handle it accordingly.
5643 */
5644int RM_HashSet(RedisModuleKey *key, int flags, ...) {
5645 va_list ap;
5646 size_t oldsize = 0;
5647 if (!key || (flags & ~(REDISMODULE_HASH_NX |
5648 REDISMODULE_HASH_XX |
5649 REDISMODULE_HASH_CFIELDS |
5650 REDISMODULE_HASH_COUNT_ALL))) {
5651 errno = EINVAL;
5652 return 0;
5653 } else if (key->kv && key->kv->type != OBJ_HASH) {
5654 errno = ENOTSUP;
5655 return 0;
5656 } else if (!(key->mode & REDISMODULE_WRITE)) {
5657 errno = EBADF;
5658 return 0;
5659 }
5660 if (key->kv == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_HASH);
5661
5662 int64_t oldlen = (int64_t) getObjectLength(key->kv);
5663
5664 int count = 0;
5665 va_start(ap, flags);
5666 while(1) {
5667 RedisModuleString *field, *value;
5668 /* Get the field and value objects. */
5669 if (flags & REDISMODULE_HASH_CFIELDS) {
5670 char *cfield = va_arg(ap,char*);
5671 if (cfield == NULL) break;
5672 field = createRawStringObject(cfield,strlen(cfield));
5673 } else {
5674 field = va_arg(ap,RedisModuleString*);
5675 if (field == NULL) break;
5676 }
5677 value = va_arg(ap,RedisModuleString*);
5678
5679 /* Handle XX and NX */
5680 if (flags & (REDISMODULE_HASH_XX|REDISMODULE_HASH_NX)) {
5681 int hfeFlags = HFE_LAZY_AVOID_HASH_DEL | HFE_LAZY_NO_UPDATE_KEYSIZES;
5682
5683 /*
5684 * The hash might contain expired fields. If we lazily delete expired
5685 * field and the command was sent with XX flag, the operation could
5686 * fail and leave the hash empty, which the caller might not expect.
5687 * To prevent unexpected behavior, we avoid lazy deletion in this case
5688 * yet let the operation fail. Note that moduleDelKeyIfEmpty()
5689 * below won't delete the hash if it left with single expired key
5690 * because hash counts blindly expired fields as well.
5691 */
5692 if (flags & REDISMODULE_HASH_XX)
5693 hfeFlags |= HFE_LAZY_AVOID_FIELD_DEL;
5694
5695 int exists = hashTypeExists(key->db, key->kv, field->ptr, hfeFlags, NULL);
5696 if (((flags & REDISMODULE_HASH_XX) && !exists) ||
5697 ((flags & REDISMODULE_HASH_NX) && exists))
5698 {
5699 if (flags & REDISMODULE_HASH_CFIELDS) decrRefCount(field);
5700 continue;
5701 }
5702 }
5703
5704 /* Handle deletion if value is REDISMODULE_HASH_DELETE. */
5705 if (value == REDISMODULE_HASH_DELETE) {
5706 if (server.memory_tracking_per_slot)
5707 oldsize = hashTypeAllocSize(key->kv);
5708 count += hashTypeDelete(key->kv, field->ptr);
5709 if (server.memory_tracking_per_slot)
5710 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, hashTypeAllocSize(key->kv));
5711 if (flags & REDISMODULE_HASH_CFIELDS) decrRefCount(field);
5712 continue;
5713 }
5714
5715 int low_flags = HASH_SET_COPY;
5716 /* If CFIELDS is active, we can pass the ownership of the
5717 * SDS object to the low level function that sets the field
5718 * to avoid a useless copy. */
5719 if (flags & REDISMODULE_HASH_CFIELDS)
5720 low_flags |= HASH_SET_TAKE_FIELD;
5721
5722 robj *argv[2] = {field,value};
5723 if (server.memory_tracking_per_slot)
5724 oldsize = hashTypeAllocSize(key->kv);
5725 hashTypeTryConversion(key->db,key->kv,argv,0,1);
5726 int updated = hashTypeSet(key->db, key->kv, field->ptr, value->ptr, low_flags);
5727 if (server.memory_tracking_per_slot)
5728 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, hashTypeAllocSize(key->kv));
5729 count += (flags & REDISMODULE_HASH_COUNT_ALL) ? 1 : updated;
5730
5731 /* If CFIELDS is active, SDS string ownership is now of hashTypeSet(),
5732 * however we still have to release the 'field' object shell. */
5733 if (flags & REDISMODULE_HASH_CFIELDS) {
5734 field->ptr = NULL; /* Prevent the SDS string from being freed. */
5735 decrRefCount(field);
5736 }
5737 }
5738 va_end(ap);
5739 updateKeysizesHist(key->db, getKeySlot(key->key->ptr), OBJ_HASH, oldlen,
5740 (int64_t) hashTypeLength(key->kv, 0));
5741
5742 moduleDelKeyIfEmpty(key);
5743 if (count == 0) errno = ENOENT;
5744 return count;
5745}
5746
5747/* Get fields from a hash value. This function is called using a variable
5748 * number of arguments, alternating a field name (as a RedisModuleString
5749 * pointer) with a pointer to a RedisModuleString pointer, that is set to the
5750 * value of the field if the field exists, or NULL if the field does not exist.
5751 * At the end of the field/value-ptr pairs, NULL must be specified as last
5752 * argument to signal the end of the arguments in the variadic function.
5753 *
5754 * This is an example usage:
5755 *
5756 * RedisModuleString *first, *second;
5757 * RedisModule_HashGet(mykey,REDISMODULE_HASH_NONE,argv[1],&first,
5758 * argv[2],&second,NULL);
5759 *
5760 * As with RedisModule_HashSet() the behavior of the command can be specified
5761 * passing flags different than REDISMODULE_HASH_NONE:
5762 *
5763 * REDISMODULE_HASH_CFIELDS: field names as null terminated C strings.
5764 *
5765 * REDISMODULE_HASH_EXISTS: instead of setting the value of the field
5766 * expecting a RedisModuleString pointer to pointer, the function just
5767 * reports if the field exists or not and expects an integer pointer
5768 * as the second element of each pair.
5769 *
5770 * REDISMODULE_HASH_EXPIRE_TIME: retrieves the expiration time of a field in the hash.
5771 * The function expects a `mstime_t` pointer as the second element of each pair.
5772 * If the field does not exist or has no expiration, the value is set to
5773 * `REDISMODULE_NO_EXPIRE`. This flag must not be used with `REDISMODULE_HASH_EXISTS`.
5774 *
5775 * Example of REDISMODULE_HASH_CFIELDS:
5776 *
5777 * RedisModuleString *username, *hashedpass;
5778 * RedisModule_HashGet(mykey,REDISMODULE_HASH_CFIELDS,"username",&username,"hp",&hashedpass, NULL);
5779 *
5780 * Example of REDISMODULE_HASH_EXISTS:
5781 *
5782 * int exists;
5783 * RedisModule_HashGet(mykey,REDISMODULE_HASH_EXISTS,"username",&exists,NULL);
5784 *
5785 * Example of REDISMODULE_HASH_EXPIRE_TIME:
5786 *
5787 * mstime_t hpExpireTime;
5788 * RedisModule_HashGet(mykey,REDISMODULE_HASH_EXPIRE_TIME,"hp",&hpExpireTime,NULL);
5789 *
5790 * The function returns REDISMODULE_OK on success and REDISMODULE_ERR if
5791 * the key is not a hash value.
5792 *
5793 * Memory management:
5794 *
5795 * The returned RedisModuleString objects should be released with
5796 * RedisModule_FreeString(), or by enabling automatic memory management.
5797 */
5798int RM_HashGet(RedisModuleKey *key, int flags, ...) {
5799 int hfeFlags = HFE_LAZY_AVOID_FIELD_DEL | HFE_LAZY_AVOID_HASH_DEL | HFE_LAZY_NO_UPDATE_KEYSIZES;
5800 va_list ap;
5801 if (key->kv && key->kv->type != OBJ_HASH) return REDISMODULE_ERR;
5802
5803 if (key->mode & REDISMODULE_OPEN_KEY_ACCESS_EXPIRED)
5804 hfeFlags = HFE_LAZY_ACCESS_EXPIRED; /* allow read also expired fields */
5805
5806 /* Verify flag HASH_EXISTS is not set together with HASH_EXPIRE_TIME */
5807 if ((flags & REDISMODULE_HASH_EXISTS) && (flags & REDISMODULE_HASH_EXPIRE_TIME))
5808 return REDISMODULE_ERR;
5809
5810 va_start(ap, flags);
5811 while(1) {
5812 RedisModuleString *field, **valueptr;
5813 int *existsptr;
5814 /* Get the field object and the value pointer to pointer. */
5815 if (flags & REDISMODULE_HASH_CFIELDS) {
5816 char *cfield = va_arg(ap,char*);
5817 if (cfield == NULL) break;
5818 field = createRawStringObject(cfield,strlen(cfield));
5819 } else {
5820 field = va_arg(ap,RedisModuleString*);
5821 if (field == NULL) break;
5822 }
5823
5824 /* Query the hash for existence or value object. */
5825 if (flags & REDISMODULE_HASH_EXISTS) {
5826 existsptr = va_arg(ap,int*);
5827 if (key->kv) {
5828 *existsptr = hashTypeExists(key->db, key->kv, field->ptr, hfeFlags, NULL);
5829 } else {
5830 *existsptr = 0;
5831 }
5832 } else if (flags & REDISMODULE_HASH_EXPIRE_TIME) {
5833 mstime_t *expireptr = va_arg(ap,mstime_t*);
5834 *expireptr = REDISMODULE_NO_EXPIRE;
5835 if (key->kv) {
5836 uint64_t expireTime = 0;
5837 /* As an opt, avoid fetching value, only expire time */
5838 int res = hashTypeGetValueObject(key->db, key->kv, field->ptr,
5839 hfeFlags, NULL, &expireTime, NULL);
5840 /* If field has expiration time */
5841 if (res && expireTime != 0) *expireptr = expireTime;
5842 }
5843 } else {
5844 valueptr = va_arg(ap,RedisModuleString**);
5845 if (key->kv) {
5846 hashTypeGetValueObject(key->db, key->kv, field->ptr,
5847 hfeFlags, valueptr, NULL, NULL);
5848
5849 if (*valueptr) {
5850 robj *decoded = getDecodedObject(*valueptr);
5851 decrRefCount(*valueptr);
5852 *valueptr = decoded;
5853 }
5854 if (*valueptr)
5855 autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,*valueptr);
5856 } else {
5857 *valueptr = NULL;
5858 }
5859 }
5860
5861 /* Cleanup */
5862 if (flags & REDISMODULE_HASH_CFIELDS) decrRefCount(field);
5863 }
5864 va_end(ap);
5865 return REDISMODULE_OK;
5866}
5867
5868/**
5869 * Retrieves the minimum expiration time of fields in a hash.
5870 *
5871 * Return:
5872 * - The minimum expiration time (in milliseconds) of the hash fields if at
5873 * least one field has an expiration set.
5874 * - REDISMODULE_NO_EXPIRE if no fields have an expiration set or if the key
5875 * is not a hash.
5876 */
5877mstime_t RM_HashFieldMinExpire(RedisModuleKey *key) {
5878 if ((!key->kv) || (key->kv->type != OBJ_HASH))
5879 return REDISMODULE_NO_EXPIRE;
5880
5881 mstime_t min = hashTypeGetMinExpire(key->kv, 1);
5882 return (min == EB_EXPIRE_TIME_INVALID) ? REDISMODULE_NO_EXPIRE : min;
5883}
5884
5885/* --------------------------------------------------------------------------
5886 * ## Key API for Stream type
5887 *
5888 * For an introduction to streams, see https://redis.io/docs/latest/develop/data-types/streams/.
5889 *
5890 * The type RedisModuleStreamID, which is used in stream functions, is a struct
5891 * with two 64-bit fields and is defined as
5892 *
5893 * typedef struct RedisModuleStreamID {
5894 * uint64_t ms;
5895 * uint64_t seq;
5896 * } RedisModuleStreamID;
5897 *
5898 * See also RM_ValueLength(), which returns the length of a stream, and the
5899 * conversion functions RM_StringToStreamID() and RM_CreateStringFromStreamID().
5900 * -------------------------------------------------------------------------- */
5901
5902/* Adds an entry to a stream. Like XADD without trimming.
5903 *
5904 * - `key`: The key where the stream is (or will be) stored
5905 * - `flags`: A bit field of
5906 * - `REDISMODULE_STREAM_ADD_AUTOID`: Assign a stream ID automatically, like
5907 * `*` in the XADD command.
5908 * - `id`: If the `AUTOID` flag is set, this is where the assigned ID is
5909 * returned. Can be NULL if `AUTOID` is set, if you don't care to receive the
5910 * ID. If `AUTOID` is not set, this is the requested ID.
5911 * - `argv`: A pointer to an array of size `numfields * 2` containing the
5912 * fields and values.
5913 * - `numfields`: The number of field-value pairs in `argv`.
5914 *
5915 * Returns REDISMODULE_OK if an entry has been added. On failure,
5916 * REDISMODULE_ERR is returned and `errno` is set as follows:
5917 *
5918 * - EINVAL if called with invalid arguments
5919 * - ENOTSUP if the key refers to a value of a type other than stream
5920 * - EBADF if the key was not opened for writing
5921 * - EDOM if the given ID was 0-0 or not greater than all other IDs in the
5922 * stream (only if the AUTOID flag is unset)
5923 * - EFBIG if the stream has reached the last possible ID
5924 * - ERANGE if the elements are too large to be stored.
5925 */
5926int RM_StreamAdd(RedisModuleKey *key, int flags, RedisModuleStreamID *id, RedisModuleString **argv, long numfields) {
5927 /* Validate args */
5928 if (!key || (numfields != 0 && !argv) || /* invalid key or argv */
5929 (flags & ~(REDISMODULE_STREAM_ADD_AUTOID)) || /* invalid flags */
5930 (!(flags & REDISMODULE_STREAM_ADD_AUTOID) && !id)) { /* id required */
5931 errno = EINVAL;
5932 return REDISMODULE_ERR;
5933 } else if (key->kv && key->kv->type != OBJ_STREAM) {
5934 errno = ENOTSUP; /* wrong type */
5935 return REDISMODULE_ERR;
5936 } else if (!(key->mode & REDISMODULE_WRITE)) {
5937 errno = EBADF; /* key not open for writing */
5938 return REDISMODULE_ERR;
5939 } else if (!(flags & REDISMODULE_STREAM_ADD_AUTOID) &&
5940 id->ms == 0 && id->seq == 0) {
5941 errno = EDOM; /* ID out of range */
5942 return REDISMODULE_ERR;
5943 }
5944
5945 /* Create key if necessary */
5946 int created = 0;
5947 if (key->kv == NULL) {
5948 moduleCreateEmptyKey(key, REDISMODULE_KEYTYPE_STREAM);
5949 created = 1;
5950 }
5951
5952 stream *s = key->kv->ptr;
5953 if (s->last_id.ms == UINT64_MAX && s->last_id.seq == UINT64_MAX) {
5954 /* The stream has reached the last possible ID */
5955 errno = EFBIG;
5956 return REDISMODULE_ERR;
5957 }
5958
5959 streamID added_id;
5960 streamID use_id;
5961 streamID *use_id_ptr = NULL;
5962 if (!(flags & REDISMODULE_STREAM_ADD_AUTOID)) {
5963 use_id.ms = id->ms;
5964 use_id.seq = id->seq;
5965 use_id_ptr = &use_id;
5966 }
5967
5968 size_t oldsize = s->alloc_size;
5969 if (streamAppendItem(s,argv,numfields,&added_id,use_id_ptr,1) == C_ERR) {
5970 /* Either the ID not greater than all existing IDs in the stream, or
5971 * the elements are too large to be stored. either way, errno is already
5972 * set by streamAppendItem. */
5973 if (created) moduleDelKeyIfEmpty(key);
5974 return REDISMODULE_ERR;
5975 }
5976 if (server.memory_tracking_per_slot)
5977 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, s->alloc_size);
5978 /* Postponed signalKeyAsReady(). Done implicitly by moduleCreateEmptyKey()
5979 * so not needed if the stream has just been created. */
5980 if (!created) key->u.stream.signalready = 1;
5981
5982 if (id != NULL) {
5983 id->ms = added_id.ms;
5984 id->seq = added_id.seq;
5985 }
5986
5987 return REDISMODULE_OK;
5988}
5989
5990/* Deletes an entry from a stream.
5991 *
5992 * - `key`: A key opened for writing, with no stream iterator started.
5993 * - `id`: The stream ID of the entry to delete.
5994 *
5995 * Returns REDISMODULE_OK on success. On failure, REDISMODULE_ERR is returned
5996 * and `errno` is set as follows:
5997 *
5998 * - EINVAL if called with invalid arguments
5999 * - ENOTSUP if the key refers to a value of a type other than stream or if the
6000 * key is empty
6001 * - EBADF if the key was not opened for writing or if a stream iterator is
6002 * associated with the key
6003 * - ENOENT if no entry with the given stream ID exists
6004 *
6005 * See also RM_StreamIteratorDelete() for deleting the current entry while
6006 * iterating using a stream iterator.
6007 */
6008int RM_StreamDelete(RedisModuleKey *key, RedisModuleStreamID *id) {
6009 if (!key || !id) {
6010 errno = EINVAL;
6011 return REDISMODULE_ERR;
6012 } else if (!key->kv || key->kv->type != OBJ_STREAM) {
6013 errno = ENOTSUP; /* wrong type */
6014 return REDISMODULE_ERR;
6015 } else if (!(key->mode & REDISMODULE_WRITE) ||
6016 key->iter != NULL) {
6017 errno = EBADF; /* key not opened for writing or iterator started */
6018 return REDISMODULE_ERR;
6019 }
6020 stream *s = key->kv->ptr;
6021 size_t oldsize = s->alloc_size;
6022 streamID streamid = {id->ms, id->seq};
6023 if (streamDeleteItem(s, &streamid)) {
6024 if (server.memory_tracking_per_slot)
6025 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, s->alloc_size);
6026 return REDISMODULE_OK;
6027 } else {
6028 errno = ENOENT; /* no entry with this id */
6029 return REDISMODULE_ERR;
6030 }
6031}
6032
6033/* Sets up a stream iterator.
6034 *
6035 * - `key`: The stream key opened for reading using RedisModule_OpenKey().
6036 * - `flags`:
6037 * - `REDISMODULE_STREAM_ITERATOR_EXCLUSIVE`: Don't include `start` and `end`
6038 * in the iterated range.
6039 * - `REDISMODULE_STREAM_ITERATOR_REVERSE`: Iterate in reverse order, starting
6040 * from the `end` of the range.
6041 * - `start`: The lower bound of the range. Use NULL for the beginning of the
6042 * stream.
6043 * - `end`: The upper bound of the range. Use NULL for the end of the stream.
6044 *
6045 * Returns REDISMODULE_OK on success. On failure, REDISMODULE_ERR is returned
6046 * and `errno` is set as follows:
6047 *
6048 * - EINVAL if called with invalid arguments
6049 * - ENOTSUP if the key refers to a value of a type other than stream or if the
6050 * key is empty
6051 * - EBADF if the key was not opened for writing or if a stream iterator is
6052 * already associated with the key
6053 * - EDOM if `start` or `end` is outside the valid range
6054 *
6055 * Returns REDISMODULE_OK on success and REDISMODULE_ERR if the key doesn't
6056 * refer to a stream or if invalid arguments were given.
6057 *
6058 * The stream IDs are retrieved using RedisModule_StreamIteratorNextID() and
6059 * for each stream ID, the fields and values are retrieved using
6060 * RedisModule_StreamIteratorNextField(). The iterator is freed by calling
6061 * RedisModule_StreamIteratorStop().
6062 *
6063 * Example (error handling omitted):
6064 *
6065 * RedisModule_StreamIteratorStart(key, 0, startid_ptr, endid_ptr);
6066 * RedisModuleStreamID id;
6067 * long numfields;
6068 * while (RedisModule_StreamIteratorNextID(key, &id, &numfields) ==
6069 * REDISMODULE_OK) {
6070 * RedisModuleString *field, *value;
6071 * while (RedisModule_StreamIteratorNextField(key, &field, &value) ==
6072 * REDISMODULE_OK) {
6073 * //
6074 * // ... Do stuff ...
6075 * //
6076 * RedisModule_FreeString(ctx, field);
6077 * RedisModule_FreeString(ctx, value);
6078 * }
6079 * }
6080 * RedisModule_StreamIteratorStop(key);
6081 */
6082int RM_StreamIteratorStart(RedisModuleKey *key, int flags, RedisModuleStreamID *start, RedisModuleStreamID *end) {
6083 /* check args */
6084 if (!key ||
6085 (flags & ~(REDISMODULE_STREAM_ITERATOR_EXCLUSIVE |
6086 REDISMODULE_STREAM_ITERATOR_REVERSE))) {
6087 errno = EINVAL; /* key missing or invalid flags */
6088 return REDISMODULE_ERR;
6089 } else if (!key->kv || key->kv->type != OBJ_STREAM) {
6090 errno = ENOTSUP;
6091 return REDISMODULE_ERR; /* not a stream */
6092 } else if (key->iter) {
6093 errno = EBADF; /* iterator already started */
6094 return REDISMODULE_ERR;
6095 }
6096
6097 /* define range for streamIteratorStart() */
6098 streamID lower, upper;
6099 if (start) lower = (streamID){start->ms, start->seq};
6100 if (end) upper = (streamID){end->ms, end->seq};
6101 if (flags & REDISMODULE_STREAM_ITERATOR_EXCLUSIVE) {
6102 if ((start && streamIncrID(&lower) != C_OK) ||
6103 (end && streamDecrID(&upper) != C_OK)) {
6104 errno = EDOM; /* end is 0-0 or start is MAX-MAX? */
6105 return REDISMODULE_ERR;
6106 }
6107 }
6108
6109 /* create iterator */
6110 stream *s = key->kv->ptr;
6111 int rev = flags & REDISMODULE_STREAM_ITERATOR_REVERSE;
6112 streamIterator *si = zmalloc(sizeof(*si));
6113 streamIteratorStart(si, s, start ? &lower : NULL, end ? &upper : NULL, rev);
6114 key->iter = si;
6115 key->u.stream.currentid.ms = 0; /* for RM_StreamIteratorDelete() */
6116 key->u.stream.currentid.seq = 0;
6117 key->u.stream.numfieldsleft = 0; /* for RM_StreamIteratorNextField() */
6118 return REDISMODULE_OK;
6119}
6120
6121/* Stops a stream iterator created using RedisModule_StreamIteratorStart() and
6122 * reclaims its memory.
6123 *
6124 * Returns REDISMODULE_OK on success. On failure, REDISMODULE_ERR is returned
6125 * and `errno` is set as follows:
6126 *
6127 * - EINVAL if called with a NULL key
6128 * - ENOTSUP if the key refers to a value of a type other than stream or if the
6129 * key is empty
6130 * - EBADF if the key was not opened for writing or if no stream iterator is
6131 * associated with the key
6132 */
6133int RM_StreamIteratorStop(RedisModuleKey *key) {
6134 if (!key) {
6135 errno = EINVAL;
6136 return REDISMODULE_ERR;
6137 } else if (!key->kv || key->kv->type != OBJ_STREAM) {
6138 errno = ENOTSUP;
6139 return REDISMODULE_ERR;
6140 } else if (!key->iter) {
6141 errno = EBADF;
6142 return REDISMODULE_ERR;
6143 }
6144 streamIteratorStop(key->iter);
6145 zfree(key->iter);
6146 key->iter = NULL;
6147 return REDISMODULE_OK;
6148}
6149
6150/* Finds the next stream entry and returns its stream ID and the number of
6151 * fields.
6152 *
6153 * - `key`: Key for which a stream iterator has been started using
6154 * RedisModule_StreamIteratorStart().
6155 * - `id`: The stream ID returned. NULL if you don't care.
6156 * - `numfields`: The number of fields in the found stream entry. NULL if you
6157 * don't care.
6158 *
6159 * Returns REDISMODULE_OK and sets `*id` and `*numfields` if an entry was found.
6160 * On failure, REDISMODULE_ERR is returned and `errno` is set as follows:
6161 *
6162 * - EINVAL if called with a NULL key
6163 * - ENOTSUP if the key refers to a value of a type other than stream or if the
6164 * key is empty
6165 * - EBADF if no stream iterator is associated with the key
6166 * - ENOENT if there are no more entries in the range of the iterator
6167 *
6168 * In practice, if RM_StreamIteratorNextID() is called after a successful call
6169 * to RM_StreamIteratorStart() and with the same key, it is safe to assume that
6170 * an REDISMODULE_ERR return value means that there are no more entries.
6171 *
6172 * Use RedisModule_StreamIteratorNextField() to retrieve the fields and values.
6173 * See the example at RedisModule_StreamIteratorStart().
6174 */
6175int RM_StreamIteratorNextID(RedisModuleKey *key, RedisModuleStreamID *id, long *numfields) {
6176 if (!key) {
6177 errno = EINVAL;
6178 return REDISMODULE_ERR;
6179 } else if (!key->kv || key->kv->type != OBJ_STREAM) {
6180 errno = ENOTSUP;
6181 return REDISMODULE_ERR;
6182 } else if (!key->iter) {
6183 errno = EBADF;
6184 return REDISMODULE_ERR;
6185 }
6186 streamIterator *si = key->iter;
6187 int64_t *num_ptr = &key->u.stream.numfieldsleft;
6188 streamID *streamid_ptr = &key->u.stream.currentid;
6189 if (streamIteratorGetID(si, streamid_ptr, num_ptr)) {
6190 if (id) {
6191 id->ms = streamid_ptr->ms;
6192 id->seq = streamid_ptr->seq;
6193 }
6194 if (numfields) *numfields = *num_ptr;
6195 return REDISMODULE_OK;
6196 } else {
6197 /* No entry found. */
6198 key->u.stream.currentid.ms = 0; /* for RM_StreamIteratorDelete() */
6199 key->u.stream.currentid.seq = 0;
6200 key->u.stream.numfieldsleft = 0; /* for RM_StreamIteratorNextField() */
6201 errno = ENOENT;
6202 return REDISMODULE_ERR;
6203 }
6204}
6205
6206/* Retrieves the next field of the current stream ID and its corresponding value
6207 * in a stream iteration. This function should be called repeatedly after calling
6208 * RedisModule_StreamIteratorNextID() to fetch each field-value pair.
6209 *
6210 * - `key`: Key where a stream iterator has been started.
6211 * - `field_ptr`: This is where the field is returned.
6212 * - `value_ptr`: This is where the value is returned.
6213 *
6214 * Returns REDISMODULE_OK and points `*field_ptr` and `*value_ptr` to freshly
6215 * allocated RedisModuleString objects. The string objects are freed
6216 * automatically when the callback finishes if automatic memory is enabled. On
6217 * failure, REDISMODULE_ERR is returned and `errno` is set as follows:
6218 *
6219 * - EINVAL if called with a NULL key
6220 * - ENOTSUP if the key refers to a value of a type other than stream or if the
6221 * key is empty
6222 * - EBADF if no stream iterator is associated with the key
6223 * - ENOENT if there are no more fields in the current stream entry
6224 *
6225 * In practice, if RM_StreamIteratorNextField() is called after a successful
6226 * call to RM_StreamIteratorNextID() and with the same key, it is safe to assume
6227 * that an REDISMODULE_ERR return value means that there are no more fields.
6228 *
6229 * See the example at RedisModule_StreamIteratorStart().
6230 */
6231int RM_StreamIteratorNextField(RedisModuleKey *key, RedisModuleString **field_ptr, RedisModuleString **value_ptr) {
6232 if (!key) {
6233 errno = EINVAL;
6234 return REDISMODULE_ERR;
6235 } else if (!key->kv || key->kv->type != OBJ_STREAM) {
6236 errno = ENOTSUP;
6237 return REDISMODULE_ERR;
6238 } else if (!key->iter) {
6239 errno = EBADF;
6240 return REDISMODULE_ERR;
6241 } else if (key->u.stream.numfieldsleft <= 0) {
6242 errno = ENOENT;
6243 return REDISMODULE_ERR;
6244 }
6245 streamIterator *si = key->iter;
6246 unsigned char *field, *value;
6247 int64_t field_len, value_len;
6248 streamIteratorGetField(si, &field, &value, &field_len, &value_len);
6249 if (field_ptr) {
6250 *field_ptr = createRawStringObject((char *)field, field_len);
6251 autoMemoryAdd(key->ctx, REDISMODULE_AM_STRING, *field_ptr);
6252 }
6253 if (value_ptr) {
6254 *value_ptr = createRawStringObject((char *)value, value_len);
6255 autoMemoryAdd(key->ctx, REDISMODULE_AM_STRING, *value_ptr);
6256 }
6257 key->u.stream.numfieldsleft--;
6258 return REDISMODULE_OK;
6259}
6260
6261/* Deletes the current stream entry while iterating.
6262 *
6263 * This function can be called after RM_StreamIteratorNextID() or after any
6264 * calls to RM_StreamIteratorNextField().
6265 *
6266 * Returns REDISMODULE_OK on success. On failure, REDISMODULE_ERR is returned
6267 * and `errno` is set as follows:
6268 *
6269 * - EINVAL if key is NULL
6270 * - ENOTSUP if the key is empty or is of another type than stream
6271 * - EBADF if the key is not opened for writing, if no iterator has been started
6272 * - ENOENT if the iterator has no current stream entry
6273 */
6274int RM_StreamIteratorDelete(RedisModuleKey *key) {
6275 if (!key) {
6276 errno = EINVAL;
6277 return REDISMODULE_ERR;
6278 } else if (!key->kv || key->kv->type != OBJ_STREAM) {
6279 errno = ENOTSUP;
6280 return REDISMODULE_ERR;
6281 } else if (!(key->mode & REDISMODULE_WRITE) || !key->iter) {
6282 errno = EBADF;
6283 return REDISMODULE_ERR;
6284 } else if (key->u.stream.currentid.ms == 0 &&
6285 key->u.stream.currentid.seq == 0) {
6286 errno = ENOENT;
6287 return REDISMODULE_ERR;
6288 }
6289 streamIterator *si = key->iter;
6290 streamIteratorRemoveEntry(si, &key->u.stream.currentid);
6291 key->u.stream.currentid.ms = 0; /* Make sure repeated Delete() fails */
6292 key->u.stream.currentid.seq = 0;
6293 key->u.stream.numfieldsleft = 0; /* Make sure NextField() fails */
6294 return REDISMODULE_OK;
6295}
6296
6297/* Trim a stream by length, similar to XTRIM with MAXLEN.
6298 *
6299 * - `key`: Key opened for writing.
6300 * - `flags`: A bitfield of
6301 * - `REDISMODULE_STREAM_TRIM_APPROX`: Trim less if it improves performance,
6302 * like XTRIM with `~`.
6303 * - `length`: The number of stream entries to keep after trimming.
6304 *
6305 * Returns the number of entries deleted. On failure, a negative value is
6306 * returned and `errno` is set as follows:
6307 *
6308 * - EINVAL if called with invalid arguments
6309 * - ENOTSUP if the key is empty or of a type other than stream
6310 * - EBADF if the key is not opened for writing
6311 */
6312long long RM_StreamTrimByLength(RedisModuleKey *key, int flags, long long length) {
6313 if (!key || (flags & ~(REDISMODULE_STREAM_TRIM_APPROX)) || length < 0) {
6314 errno = EINVAL;
6315 return -1;
6316 } else if (!key->kv || key->kv->type != OBJ_STREAM) {
6317 errno = ENOTSUP;
6318 return -1;
6319 } else if (!(key->mode & REDISMODULE_WRITE)) {
6320 errno = EBADF;
6321 return -1;
6322 }
6323 int approx = flags & REDISMODULE_STREAM_TRIM_APPROX ? 1 : 0;
6324 stream *s = key->kv->ptr;
6325 size_t oldsize = s->alloc_size;
6326 long long retval = streamTrimByLength(s, length, approx);
6327 if (server.memory_tracking_per_slot)
6328 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, s->alloc_size);
6329 return retval;
6330}
6331
6332/* Trim a stream by ID, similar to XTRIM with MINID.
6333 *
6334 * - `key`: Key opened for writing.
6335 * - `flags`: A bitfield of
6336 * - `REDISMODULE_STREAM_TRIM_APPROX`: Trim less if it improves performance,
6337 * like XTRIM with `~`.
6338 * - `id`: The smallest stream ID to keep after trimming.
6339 *
6340 * Returns the number of entries deleted. On failure, a negative value is
6341 * returned and `errno` is set as follows:
6342 *
6343 * - EINVAL if called with invalid arguments
6344 * - ENOTSUP if the key is empty or of a type other than stream
6345 * - EBADF if the key is not opened for writing
6346 */
6347long long RM_StreamTrimByID(RedisModuleKey *key, int flags, RedisModuleStreamID *id) {
6348 if (!key || (flags & ~(REDISMODULE_STREAM_TRIM_APPROX)) || !id) {
6349 errno = EINVAL;
6350 return -1;
6351 } else if (!key->kv || key->kv->type != OBJ_STREAM) {
6352 errno = ENOTSUP;
6353 return -1;
6354 } else if (!(key->mode & REDISMODULE_WRITE)) {
6355 errno = EBADF;
6356 return -1;
6357 }
6358 int approx = flags & REDISMODULE_STREAM_TRIM_APPROX ? 1 : 0;
6359 streamID minid = (streamID){id->ms, id->seq};
6360 stream *s = key->kv->ptr;
6361 size_t oldsize = s->alloc_size;
6362 long long retval = streamTrimByID(s, minid, approx);
6363 if (server.memory_tracking_per_slot)
6364 updateSlotAllocSize(key->db, getKeySlot(key->key->ptr), oldsize, s->alloc_size);
6365 return retval;
6366}
6367
6368/* --------------------------------------------------------------------------
6369 * ## Calling Redis commands from modules
6370 *
6371 * RM_Call() sends a command to Redis. The remaining functions handle the reply.
6372 * -------------------------------------------------------------------------- */
6373
6374
6375void moduleParseCallReply_Int(RedisModuleCallReply *reply);
6376void moduleParseCallReply_BulkString(RedisModuleCallReply *reply);
6377void moduleParseCallReply_SimpleString(RedisModuleCallReply *reply);
6378void moduleParseCallReply_Array(RedisModuleCallReply *reply);
6379
6380
6381
6382
6383/* Free a Call reply and all the nested replies it contains if it's an
6384 * array. */
6385void RM_FreeCallReply(RedisModuleCallReply *reply) {
6386 /* This is a wrapper for the recursive free reply function. This is needed
6387 * in order to have the first level function to return on nested replies,
6388 * but only if called by the module API. */
6389
6390 RedisModuleCtx *ctx = NULL;
6391 if(callReplyType(reply) == REDISMODULE_REPLY_PROMISE) {
6392 RedisModuleAsyncRMCallPromise *promise = callReplyGetPrivateData(reply);
6393 ctx = promise->ctx;
6394 freeRedisModuleAsyncRMCallPromise(promise);
6395 } else {
6396 ctx = callReplyGetPrivateData(reply);
6397 }
6398
6399 freeCallReply(reply);
6400 if (ctx) {
6401 autoMemoryFreed(ctx,REDISMODULE_AM_REPLY,reply);
6402 }
6403}
6404
6405/* Return the reply type as one of the following:
6406 *
6407 * - REDISMODULE_REPLY_UNKNOWN
6408 * - REDISMODULE_REPLY_STRING
6409 * - REDISMODULE_REPLY_ERROR
6410 * - REDISMODULE_REPLY_INTEGER
6411 * - REDISMODULE_REPLY_ARRAY
6412 * - REDISMODULE_REPLY_NULL
6413 * - REDISMODULE_REPLY_MAP
6414 * - REDISMODULE_REPLY_SET
6415 * - REDISMODULE_REPLY_BOOL
6416 * - REDISMODULE_REPLY_DOUBLE
6417 * - REDISMODULE_REPLY_BIG_NUMBER
6418 * - REDISMODULE_REPLY_VERBATIM_STRING
6419 * - REDISMODULE_REPLY_ATTRIBUTE
6420 * - REDISMODULE_REPLY_PROMISE */
6421int RM_CallReplyType(RedisModuleCallReply *reply) {
6422 return callReplyType(reply);
6423}
6424
6425/* Return the reply type length, where applicable. */
6426size_t RM_CallReplyLength(RedisModuleCallReply *reply) {
6427 return callReplyGetLen(reply);
6428}
6429
6430/* Return the 'idx'-th nested call reply element of an array reply, or NULL
6431 * if the reply type is wrong or the index is out of range. */
6432RedisModuleCallReply *RM_CallReplyArrayElement(RedisModuleCallReply *reply, size_t idx) {
6433 return callReplyGetArrayElement(reply, idx);
6434}
6435
6436/* Return the `long long` of an integer reply. */
6437long long RM_CallReplyInteger(RedisModuleCallReply *reply) {
6438 return callReplyGetLongLong(reply);
6439}
6440
6441/* Return the double value of a double reply. */
6442double RM_CallReplyDouble(RedisModuleCallReply *reply) {
6443 return callReplyGetDouble(reply);
6444}
6445
6446/* Return the big number value of a big number reply. */
6447const char *RM_CallReplyBigNumber(RedisModuleCallReply *reply, size_t *len) {
6448 return callReplyGetBigNumber(reply, len);
6449}
6450
6451/* Return the value of a verbatim string reply,
6452 * An optional output argument can be given to get verbatim reply format. */
6453const char *RM_CallReplyVerbatim(RedisModuleCallReply *reply, size_t *len, const char **format) {
6454 return callReplyGetVerbatim(reply, len, format);
6455}
6456
6457/* Return the Boolean value of a Boolean reply. */
6458int RM_CallReplyBool(RedisModuleCallReply *reply) {
6459 return callReplyGetBool(reply);
6460}
6461
6462/* Return the 'idx'-th nested call reply element of a set reply, or NULL
6463 * if the reply type is wrong or the index is out of range. */
6464RedisModuleCallReply *RM_CallReplySetElement(RedisModuleCallReply *reply, size_t idx) {
6465 return callReplyGetSetElement(reply, idx);
6466}
6467
6468/* Retrieve the 'idx'-th key and value of a map reply.
6469 *
6470 * Returns:
6471 * - REDISMODULE_OK on success.
6472 * - REDISMODULE_ERR if idx out of range or if the reply type is wrong.
6473 *
6474 * The `key` and `value` arguments are used to return by reference, and may be
6475 * NULL if not required. */
6476int RM_CallReplyMapElement(RedisModuleCallReply *reply, size_t idx, RedisModuleCallReply **key, RedisModuleCallReply **val) {
6477 if (callReplyGetMapElement(reply, idx, key, val) == C_OK){
6478 return REDISMODULE_OK;
6479 }
6480 return REDISMODULE_ERR;
6481}
6482
6483/* Return the attribute of the given reply, or NULL if no attribute exists. */
6484RedisModuleCallReply *RM_CallReplyAttribute(RedisModuleCallReply *reply) {
6485 return callReplyGetAttribute(reply);
6486}
6487
6488/* Retrieve the 'idx'-th key and value of an attribute reply.
6489 *
6490 * Returns:
6491 * - REDISMODULE_OK on success.
6492 * - REDISMODULE_ERR if idx out of range or if the reply type is wrong.
6493 *
6494 * The `key` and `value` arguments are used to return by reference, and may be
6495 * NULL if not required. */
6496int RM_CallReplyAttributeElement(RedisModuleCallReply *reply, size_t idx, RedisModuleCallReply **key, RedisModuleCallReply **val) {
6497 if (callReplyGetAttributeElement(reply, idx, key, val) == C_OK){
6498 return REDISMODULE_OK;
6499 }
6500 return REDISMODULE_ERR;
6501}
6502
6503/* Set unblock handler (callback and private data) on the given promise RedisModuleCallReply.
6504 * The given reply must be of promise type (REDISMODULE_REPLY_PROMISE). */
6505void RM_CallReplyPromiseSetUnblockHandler(RedisModuleCallReply *reply, RedisModuleOnUnblocked on_unblock, void *private_data) {
6506 RedisModuleAsyncRMCallPromise *promise = callReplyGetPrivateData(reply);
6507 promise->on_unblocked = on_unblock;
6508 promise->private_data = private_data;
6509}
6510
6511/* Abort the execution of a given promise RedisModuleCallReply.
6512 * return REDMODULE_OK in case the abort was done successfully and REDISMODULE_ERR
6513 * if its not possible to abort the execution (execution already finished).
6514 * In case the execution was aborted (REDMODULE_OK was returned), the private_data out parameter
6515 * will be set with the value of the private data that was given on 'RM_CallReplyPromiseSetUnblockHandler'
6516 * so the caller will be able to release the private data.
6517 *
6518 * If the execution was aborted successfully, it is promised that the unblock handler will not be called.
6519 * That said, it is possible that the abort operation will successes but the operation will still continue.
6520 * This can happened if, for example, a module implements some blocking command and does not respect the
6521 * disconnect callback. For pure Redis commands this can not happened.*/
6522int RM_CallReplyPromiseAbort(RedisModuleCallReply *reply, void **private_data) {
6523 RedisModuleAsyncRMCallPromise *promise = callReplyGetPrivateData(reply);
6524 if (!promise->c) return REDISMODULE_ERR; /* Promise can not be aborted, either already aborted or already finished. */
6525 if (!(promise->c->flags & CLIENT_BLOCKED)) return REDISMODULE_ERR; /* Client is not blocked anymore, can not abort it. */
6526
6527 /* Client is still blocked, remove it from any blocking state and release it. */
6528 if (private_data) *private_data = promise->private_data;
6529 promise->private_data = NULL;
6530 promise->on_unblocked = NULL;
6531 unblockClient(promise->c, 0);
6532 moduleReleaseTempClient(promise->c);
6533 return REDISMODULE_OK;
6534}
6535
6536/* Return the pointer and length of a string or error reply. */
6537const char *RM_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *len) {
6538 size_t private_len;
6539 if (!len) len = &private_len;
6540 return callReplyGetString(reply, len);
6541}
6542
6543/* Return a new string object from a call reply of type string, error or
6544 * integer. Otherwise (wrong reply type) return NULL. */
6545RedisModuleString *RM_CreateStringFromCallReply(RedisModuleCallReply *reply) {
6546 RedisModuleCtx* ctx = callReplyGetPrivateData(reply);
6547 size_t len;
6548 const char *str;
6549 switch(callReplyType(reply)) {
6550 case REDISMODULE_REPLY_STRING:
6551 case REDISMODULE_REPLY_ERROR:
6552 str = callReplyGetString(reply, &len);
6553 return RM_CreateString(ctx, str, len);
6554 case REDISMODULE_REPLY_INTEGER: {
6555 char buf[64];
6556 int len = ll2string(buf,sizeof(buf),callReplyGetLongLong(reply));
6557 return RM_CreateString(ctx ,buf,len);
6558 }
6559 default:
6560 return NULL;
6561 }
6562}
6563
6564/* Modifies the user that RM_Call will use (e.g. for ACL checks) */
6565void RM_SetContextUser(RedisModuleCtx *ctx, const RedisModuleUser *user) {
6566 ctx->user = user;
6567}
6568
6569/* Returns an array of robj pointers, by parsing the format specifier "fmt" as described for
6570 * the RM_Call(), RM_Replicate() and other module APIs. Populates *argcp with the number of
6571 * items (which equals to the length of the allocated argv).
6572 *
6573 * The integer pointed by 'flags' is populated with flags according
6574 * to special modifiers in "fmt".
6575 *
6576 * "!" -> REDISMODULE_ARGV_REPLICATE
6577 * "A" -> REDISMODULE_ARGV_NO_AOF
6578 * "R" -> REDISMODULE_ARGV_NO_REPLICAS
6579 * "3" -> REDISMODULE_ARGV_RESP_3
6580 * "0" -> REDISMODULE_ARGV_RESP_AUTO
6581 * "C" -> REDISMODULE_ARGV_RUN_AS_USER
6582 * "M" -> REDISMODULE_ARGV_RESPECT_DENY_OOM
6583 * "K" -> REDISMODULE_ARGV_ALLOW_BLOCK
6584 *
6585 * On error (format specifier error) NULL is returned and nothing is
6586 * allocated. On success the argument vector is returned. */
6587robj **moduleCreateArgvFromUserFormat(const char *cmdname, const char *fmt, int *argcp, int *flags, va_list ap) {
6588 int argc = 0, argv_size, j;
6589 robj **argv = NULL;
6590
6591 /* As a first guess to avoid useless reallocations, size argv to
6592 * hold one argument for each char specifier in 'fmt'. */
6593 argv_size = strlen(fmt)+1; /* +1 because of the command name. */
6594 argv = zrealloc(argv,sizeof(robj*)*argv_size);
6595
6596 /* Build the arguments vector based on the format specifier. */
6597 argv[0] = createStringObject(cmdname,strlen(cmdname));
6598 argc++;
6599
6600 /* Create the client and dispatch the command. */
6601 const char *p = fmt;
6602 while(*p) {
6603 if (*p == 'c') {
6604 char *cstr = va_arg(ap,char*);
6605 argv[argc++] = createStringObject(cstr,strlen(cstr));
6606 } else if (*p == 's') {
6607 robj *obj = va_arg(ap,void*);
6608 if (obj->refcount == OBJ_STATIC_REFCOUNT)
6609 obj = createStringObject(obj->ptr,sdslen(obj->ptr));
6610 else
6611 incrRefCount(obj);
6612 argv[argc++] = obj;
6613 } else if (*p == 'b') {
6614 char *buf = va_arg(ap,char*);
6615 size_t len = va_arg(ap,size_t);
6616 argv[argc++] = createStringObject(buf,len);
6617 } else if (*p == 'l') {
6618 long long ll = va_arg(ap,long long);
6619 argv[argc++] = createStringObjectFromLongLongWithSds(ll);
6620 } else if (*p == 'v') {
6621 /* A vector of strings */
6622 robj **v = va_arg(ap, void*);
6623 size_t vlen = va_arg(ap, size_t);
6624
6625 /* We need to grow argv to hold the vector's elements.
6626 * We resize by vector_len-1 elements, because we held
6627 * one element in argv for the vector already */
6628 argv_size += vlen-1;
6629 argv = zrealloc(argv,sizeof(robj*)*argv_size);
6630
6631 size_t i = 0;
6632 for (i = 0; i < vlen; i++) {
6633 incrRefCount(v[i]);
6634 argv[argc++] = v[i];
6635 }
6636 } else if (*p == '!') {
6637 if (flags) (*flags) |= REDISMODULE_ARGV_REPLICATE;
6638 } else if (*p == 'A') {
6639 if (flags) (*flags) |= REDISMODULE_ARGV_NO_AOF;
6640 } else if (*p == 'R') {
6641 if (flags) (*flags) |= REDISMODULE_ARGV_NO_REPLICAS;
6642 } else if (*p == '3') {
6643 if (flags) (*flags) |= REDISMODULE_ARGV_RESP_3;
6644 } else if (*p == '0') {
6645 if (flags) (*flags) |= REDISMODULE_ARGV_RESP_AUTO;
6646 } else if (*p == 'C') {
6647 if (flags) (*flags) |= REDISMODULE_ARGV_RUN_AS_USER;
6648 } else if (*p == 'S') {
6649 if (flags) (*flags) |= REDISMODULE_ARGV_SCRIPT_MODE;
6650 } else if (*p == 'W') {
6651 if (flags) (*flags) |= REDISMODULE_ARGV_NO_WRITES;
6652 } else if (*p == 'M') {
6653 if (flags) (*flags) |= REDISMODULE_ARGV_RESPECT_DENY_OOM;
6654 } else if (*p == 'E') {
6655 if (flags) (*flags) |= REDISMODULE_ARGV_CALL_REPLIES_AS_ERRORS;
6656 } else if (*p == 'D') {
6657 if (flags) (*flags) |= (REDISMODULE_ARGV_DRY_RUN | REDISMODULE_ARGV_CALL_REPLIES_AS_ERRORS);
6658 } else if (*p == 'K') {
6659 if (flags) (*flags) |= REDISMODULE_ARGV_ALLOW_BLOCK;
6660 } else {
6661 goto fmterr;
6662 }
6663 p++;
6664 }
6665 if (argcp) *argcp = argc;
6666 return argv;
6667
6668fmterr:
6669 for (j = 0; j < argc; j++)
6670 decrRefCount(argv[j]);
6671 zfree(argv);
6672 return NULL;
6673}
6674
6675/* Exported API to call any Redis command from modules.
6676 *
6677 * * **cmdname**: The Redis command to call.
6678 * * **fmt**: A format specifier string for the command's arguments. Each
6679 * of the arguments should be specified by a valid type specification. The
6680 * format specifier can also contain the modifiers `!`, `A`, `3` and `R` which
6681 * don't have a corresponding argument.
6682 *
6683 * * `b` -- The argument is a buffer and is immediately followed by another
6684 * argument that is the buffer's length.
6685 * * `c` -- The argument is a pointer to a plain C string (null-terminated).
6686 * * `l` -- The argument is a `long long` integer.
6687 * * `s` -- The argument is a RedisModuleString.
6688 * * `v` -- The argument(s) is a vector of RedisModuleString.
6689 * * `!` -- Sends the Redis command and its arguments to replicas and AOF.
6690 * * `A` -- Suppress AOF propagation, send only to replicas (requires `!`).
6691 * * `R` -- Suppress replicas propagation, send only to AOF (requires `!`).
6692 * * `3` -- Return a RESP3 reply. This will change the command reply.
6693 * e.g., HGETALL returns a map instead of a flat array.
6694 * * `0` -- Return the reply in auto mode, i.e. the reply format will be the
6695 * same as the client attached to the given RedisModuleCtx. This will
6696 * probably used when you want to pass the reply directly to the client.
6697 * * `C` -- Run a command as the user attached to the context.
6698 * User is either attached automatically via the client that directly
6699 * issued the command and created the context or via RM_SetContextUser.
6700 * If the context is not directly created by an issued command (such as a
6701 * background context and no user was set on it via RM_SetContextUser,
6702 * RM_Call will fail.
6703 * Checks if the command can be executed according to ACL rules and causes
6704 * the command to run as the determined user, so that any future user
6705 * dependent activity, such as ACL checks within scripts will proceed as
6706 * expected.
6707 * Otherwise, the command will run as the Redis unrestricted user.
6708 * Upon sending a command from an internal connection, this flag is
6709 * ignored and the command will run as the Redis unrestricted user.
6710 * * `S` -- Run the command in a script mode, this means that it will raise
6711 * an error if a command which are not allowed inside a script
6712 * (flagged with the `deny-script` flag) is invoked (like SHUTDOWN).
6713 * In addition, on script mode, write commands are not allowed if there are
6714 * not enough good replicas (as configured with `min-replicas-to-write`)
6715 * or when the server is unable to persist to the disk.
6716 * * `W` -- Do not allow to run any write command (flagged with the `write` flag).
6717 * * `M` -- Do not allow `deny-oom` flagged commands when over the memory limit.
6718 * * `E` -- Return error as RedisModuleCallReply. If there is an error before
6719 * invoking the command, the error is returned using errno mechanism.
6720 * This flag allows to get the error also as an error CallReply with
6721 * relevant error message.
6722 * * 'D' -- A "Dry Run" mode. Return before executing the underlying call().
6723 * If everything succeeded, it will return with a NULL, otherwise it will
6724 * return with a CallReply object denoting the error, as if it was called with
6725 * the 'E' code.
6726 * * 'K' -- Allow running blocking commands. If enabled and the command gets blocked, a
6727 * special REDISMODULE_REPLY_PROMISE will be returned. This reply type
6728 * indicates that the command was blocked and the reply will be given asynchronously.
6729 * The module can use this reply object to set a handler which will be called when
6730 * the command gets unblocked using RedisModule_CallReplyPromiseSetUnblockHandler.
6731 * The handler must be set immediately after the command invocation (without releasing
6732 * the Redis lock in between). If the handler is not set, the blocking command will
6733 * still continue its execution but the reply will be ignored (fire and forget),
6734 * notice that this is dangerous in case of role change, as explained below.
6735 * The module can use RedisModule_CallReplyPromiseAbort to abort the command invocation
6736 * if it was not yet finished (see RedisModule_CallReplyPromiseAbort documentation for more
6737 * details). It is also the module's responsibility to abort the execution on role change, either by using
6738 * server event (to get notified when the instance becomes a replica) or relying on the disconnect
6739 * callback of the original client. Failing to do so can result in a write operation on a replica.
6740 * Unlike other call replies, promise call reply **must** be freed while the Redis GIL is locked.
6741 * Notice that on unblocking, the only promise is that the unblock handler will be called,
6742 * If the blocking RM_Call caused the module to also block some real client (using RM_BlockClient),
6743 * it is the module responsibility to unblock this client on the unblock handler.
6744 * On the unblock handler it is only allowed to perform the following:
6745 * * Calling additional Redis commands using RM_Call
6746 * * Open keys using RM_OpenKey
6747 * * Replicate data to the replica or AOF
6748 *
6749 * Specifically, it is not allowed to call any Redis module API which are client related such as:
6750 * * RM_Reply* API's
6751 * * RM_BlockClient
6752 * * RM_GetCurrentUserName
6753 *
6754 * * **...**: The actual arguments to the Redis command.
6755 *
6756 * On success a RedisModuleCallReply object is returned, otherwise
6757 * NULL is returned and errno is set to the following values:
6758 *
6759 * * EBADF: wrong format specifier.
6760 * * EINVAL: wrong command arity.
6761 * * ENOENT: command does not exist.
6762 * * EPERM: operation in Cluster instance with key in non local slot.
6763 * * EROFS: operation in Cluster instance when a write command is sent
6764 * in a readonly state.
6765 * * ENETDOWN: operation in Cluster instance when cluster is down.
6766 * * ENOTSUP: No ACL user for the specified module context
6767 * * EACCES: Command cannot be executed, according to ACL rules
6768 * * ENOSPC: Write or deny-oom command is not allowed
6769 * * ESPIPE: Command not allowed on script mode
6770 *
6771 * Example code fragment:
6772 *
6773 * reply = RedisModule_Call(ctx,"INCRBY","sc",argv[1],"10");
6774 * if (RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_INTEGER) {
6775 * long long myval = RedisModule_CallReplyInteger(reply);
6776 * // Do something with myval.
6777 * }
6778 *
6779 * This API is documented here: https://redis.io/docs/latest/develop/reference/modules/
6780 */
6781RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
6782 client *c = NULL;
6783 robj **argv = NULL;
6784 int argc = 0, flags = 0;
6785 va_list ap;
6786 RedisModuleCallReply *reply = NULL;
6787 int replicate = 0; /* Replicate this command? */
6788 int error_as_call_replies = 0; /* return errors as RedisModuleCallReply object */
6789 uint64_t cmd_flags;
6790
6791 /* Handle arguments. */
6792 va_start(ap, fmt);
6793 argv = moduleCreateArgvFromUserFormat(cmdname,fmt,&argc,&flags,ap);
6794 replicate = flags & REDISMODULE_ARGV_REPLICATE;
6795 error_as_call_replies = flags & REDISMODULE_ARGV_CALL_REPLIES_AS_ERRORS;
6796 va_end(ap);
6797
6798 c = moduleAllocTempClient();
6799
6800 if (!(flags & REDISMODULE_ARGV_ALLOW_BLOCK)) {
6801 /* We do not want to allow block, the module do not expect it */
6802 c->flags |= CLIENT_DENY_BLOCKING;
6803 }
6804 c->db = ctx->client->db;
6805 c->argv = argv;
6806 /* We have to assign argv_len, which is equal to argc in that case (RM_Call)
6807 * because we may be calling a command that uses rewriteClientCommandArgument */
6808 c->argc = c->argv_len = argc;
6809 c->resp = 2;
6810 if (flags & REDISMODULE_ARGV_RESP_3) {
6811 c->resp = 3;
6812 } else if (flags & REDISMODULE_ARGV_RESP_AUTO) {
6813 /* Auto mode means to take the same protocol as the ctx client. */
6814 c->resp = ctx->client->resp;
6815 }
6816 if (ctx->module) ctx->module->in_call++;
6817
6818 /* Attach the user of the context or client.
6819 * Internal connections always run with the unrestricted user. */
6820 user *user = NULL;
6821 if ((flags & REDISMODULE_ARGV_RUN_AS_USER) &&
6822 !(ctx->client->flags & CLIENT_INTERNAL))
6823 {
6824 user = ctx->user ? ctx->user->user : ctx->client->user;
6825 if (!user) {
6826 errno = ENOTSUP;
6827 if (error_as_call_replies) {
6828 sds msg = sdsnew("cannot run as user, no user directly attached to context or context's client");
6829 reply = callReplyCreateError(msg, ctx);
6830 }
6831 goto cleanup;
6832 }
6833 c->user = user;
6834 }
6835
6836 /* We handle the above format error only when the client is setup so that
6837 * we can free it normally. */
6838 if (argv == NULL) {
6839 /* We do not return a call reply here this is an error that should only
6840 * be catch by the module indicating wrong fmt was given, the module should
6841 * handle this error and decide how to continue. It is not an error that
6842 * should be propagated to the user. */
6843 errno = EBADF;
6844 goto cleanup;
6845 }
6846
6847 /* Call command filters */
6848 moduleCallCommandFilters(c);
6849
6850 /* Lookup command now, after filters had a chance to make modifications
6851 * if necessary.
6852 */
6853 c->cmd = c->lastcmd = c->realcmd = lookupCommand(c->argv,c->argc);
6854
6855 /* We nullify the command if it is not supposed to be seen by the client,
6856 * such that it will be rejected like an unknown command. */
6857 if (c->cmd &&
6858 (c->cmd->flags & CMD_INTERNAL) &&
6859 (flags & REDISMODULE_ARGV_RUN_AS_USER) &&
6860 !((ctx->client->flags & CLIENT_INTERNAL) || mustObeyClient(ctx->client)))
6861 {
6862 c->cmd = c->lastcmd = c->realcmd = NULL;
6863 }
6864
6865 sds err;
6866 if (!commandCheckExistence(c, error_as_call_replies? &err : NULL)) {
6867 errno = ENOENT;
6868 if (error_as_call_replies)
6869 reply = callReplyCreateError(err, ctx);
6870 goto cleanup;
6871 }
6872 if (!commandCheckArity(c->cmd, c->argc, error_as_call_replies? &err : NULL)) {
6873 errno = EINVAL;
6874 if (error_as_call_replies)
6875 reply = callReplyCreateError(err, ctx);
6876 goto cleanup;
6877 }
6878
6879 cmd_flags = getCommandFlags(c);
6880
6881 if (flags & REDISMODULE_ARGV_SCRIPT_MODE) {
6882 /* Basically on script mode we want to only allow commands that can
6883 * be executed on scripts (CMD_NOSCRIPT is not set on the command flags) */
6884 if (cmd_flags & CMD_NOSCRIPT) {
6885 errno = ESPIPE;
6886 if (error_as_call_replies) {
6887 sds msg = sdscatfmt(sdsempty(), "command '%S' is not allowed on script mode", c->cmd->fullname);
6888 reply = callReplyCreateError(msg, ctx);
6889 }
6890 goto cleanup;
6891 }
6892 }
6893
6894 if (flags & REDISMODULE_ARGV_RESPECT_DENY_OOM && server.maxmemory) {
6895 if (cmd_flags & CMD_DENYOOM) {
6896 int oom_state;
6897 if (ctx->flags & REDISMODULE_CTX_THREAD_SAFE) {
6898 /* On background thread we can not count on server.pre_command_oom_state.
6899 * Because it is only set on the main thread, in such case we will check
6900 * the actual memory usage. */
6901 oom_state = (getMaxmemoryState(NULL,NULL,NULL,NULL) == C_ERR);
6902 } else {
6903 oom_state = server.pre_command_oom_state;
6904 }
6905 if (oom_state) {
6906 errno = ENOSPC;
6907 if (error_as_call_replies) {
6908 sds msg = sdsdup(shared.oomerr->ptr);
6909 reply = callReplyCreateError(msg, ctx);
6910 }
6911 goto cleanup;
6912 }
6913 }
6914 } else {
6915 /* if we aren't OOM checking in RM_Call, we want further executions from this client to also not fail on OOM */
6916 c->flags |= CLIENT_ALLOW_OOM;
6917 }
6918
6919 if (flags & REDISMODULE_ARGV_NO_WRITES) {
6920 if (cmd_flags & CMD_WRITE) {
6921 errno = ENOSPC;
6922 if (error_as_call_replies) {
6923 sds msg = sdscatfmt(sdsempty(), "Write command '%S' was "
6924 "called while write is not allowed.", c->cmd->fullname);
6925 reply = callReplyCreateError(msg, ctx);
6926 }
6927 goto cleanup;
6928 }
6929 }
6930
6931 /* Script mode tests */
6932 if (flags & REDISMODULE_ARGV_SCRIPT_MODE) {
6933 if (cmd_flags & CMD_WRITE) {
6934 /* on script mode, if a command is a write command,
6935 * We will not run it if we encounter disk error
6936 * or we do not have enough replicas */
6937
6938 if (!checkGoodReplicasStatus()) {
6939 errno = ESPIPE;
6940 if (error_as_call_replies) {
6941 sds msg = sdsdup(shared.noreplicaserr->ptr);
6942 reply = callReplyCreateError(msg, ctx);
6943 }
6944 goto cleanup;
6945 }
6946
6947 int deny_write_type = writeCommandsDeniedByDiskError();
6948 int obey_client = (server.current_client && mustObeyClient(server.current_client));
6949
6950 if (deny_write_type != DISK_ERROR_TYPE_NONE && !obey_client) {
6951 errno = ESPIPE;
6952 if (error_as_call_replies) {
6953 sds msg = writeCommandsGetDiskErrorMessage(deny_write_type);
6954 reply = callReplyCreateError(msg, ctx);
6955 }
6956 goto cleanup;
6957 }
6958
6959 if (server.masterhost && server.repl_slave_ro && !obey_client) {
6960 errno = ESPIPE;
6961 if (error_as_call_replies) {
6962 sds msg = sdsdup(shared.roslaveerr->ptr);
6963 reply = callReplyCreateError(msg, ctx);
6964 }
6965 goto cleanup;
6966 }
6967 }
6968
6969 if (server.masterhost && server.repl_state != REPL_STATE_CONNECTED &&
6970 server.repl_serve_stale_data == 0 && !(cmd_flags & CMD_STALE)) {
6971 errno = ESPIPE;
6972 if (error_as_call_replies) {
6973 sds msg = sdsdup(shared.masterdownerr->ptr);
6974 reply = callReplyCreateError(msg, ctx);
6975 }
6976 goto cleanup;
6977 }
6978 }
6979
6980 /* Check if the user can run this command according to the current
6981 * ACLs.
6982 *
6983 * If RM_SetContextUser has set a user, that user is used, otherwise
6984 * use the attached client's user. If there is no attached client user and no manually
6985 * set user, an error will be returned.
6986 * An internal command should only succeed for an internal connection, AOF,
6987 * and master commands. */
6988 if (flags & REDISMODULE_ARGV_RUN_AS_USER) {
6989 int acl_errpos;
6990 int acl_retval;
6991
6992 acl_retval = ACLCheckAllUserCommandPerm(user,c->cmd,c->argv,c->argc,NULL,&acl_errpos);
6993 if (acl_retval != ACL_OK) {
6994 sds object = (acl_retval == ACL_DENIED_CMD) ? sdsdup(c->cmd->fullname) : sdsdup(c->argv[acl_errpos]->ptr);
6995 addACLLogEntry(ctx->client, acl_retval, ACL_LOG_CTX_MODULE, -1, c->user->name, object);
6996 if (error_as_call_replies) {
6997 /* verbosity should be same as processCommand() in server.c */
6998 sds acl_msg = getAclErrorMessage(acl_retval, c->user, c->cmd, c->argv[acl_errpos]->ptr, 0);
6999 sds msg = sdscatfmt(sdsempty(), "-NOPERM %S\r\n", acl_msg);
7000 sdsfree(acl_msg);
7001 reply = callReplyCreateError(msg, ctx);
7002 }
7003 errno = EACCES;
7004 goto cleanup;
7005 }
7006 }
7007
7008 /* If this is a Redis Cluster node, we need to make sure the module is not
7009 * trying to access non-local keys, with the exception of commands
7010 * received from our master. */
7011 if (server.cluster_enabled && !mustObeyClient(ctx->client)) {
7012 int error_code;
7013 /* Duplicate relevant flags in the module client. */
7014 c->flags &= ~(CLIENT_READONLY|CLIENT_ASKING);
7015 c->flags |= ctx->client->flags & (CLIENT_READONLY|CLIENT_ASKING);
7016 const uint64_t cmd_flags = getCommandFlags(c);
7017 if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,NULL,0,cmd_flags,&error_code) !=
7018 getMyClusterNode())
7019 {
7020 sds msg = NULL;
7021 if (error_code == CLUSTER_REDIR_DOWN_RO_STATE) {
7022 if (error_as_call_replies) {
7023 msg = sdscatfmt(sdsempty(), "Can not execute a write command '%S' while the cluster is down and readonly", c->cmd->fullname);
7024 }
7025 errno = EROFS;
7026 } else if (error_code == CLUSTER_REDIR_DOWN_STATE) {
7027 if (error_as_call_replies) {
7028 msg = sdscatfmt(sdsempty(), "Can not execute a command '%S' while the cluster is down", c->cmd->fullname);
7029 }
7030 errno = ENETDOWN;
7031 } else {
7032 if (error_as_call_replies) {
7033 msg = sdsnew("Attempted to access a non local key in a cluster node");
7034 }
7035 errno = EPERM;
7036 }
7037 if (msg) {
7038 reply = callReplyCreateError(msg, ctx);
7039 }
7040 goto cleanup;
7041 }
7042 }
7043
7044 if (flags & REDISMODULE_ARGV_DRY_RUN) {
7045 goto cleanup;
7046 }
7047
7048 /* We need to use a global replication_allowed flag in order to prevent
7049 * replication of nested RM_Calls. Example:
7050 * 1. module1.foo does RM_Call of module2.bar without replication (i.e. no '!')
7051 * 2. module2.bar internally calls RM_Call of INCR with '!'
7052 * 3. at the end of module1.foo we call RM_ReplicateVerbatim
7053 * We want the replica/AOF to see only module1.foo and not the INCR from module2.bar */
7054 int prev_replication_allowed = server.replication_allowed;
7055 server.replication_allowed = replicate && server.replication_allowed;
7056
7057 /* Run the command */
7058 int call_flags = CMD_CALL_FROM_MODULE;
7059 if (replicate) {
7060 if (!(flags & REDISMODULE_ARGV_NO_AOF))
7061 call_flags |= CMD_CALL_PROPAGATE_AOF;
7062 if (!(flags & REDISMODULE_ARGV_NO_REPLICAS))
7063 call_flags |= CMD_CALL_PROPAGATE_REPL;
7064 }
7065 call(c,call_flags);
7066 server.replication_allowed = prev_replication_allowed;
7067
7068 if (c->flags & CLIENT_BLOCKED) {
7069 serverAssert(flags & REDISMODULE_ARGV_ALLOW_BLOCK);
7070 serverAssert(ctx->module);
7071 RedisModuleAsyncRMCallPromise *promise = zmalloc(sizeof(RedisModuleAsyncRMCallPromise));
7072 *promise = (RedisModuleAsyncRMCallPromise) {
7073 /* We start with ref_count value of 2 because this object is held
7074 * by the promise CallReply and the fake client that was used to execute the command. */
7075 .ref_count = 2,
7076 .module = ctx->module,
7077 .on_unblocked = NULL,
7078 .private_data = NULL,
7079 .c = c,
7080 .ctx = (ctx->flags & REDISMODULE_CTX_AUTO_MEMORY) ? ctx : NULL,
7081 };
7082 reply = callReplyCreatePromise(promise);
7083 c->bstate.async_rm_call_handle = promise;
7084 if (!(call_flags & CMD_CALL_PROPAGATE_AOF)) {
7085 /* No need for AOF propagation, set the relevant flags of the client */
7086 c->flags |= CLIENT_MODULE_PREVENT_AOF_PROP;
7087 }
7088 if (!(call_flags & CMD_CALL_PROPAGATE_REPL)) {
7089 /* No need for replication propagation, set the relevant flags of the client */
7090 c->flags |= CLIENT_MODULE_PREVENT_REPL_PROP;
7091 }
7092 c = NULL; /* Make sure not to free the client */
7093 } else {
7094 reply = moduleParseReply(c, (ctx->flags & REDISMODULE_CTX_AUTO_MEMORY) ? ctx : NULL);
7095 }
7096
7097cleanup:
7098 if (reply) autoMemoryAdd(ctx,REDISMODULE_AM_REPLY,reply);
7099 if (ctx->module) ctx->module->in_call--;
7100 if (c) moduleReleaseTempClient(c);
7101 return reply;
7102}
7103
7104/* Return a pointer, and a length, to the protocol returned by the command
7105 * that returned the reply object. */
7106const char *RM_CallReplyProto(RedisModuleCallReply *reply, size_t *len) {
7107 return callReplyGetProto(reply, len);
7108}
7109
7110/* --------------------------------------------------------------------------
7111 * ## Modules data types
7112 *
7113 * When String DMA or using existing data structures is not enough, it is
7114 * possible to create new data types from scratch and export them to
7115 * Redis. The module must provide a set of callbacks for handling the
7116 * new values exported (for example in order to provide RDB saving/loading,
7117 * AOF rewrite, and so forth). In this section we define this API.
7118 * -------------------------------------------------------------------------- */
7119
7120/* Turn a 9 chars name in the specified charset and a 10 bit encver into
7121 * a single 64 bit unsigned integer that represents this exact module name
7122 * and version. This final number is called a "type ID" and is used when
7123 * writing module exported values to RDB files, in order to re-associate the
7124 * value to the right module to load them during RDB loading.
7125 *
7126 * If the string is not of the right length or the charset is wrong, or
7127 * if encver is outside the unsigned 10 bit integer range, 0 is returned,
7128 * otherwise the function returns the right type ID.
7129 *
7130 * The resulting 64 bit integer is composed as follows:
7131 *
7132 * (high order bits) 6|6|6|6|6|6|6|6|6|10 (low order bits)
7133 *
7134 * The first 6 bits value is the first character, name[0], while the last
7135 * 6 bits value, immediately before the 10 bits integer, is name[8].
7136 * The last 10 bits are the encoding version.
7137 *
7138 * Note that a name and encver combo of "AAAAAAAAA" and 0, will produce
7139 * zero as return value, that is the same we use to signal errors, thus
7140 * this combination is invalid, and also useless since type names should
7141 * try to be vary to avoid collisions. */
7142
7143const char *ModuleTypeNameCharSet =
7144 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7145 "abcdefghijklmnopqrstuvwxyz"
7146 "0123456789-_";
7147
7148uint64_t moduleTypeEncodeId(const char *name, int encver) {
7149 /* We use 64 symbols so that we can map each character into 6 bits
7150 * of the final output. */
7151 const char *cset = ModuleTypeNameCharSet;
7152 if (strlen(name) != 9) return 0;
7153 if (encver < 0 || encver > 1023) return 0;
7154
7155 uint64_t id = 0;
7156 for (int j = 0; j < 9; j++) {
7157 char *p = strchr(cset,name[j]);
7158 if (!p) return 0;
7159 unsigned long pos = p-cset;
7160 id = (id << 6) | pos;
7161 }
7162 id = (id << 10) | encver;
7163 return id;
7164}
7165
7166/* Search, in the list of exported data types of all the modules registered,
7167 * a type with the same name as the one given. Returns the moduleType
7168 * structure pointer if such a module is found, or NULL otherwise. */
7169moduleType *moduleTypeLookupModuleByNameInternal(const char *name, int ignore_case) {
7170 dictIterator di;
7171 dictEntry *de;
7172
7173 dictInitIterator(&di, modules);
7174 while ((de = dictNext(&di)) != NULL) {
7175 struct RedisModule *module = dictGetVal(de);
7176 listIter li;
7177 listNode *ln;
7178
7179 listRewind(module->types,&li);
7180 while((ln = listNext(&li))) {
7181 moduleType *mt = ln->value;
7182 if ((!ignore_case && memcmp(name,mt->entity.name,sizeof(mt->entity.name)) == 0)
7183 || (ignore_case && !strcasecmp(name, mt->entity.name)))
7184 {
7185 dictResetIterator(&di);
7186 return mt;
7187 }
7188 }
7189 }
7190 dictResetIterator(&di);
7191 return NULL;
7192}
7193/* Search all registered modules by name, and name is case sensitive */
7194moduleType *moduleTypeLookupModuleByName(const char *name) {
7195 return moduleTypeLookupModuleByNameInternal(name, 0);
7196}
7197
7198/* Search all registered modules by name, but case insensitive */
7199moduleType *moduleTypeLookupModuleByNameIgnoreCase(const char *name) {
7200 return moduleTypeLookupModuleByNameInternal(name, 1);
7201}
7202
7203/* Lookup a module by ID, with caching. This function is used during RDB
7204 * loading. Modules exporting data types should never be able to unload, so
7205 * our cache does not need to expire. */
7206#define MODULE_LOOKUP_CACHE_SIZE 3
7207
7208moduleType *moduleTypeLookupModuleByID(uint64_t id) {
7209 static struct {
7210 uint64_t id;
7211 moduleType *mt;
7212 } cache[MODULE_LOOKUP_CACHE_SIZE];
7213
7214 /* Search in cache to start. */
7215 int j;
7216 for (j = 0; j < MODULE_LOOKUP_CACHE_SIZE && cache[j].mt != NULL; j++)
7217 if (cache[j].id == id) return cache[j].mt;
7218
7219 /* Slow module by module lookup. */
7220 moduleType *mt = NULL;
7221 dictIterator di;
7222 dictEntry *de;
7223
7224 dictInitIterator(&di, modules);
7225 while ((de = dictNext(&di)) != NULL && mt == NULL) {
7226 struct RedisModule *module = dictGetVal(de);
7227 listIter li;
7228 listNode *ln;
7229
7230 listRewind(module->types,&li);
7231 while((ln = listNext(&li))) {
7232 moduleType *this_mt = ln->value;
7233 /* Compare only the 54 bit module identifier and not the
7234 * encoding version. */
7235 if (this_mt->entity.id >> 10 == id >> 10) {
7236 mt = this_mt;
7237 break;
7238 }
7239 }
7240 }
7241 dictResetIterator(&di);
7242
7243 /* Add to cache if possible. */
7244 if (mt && j < MODULE_LOOKUP_CACHE_SIZE) {
7245 cache[j].id = id;
7246 cache[j].mt = mt;
7247 }
7248 return mt;
7249}
7250
7251/* Turn an (unresolved) module ID into a type name, to show the user an
7252 * error when RDB files contain module data we can't load.
7253 * The buffer pointed by 'name' must be 10 bytes at least. The function will
7254 * fill it with a null terminated module name. */
7255void moduleTypeNameByID(char *name, uint64_t moduleid) {
7256 const char *cset = ModuleTypeNameCharSet;
7257
7258 name[9] = '\0';
7259 char *p = name+8;
7260 moduleid >>= 10;
7261 for (int j = 0; j < 9; j++) {
7262 *p-- = cset[moduleid & 63];
7263 moduleid >>= 6;
7264 }
7265}
7266
7267/* Return the name of the module that owns the specified moduleType. */
7268const char *moduleTypeModuleName(moduleType *mt) {
7269 if (!mt || !mt->entity.module) return NULL;
7270 return mt->entity.module->name;
7271}
7272
7273/* Return the module name from a module command */
7274const char *moduleNameFromCommand(struct redisCommand *cmd) {
7275 serverAssert(cmd->proc == RedisModuleCommandDispatcher);
7276
7277 RedisModuleCommand *cp = cmd->module_cmd;
7278 return cp->module->name;
7279}
7280
7281/* Create a copy of a module type value using the copy callback. If failed
7282 * or not supported, produce an error reply and return NULL.
7283 */
7284robj *moduleTypeDupOrReply(client *c, robj *fromkey, robj *tokey, int todb, robj *value) {
7285 moduleValue *mv = value->ptr;
7286 moduleType *mt = mv->type;
7287 if (!mt->copy && !mt->copy2) {
7288 addReplyError(c, "not supported for this module key");
7289 return NULL;
7290 }
7291 void *newval = NULL;
7292 if (mt->copy2 != NULL) {
7293 RedisModuleKeyOptCtx ctx = {fromkey, tokey, c->db->id, todb};
7294 newval = mt->copy2(&ctx, mv->value);
7295 } else {
7296 newval = mt->copy(fromkey, tokey, mv->value);
7297 }
7298
7299 if (!newval) {
7300 addReplyError(c, "module key failed to copy");
7301 return NULL;
7302 }
7303 return createModuleObject(mt, newval);
7304}
7305
7306/* Register a new data type exported by the module. The parameters are the
7307 * following. Please for in depth documentation check the modules API
7308 * documentation, especially https://redis.io/docs/latest/develop/reference/modules/modules-native-types/.
7309 *
7310 * * **name**: A 9 characters data type name that MUST be unique in the Redis
7311 * Modules ecosystem. Be creative... and there will be no collisions. Use
7312 * the charset A-Z a-z 9-0, plus the two "-_" characters. A good
7313 * idea is to use, for example `<typename>-<vendor>`. For example
7314 * "tree-AntZ" may mean "Tree data structure by @antirez". To use both
7315 * lower case and upper case letters helps in order to prevent collisions.
7316 * * **encver**: Encoding version, which is, the version of the serialization
7317 * that a module used in order to persist data. As long as the "name"
7318 * matches, the RDB loading will be dispatched to the type callbacks
7319 * whatever 'encver' is used, however the module can understand if
7320 * the encoding it must load are of an older version of the module.
7321 * For example the module "tree-AntZ" initially used encver=0. Later
7322 * after an upgrade, it started to serialize data in a different format
7323 * and to register the type with encver=1. However this module may
7324 * still load old data produced by an older version if the rdb_load
7325 * callback is able to check the encver value and act accordingly.
7326 * The encver must be a positive value between 0 and 1023.
7327 *
7328 * * **typemethods_ptr** is a pointer to a RedisModuleTypeMethods structure
7329 * that should be populated with the methods callbacks and structure
7330 * version, like in the following example:
7331 *
7332 * RedisModuleTypeMethods tm = {
7333 * .version = REDISMODULE_TYPE_METHOD_VERSION,
7334 * .rdb_load = myType_RDBLoadCallBack,
7335 * .rdb_save = myType_RDBSaveCallBack,
7336 * .aof_rewrite = myType_AOFRewriteCallBack,
7337 * .free = myType_FreeCallBack,
7338 *
7339 * // Optional fields
7340 * .digest = myType_DigestCallBack,
7341 * .mem_usage = myType_MemUsageCallBack,
7342 * .aux_load = myType_AuxRDBLoadCallBack,
7343 * .aux_save = myType_AuxRDBSaveCallBack,
7344 * .free_effort = myType_FreeEffortCallBack,
7345 * .unlink = myType_UnlinkCallBack,
7346 * .copy = myType_CopyCallback,
7347 * .defrag = myType_DefragCallback
7348 *
7349 * // Enhanced optional fields
7350 * .mem_usage2 = myType_MemUsageCallBack2,
7351 * .free_effort2 = myType_FreeEffortCallBack2,
7352 * .unlink2 = myType_UnlinkCallBack2,
7353 * .copy2 = myType_CopyCallback2,
7354 * }
7355 *
7356 * * **rdb_load**: A callback function pointer that loads data from RDB files.
7357 * * **rdb_save**: A callback function pointer that saves data to RDB files.
7358 * * **aof_rewrite**: A callback function pointer that rewrites data as commands.
7359 * * **digest**: A callback function pointer that is used for `DEBUG DIGEST`.
7360 * * **free**: A callback function pointer that can free a type value.
7361 * * **aux_save**: A callback function pointer that saves out of keyspace data to RDB files.
7362 * 'when' argument is either REDISMODULE_AUX_BEFORE_RDB or REDISMODULE_AUX_AFTER_RDB.
7363 * * **aux_load**: A callback function pointer that loads out of keyspace data from RDB files.
7364 * Similar to aux_save, returns REDISMODULE_OK on success, and ERR otherwise.
7365 * * **free_effort**: A callback function pointer that used to determine whether the module's
7366 * memory needs to be lazy reclaimed. The module should return the complexity involved by
7367 * freeing the value. for example: how many pointers are gonna be freed. Note that if it
7368 * returns 0, we'll always do an async free.
7369 * * **unlink**: A callback function pointer that used to notifies the module that the key has
7370 * been removed from the DB by redis, and may soon be freed by a background thread. Note that
7371 * it won't be called on FLUSHALL/FLUSHDB (both sync and async), and the module can use the
7372 * RedisModuleEvent_FlushDB to hook into that.
7373 * * **copy**: A callback function pointer that is used to make a copy of the specified key.
7374 * The module is expected to perform a deep copy of the specified value and return it.
7375 * In addition, hints about the names of the source and destination keys is provided.
7376 * A NULL return value is considered an error and the copy operation fails.
7377 * Note: if the target key exists and is being overwritten, the copy callback will be
7378 * called first, followed by a free callback to the value that is being replaced.
7379 *
7380 * * **defrag**: A callback function pointer that is used to request the module to defrag
7381 * a key. The module should then iterate pointers and call the relevant RM_Defrag*()
7382 * functions to defragment pointers or complex types. The module should continue
7383 * iterating as long as RM_DefragShouldStop() returns a zero value, and return a
7384 * zero value if finished or non-zero value if more work is left to be done. If more work
7385 * needs to be done, RM_DefragCursorSet() and RM_DefragCursorGet() can be used to track
7386 * this work across different calls.
7387 * Normally, the defrag mechanism invokes the callback without a time limit, so
7388 * RM_DefragShouldStop() always returns zero. The "late defrag" mechanism which has
7389 * a time limit and provides cursor support is used only for keys that are determined
7390 * to have significant internal complexity. To determine this, the defrag mechanism
7391 * uses the free_effort callback and the 'active-defrag-max-scan-fields' config directive.
7392 * NOTE: The value is passed as a `void**` and the function is expected to update the
7393 * pointer if the top-level value pointer is defragmented and consequently changes.
7394 *
7395 * * **mem_usage2**: Similar to `mem_usage`, but provides the `RedisModuleKeyOptCtx` parameter
7396 * so that meta information such as key name and db id can be obtained, and
7397 * the `sample_size` for size estimation (see MEMORY USAGE command).
7398 * * **free_effort2**: Similar to `free_effort`, but provides the `RedisModuleKeyOptCtx` parameter
7399 * so that meta information such as key name and db id can be obtained.
7400 * * **unlink2**: Similar to `unlink`, but provides the `RedisModuleKeyOptCtx` parameter
7401 * so that meta information such as key name and db id can be obtained.
7402 * * **copy2**: Similar to `copy`, but provides the `RedisModuleKeyOptCtx` parameter
7403 * so that meta information such as key names and db ids can be obtained.
7404 * * **aux_save2**: Similar to `aux_save`, but with small semantic change, if the module
7405 * saves nothing on this callback then no data about this aux field will be written to the
7406 * RDB and it will be possible to load the RDB even if the module is not loaded.
7407 *
7408 * Note: the module name "AAAAAAAAA" is reserved and produces an error, it
7409 * happens to be pretty lame as well.
7410 *
7411 * If RedisModule_CreateDataType() is called outside of RedisModule_OnLoad() function,
7412 * there is already a module registering a type with the same name,
7413 * or if the module name or encver is invalid, NULL is returned.
7414 * Otherwise the new type is registered into Redis, and a reference of
7415 * type RedisModuleType is returned: the caller of the function should store
7416 * this reference into a global variable to make future use of it in the
7417 * modules type API, since a single module may register multiple types.
7418 * Example code fragment:
7419 *
7420 * static RedisModuleType *BalancedTreeType;
7421 *
7422 * int RedisModule_OnLoad(RedisModuleCtx *ctx) {
7423 * // some code here ...
7424 * BalancedTreeType = RM_CreateDataType(...);
7425 * }
7426 */
7427moduleType *RM_CreateDataType(RedisModuleCtx *ctx, const char *name, int encver, void *typemethods_ptr) {
7428 if (!ctx->module->onload)
7429 return NULL;
7430 uint64_t id = moduleTypeEncodeId(name,encver);
7431 if (id == 0) return NULL;
7432 if (moduleTypeLookupModuleByName(name) != NULL) return NULL;
7433
7434 long typemethods_version = ((long*)typemethods_ptr)[0];
7435 if (typemethods_version == 0) return NULL;
7436
7437 struct typemethods {
7438 uint64_t version;
7439 moduleTypeLoadFunc rdb_load;
7440 moduleTypeSaveFunc rdb_save;
7441 moduleTypeRewriteFunc aof_rewrite;
7442 moduleTypeMemUsageFunc mem_usage;
7443 moduleTypeDigestFunc digest;
7444 moduleTypeFreeFunc free;
7445 struct {
7446 moduleTypeAuxLoadFunc aux_load;
7447 moduleTypeAuxSaveFunc aux_save;
7448 int aux_save_triggers;
7449 } v2;
7450 struct {
7451 moduleTypeFreeEffortFunc free_effort;
7452 moduleTypeUnlinkFunc unlink;
7453 moduleTypeCopyFunc copy;
7454 moduleTypeDefragFunc defrag;
7455 } v3;
7456 struct {
7457 moduleTypeMemUsageFunc2 mem_usage2;
7458 moduleTypeFreeEffortFunc2 free_effort2;
7459 moduleTypeUnlinkFunc2 unlink2;
7460 moduleTypeCopyFunc2 copy2;
7461 } v4;
7462 struct {
7463 moduleTypeAuxSaveFunc aux_save2;
7464 } v5;
7465 } *tms = (struct typemethods*) typemethods_ptr;
7466
7467 moduleType *mt = zcalloc(sizeof(*mt));
7468 mt->entity.id = id;
7469 mt->entity.module = ctx->module;
7470 mt->rdb_load = tms->rdb_load;
7471 mt->rdb_save = tms->rdb_save;
7472 mt->aof_rewrite = tms->aof_rewrite;
7473 mt->mem_usage = tms->mem_usage;
7474 mt->digest = tms->digest;
7475 mt->free = tms->free;
7476 if (tms->version >= 2) {
7477 mt->aux_load = tms->v2.aux_load;
7478 mt->aux_save = tms->v2.aux_save;
7479 mt->aux_save_triggers = tms->v2.aux_save_triggers;
7480 }
7481 if (tms->version >= 3) {
7482 mt->free_effort = tms->v3.free_effort;
7483 mt->unlink = tms->v3.unlink;
7484 mt->copy = tms->v3.copy;
7485 mt->defrag = tms->v3.defrag;
7486 }
7487 if (tms->version >= 4) {
7488 mt->mem_usage2 = tms->v4.mem_usage2;
7489 mt->unlink2 = tms->v4.unlink2;
7490 mt->free_effort2 = tms->v4.free_effort2;
7491 mt->copy2 = tms->v4.copy2;
7492 }
7493 if (tms->version >= 5) {
7494 mt->aux_save2 = tms->v5.aux_save2;
7495 }
7496 memcpy(mt->entity.name,name,sizeof(mt->entity.name));
7497 listAddNodeTail(ctx->module->types,mt);
7498 return mt;
7499}
7500
7501/* If the key is open for writing, set the specified module type object
7502 * as the value of the key, deleting the old value if any.
7503 * On success REDISMODULE_OK is returned. If the key is not open for
7504 * writing or there is an active iterator, REDISMODULE_ERR is returned. */
7505int RM_ModuleTypeSetValue(RedisModuleKey *key, moduleType *mt, void *value) {
7506 if (!(key->mode & REDISMODULE_WRITE) || key->iter) return REDISMODULE_ERR;
7507 RM_DeleteKey(key);
7508 robj *o = createModuleObject(mt,value);
7509 setKey(key->ctx->client,key->db,key->key, &o,SETKEY_NO_SIGNAL);
7510 key->kv = o;
7511 return REDISMODULE_OK;
7512}
7513
7514/* Assuming RedisModule_KeyType() returned REDISMODULE_KEYTYPE_MODULE on
7515 * the key, returns the module type pointer of the value stored at key.
7516 *
7517 * If the key is NULL, is not associated with a module type, or is empty,
7518 * then NULL is returned instead. */
7519moduleType *RM_ModuleTypeGetType(RedisModuleKey *key) {
7520 if (key == NULL ||
7521 key->kv == NULL ||
7522 RM_KeyType(key) != REDISMODULE_KEYTYPE_MODULE) return NULL;
7523 moduleValue *mv = key->kv->ptr;
7524 return mv->type;
7525}
7526
7527/* Assuming RedisModule_KeyType() returned REDISMODULE_KEYTYPE_MODULE on
7528 * the key, returns the module type low-level value stored at key, as
7529 * it was set by the user via RedisModule_ModuleTypeSetValue().
7530 *
7531 * If the key is NULL, is not associated with a module type, or is empty,
7532 * then NULL is returned instead. */
7533void *RM_ModuleTypeGetValue(RedisModuleKey *key) {
7534 if (key == NULL ||
7535 key->kv == NULL ||
7536 RM_KeyType(key) != REDISMODULE_KEYTYPE_MODULE) return NULL;
7537 moduleValue *mv = key->kv->ptr;
7538 return mv->value;
7539}
7540
7541/* --------------------------------------------------------------------------
7542 * ## RDB loading and saving functions
7543 * -------------------------------------------------------------------------- */
7544
7545/* Called when there is a load error in the context of a module. On some
7546 * modules this cannot be recovered, but if the module declared capability
7547 * to handle errors, we'll raise a flag rather than exiting. */
7548void moduleRDBLoadError(RedisModuleIO *io) {
7549 if (io->entity->module->options & REDISMODULE_OPTIONS_HANDLE_IO_ERRORS) {
7550 io->error = 1;
7551 return;
7552 }
7553 serverPanic(
7554 "Error loading data from RDB (short read or EOF). "
7555 "Read performed by module '%s' about type '%s' "
7556 "after reading '%llu' bytes of a value "
7557 "for key named: '%s'.",
7558 io->entity->module->name,
7559 io->entity->name,
7560 (unsigned long long)io->bytes,
7561 io->key? (char*)io->key->ptr: "(null)");
7562}
7563
7564/* Returns 0 if there's at least one registered data type that did not declare
7565 * REDISMODULE_OPTIONS_HANDLE_IO_ERRORS, in which case diskless loading should
7566 * be avoided since it could cause data loss. */
7567int moduleAllDatatypesHandleErrors(void) {
7568 dictIterator di;
7569 dictEntry *de;
7570
7571 dictInitIterator(&di, modules);
7572 while ((de = dictNext(&di)) != NULL) {
7573 struct RedisModule *module = dictGetVal(de);
7574 if (listLength(module->types) &&
7575 !(module->options & REDISMODULE_OPTIONS_HANDLE_IO_ERRORS))
7576 {
7577 dictResetIterator(&di);
7578 return 0;
7579 }
7580 }
7581 dictResetIterator(&di);
7582 return 1;
7583}
7584
7585/* Returns 0 if module did not declare REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD, in which case
7586 * diskless async loading should be avoided because module doesn't know there can be traffic during
7587 * database full resynchronization. */
7588int moduleAllModulesHandleReplAsyncLoad(void) {
7589 dictIterator di;
7590 dictEntry *de;
7591
7592 dictInitIterator(&di, modules);
7593 while ((de = dictNext(&di)) != NULL) {
7594 struct RedisModule *module = dictGetVal(de);
7595 if (!(module->options & REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD)) {
7596 dictResetIterator(&di);
7597 return 0;
7598 }
7599 }
7600 dictResetIterator(&di);
7601 return 1;
7602}
7603
7604/* Returns true if any previous IO API failed.
7605 * for `Load*` APIs the REDISMODULE_OPTIONS_HANDLE_IO_ERRORS flag must be set with
7606 * RedisModule_SetModuleOptions first. */
7607int RM_IsIOError(RedisModuleIO *io) {
7608 return io->error;
7609}
7610
7611static int flushRedisModuleIOBuffer(RedisModuleIO *io) {
7612 if (!io->pre_flush_buffer) return 0;
7613
7614 /* We have data that must be flushed before saving the current data.
7615 * Lets flush it. */
7616 sds pre_flush_buffer = io->pre_flush_buffer;
7617 io->pre_flush_buffer = NULL;
7618 ssize_t retval = rdbWriteRaw(io->rio, pre_flush_buffer, sdslen(pre_flush_buffer));
7619 sdsfree(pre_flush_buffer);
7620 if (retval >= 0) io->bytes += retval;
7621 return retval;
7622}
7623
7624/* Save an unsigned 64 bit value into the RDB file. This function should only
7625 * be called in the context of the rdb_save method of modules implementing new
7626 * data types. */
7627void RM_SaveUnsigned(RedisModuleIO *io, uint64_t value) {
7628 if (io->error) return;
7629 if (flushRedisModuleIOBuffer(io) == -1) goto saveerr;
7630 /* Save opcode. */
7631 int retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_UINT);
7632 if (retval == -1) goto saveerr;
7633 io->bytes += retval;
7634 /* Save value. */
7635 retval = rdbSaveLen(io->rio, value);
7636 if (retval == -1) goto saveerr;
7637 io->bytes += retval;
7638 return;
7639
7640saveerr:
7641 io->error = 1;
7642}
7643
7644/* Load an unsigned 64 bit value from the RDB file. This function should only
7645 * be called in the context of the `rdb_load` method of modules implementing
7646 * new data types. */
7647uint64_t RM_LoadUnsigned(RedisModuleIO *io) {
7648 if (io->error) return 0;
7649 uint64_t opcode = rdbLoadLen(io->rio,NULL);
7650 if (opcode != RDB_MODULE_OPCODE_UINT) goto loaderr;
7651 uint64_t value;
7652 int retval = rdbLoadLenByRef(io->rio, NULL, &value);
7653 if (retval == -1) goto loaderr;
7654 return value;
7655
7656loaderr:
7657 moduleRDBLoadError(io);
7658 return 0;
7659}
7660
7661/* Like RedisModule_SaveUnsigned() but for signed 64 bit values. */
7662void RM_SaveSigned(RedisModuleIO *io, int64_t value) {
7663 union {uint64_t u; int64_t i;} conv;
7664 conv.i = value;
7665 RM_SaveUnsigned(io,conv.u);
7666}
7667
7668/* Like RedisModule_LoadUnsigned() but for signed 64 bit values. */
7669int64_t RM_LoadSigned(RedisModuleIO *io) {
7670 union {uint64_t u; int64_t i;} conv;
7671 conv.u = RM_LoadUnsigned(io);
7672 return conv.i;
7673}
7674
7675/* In the context of the rdb_save method of a module type, saves a
7676 * string into the RDB file taking as input a RedisModuleString.
7677 *
7678 * The string can be later loaded with RedisModule_LoadString() or
7679 * other Load family functions expecting a serialized string inside
7680 * the RDB file. */
7681void RM_SaveString(RedisModuleIO *io, RedisModuleString *s) {
7682 if (io->error) return;
7683 if (flushRedisModuleIOBuffer(io) == -1) goto saveerr;
7684 /* Save opcode. */
7685 ssize_t retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_STRING);
7686 if (retval == -1) goto saveerr;
7687 io->bytes += retval;
7688 /* Save value. */
7689 retval = rdbSaveStringObject(io->rio, s);
7690 if (retval == -1) goto saveerr;
7691 io->bytes += retval;
7692 return;
7693
7694saveerr:
7695 io->error = 1;
7696}
7697
7698/* Like RedisModule_SaveString() but takes a raw C pointer and length
7699 * as input. */
7700void RM_SaveStringBuffer(RedisModuleIO *io, const char *str, size_t len) {
7701 if (io->error) return;
7702 if (flushRedisModuleIOBuffer(io) == -1) goto saveerr;
7703 /* Save opcode. */
7704 ssize_t retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_STRING);
7705 if (retval == -1) goto saveerr;
7706 io->bytes += retval;
7707 /* Save value. */
7708 retval = rdbSaveRawString(io->rio, (unsigned char*)str,len);
7709 if (retval == -1) goto saveerr;
7710 io->bytes += retval;
7711 return;
7712
7713saveerr:
7714 io->error = 1;
7715}
7716
7717/* Implements RM_LoadString() and RM_LoadStringBuffer() */
7718void *moduleLoadString(RedisModuleIO *io, int plain, size_t *lenptr) {
7719 if (io->error) return NULL;
7720 uint64_t opcode = rdbLoadLen(io->rio,NULL);
7721 if (opcode != RDB_MODULE_OPCODE_STRING) goto loaderr;
7722 void *s = rdbGenericLoadStringObject(io->rio,
7723 plain ? RDB_LOAD_PLAIN : RDB_LOAD_NONE, lenptr);
7724 if (s == NULL) goto loaderr;
7725 return s;
7726
7727loaderr:
7728 moduleRDBLoadError(io);
7729 return NULL;
7730}
7731
7732/* In the context of the rdb_load method of a module data type, loads a string
7733 * from the RDB file, that was previously saved with RedisModule_SaveString()
7734 * functions family.
7735 *
7736 * The returned string is a newly allocated RedisModuleString object, and
7737 * the user should at some point free it with a call to RedisModule_FreeString().
7738 *
7739 * If the data structure does not store strings as RedisModuleString objects,
7740 * the similar function RedisModule_LoadStringBuffer() could be used instead. */
7741RedisModuleString *RM_LoadString(RedisModuleIO *io) {
7742 return moduleLoadString(io,0,NULL);
7743}
7744
7745/* Like RedisModule_LoadString() but returns a heap allocated string that
7746 * was allocated with RedisModule_Alloc(), and can be resized or freed with
7747 * RedisModule_Realloc() or RedisModule_Free().
7748 *
7749 * The size of the string is stored at '*lenptr' if not NULL.
7750 * The returned string is not automatically NULL terminated, it is loaded
7751 * exactly as it was stored inside the RDB file. */
7752char *RM_LoadStringBuffer(RedisModuleIO *io, size_t *lenptr) {
7753 return moduleLoadString(io,1,lenptr);
7754}
7755
7756/* In the context of the rdb_save method of a module data type, saves a double
7757 * value to the RDB file. The double can be a valid number, a NaN or infinity.
7758 * It is possible to load back the value with RedisModule_LoadDouble(). */
7759void RM_SaveDouble(RedisModuleIO *io, double value) {
7760 if (io->error) return;
7761 if (flushRedisModuleIOBuffer(io) == -1) goto saveerr;
7762 /* Save opcode. */
7763 int retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_DOUBLE);
7764 if (retval == -1) goto saveerr;
7765 io->bytes += retval;
7766 /* Save value. */
7767 retval = rdbSaveBinaryDoubleValue(io->rio, value);
7768 if (retval == -1) goto saveerr;
7769 io->bytes += retval;
7770 return;
7771
7772saveerr:
7773 io->error = 1;
7774}
7775
7776/* In the context of the rdb_save method of a module data type, loads back the
7777 * double value saved by RedisModule_SaveDouble(). */
7778double RM_LoadDouble(RedisModuleIO *io) {
7779 if (io->error) return 0;
7780 uint64_t opcode = rdbLoadLen(io->rio,NULL);
7781 if (opcode != RDB_MODULE_OPCODE_DOUBLE) goto loaderr;
7782 double value;
7783 int retval = rdbLoadBinaryDoubleValue(io->rio, &value);
7784 if (retval == -1) goto loaderr;
7785 return value;
7786
7787loaderr:
7788 moduleRDBLoadError(io);
7789 return 0;
7790}
7791
7792/* In the context of the rdb_save method of a module data type, saves a float
7793 * value to the RDB file. The float can be a valid number, a NaN or infinity.
7794 * It is possible to load back the value with RedisModule_LoadFloat(). */
7795void RM_SaveFloat(RedisModuleIO *io, float value) {
7796 if (io->error) return;
7797 if (flushRedisModuleIOBuffer(io) == -1) goto saveerr;
7798 /* Save opcode. */
7799 int retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_FLOAT);
7800 if (retval == -1) goto saveerr;
7801 io->bytes += retval;
7802 /* Save value. */
7803 retval = rdbSaveBinaryFloatValue(io->rio, value);
7804 if (retval == -1) goto saveerr;
7805 io->bytes += retval;
7806 return;
7807
7808saveerr:
7809 io->error = 1;
7810}
7811
7812/* In the context of the rdb_save method of a module data type, loads back the
7813 * float value saved by RedisModule_SaveFloat(). */
7814float RM_LoadFloat(RedisModuleIO *io) {
7815 if (io->error) return 0;
7816 uint64_t opcode = rdbLoadLen(io->rio,NULL);
7817 if (opcode != RDB_MODULE_OPCODE_FLOAT) goto loaderr;
7818 float value;
7819 int retval = rdbLoadBinaryFloatValue(io->rio, &value);
7820 if (retval == -1) goto loaderr;
7821 return value;
7822
7823loaderr:
7824 moduleRDBLoadError(io);
7825 return 0;
7826}
7827
7828/* In the context of the rdb_save method of a module data type, saves a long double
7829 * value to the RDB file. The double can be a valid number, a NaN or infinity.
7830 * It is possible to load back the value with RedisModule_LoadLongDouble(). */
7831void RM_SaveLongDouble(RedisModuleIO *io, long double value) {
7832 if (io->error) return;
7833 char buf[MAX_LONG_DOUBLE_CHARS];
7834 /* Long double has different number of bits in different platforms, so we
7835 * save it as a string type. */
7836 size_t len = ld2string(buf,sizeof(buf),value,LD_STR_HEX);
7837 RM_SaveStringBuffer(io,buf,len);
7838}
7839
7840/* In the context of the rdb_save method of a module data type, loads back the
7841 * long double value saved by RedisModule_SaveLongDouble(). */
7842long double RM_LoadLongDouble(RedisModuleIO *io) {
7843 if (io->error) return 0;
7844 long double value;
7845 size_t len;
7846 char* str = RM_LoadStringBuffer(io,&len);
7847 if (!str) return 0;
7848 string2ld(str,len,&value);
7849 RM_Free(str);
7850 return value;
7851}
7852
7853/* Iterate over modules, and trigger rdb aux saving for the ones modules types
7854 * who asked for it. */
7855ssize_t rdbSaveModulesAux(rio *rdb, int when) {
7856 size_t total_written = 0;
7857 dictIterator di;
7858 dictEntry *de;
7859
7860 dictInitIterator(&di, modules);
7861 while ((de = dictNext(&di)) != NULL) {
7862 struct RedisModule *module = dictGetVal(de);
7863 listIter li;
7864 listNode *ln;
7865
7866 listRewind(module->types,&li);
7867 while((ln = listNext(&li))) {
7868 moduleType *mt = ln->value;
7869 if ((!mt->aux_save && !mt->aux_save2) || !(mt->aux_save_triggers & when))
7870 continue;
7871 ssize_t ret = rdbSaveSingleModuleAux(rdb, when, mt);
7872 if (ret==-1) {
7873 dictResetIterator(&di);
7874 return -1;
7875 }
7876 total_written += ret;
7877 }
7878 }
7879
7880 dictResetIterator(&di);
7881 return total_written;
7882}
7883
7884/* --------------------------------------------------------------------------
7885 * ## Key digest API (DEBUG DIGEST interface for modules types)
7886 * -------------------------------------------------------------------------- */
7887
7888/* Add a new element to the digest. This function can be called multiple times
7889 * one element after the other, for all the elements that constitute a given
7890 * data structure. The function call must be followed by the call to
7891 * `RedisModule_DigestEndSequence` eventually, when all the elements that are
7892 * always in a given order are added. See the Redis Modules data types
7893 * documentation for more info. However this is a quick example that uses Redis
7894 * data types as an example.
7895 *
7896 * To add a sequence of unordered elements (for example in the case of a Redis
7897 * Set), the pattern to use is:
7898 *
7899 * foreach element {
7900 * AddElement(element);
7901 * EndSequence();
7902 * }
7903 *
7904 * Because Sets are not ordered, so every element added has a position that
7905 * does not depend from the other. However if instead our elements are
7906 * ordered in pairs, like field-value pairs of a Hash, then one should
7907 * use:
7908 *
7909 * foreach key,value {
7910 * AddElement(key);
7911 * AddElement(value);
7912 * EndSequence();
7913 * }
7914 *
7915 * Because the key and value will be always in the above order, while instead
7916 * the single key-value pairs, can appear in any position into a Redis hash.
7917 *
7918 * A list of ordered elements would be implemented with:
7919 *
7920 * foreach element {
7921 * AddElement(element);
7922 * }
7923 * EndSequence();
7924 *
7925 */
7926void RM_DigestAddStringBuffer(RedisModuleDigest *md, const char *ele, size_t len) {
7927 mixDigest(md->o,ele,len);
7928}
7929
7930/* Like `RedisModule_DigestAddStringBuffer()` but takes a `long long` as input
7931 * that gets converted into a string before adding it to the digest. */
7932void RM_DigestAddLongLong(RedisModuleDigest *md, long long ll) {
7933 char buf[LONG_STR_SIZE];
7934 size_t len = ll2string(buf,sizeof(buf),ll);
7935 mixDigest(md->o,buf,len);
7936}
7937
7938/* See the documentation for `RedisModule_DigestAddElement()`. */
7939void RM_DigestEndSequence(RedisModuleDigest *md) {
7940 xorDigest(md->x,md->o,sizeof(md->o));
7941 memset(md->o,0,sizeof(md->o));
7942}
7943
7944/* Decode a serialized representation of a module data type 'mt', in a specific encoding version 'encver'
7945 * from string 'str' and return a newly allocated value, or NULL if decoding failed.
7946 *
7947 * This call basically reuses the 'rdb_load' callback which module data types
7948 * implement in order to allow a module to arbitrarily serialize/de-serialize
7949 * keys, similar to how the Redis 'DUMP' and 'RESTORE' commands are implemented.
7950 *
7951 * Modules should generally use the REDISMODULE_OPTIONS_HANDLE_IO_ERRORS flag and
7952 * make sure the de-serialization code properly checks and handles IO errors
7953 * (freeing allocated buffers and returning a NULL).
7954 *
7955 * If this is NOT done, Redis will handle corrupted (or just truncated) serialized
7956 * data by producing an error message and terminating the process.
7957 */
7958void *RM_LoadDataTypeFromStringEncver(const RedisModuleString *str, const moduleType *mt, int encver) {
7959 rio payload;
7960 RedisModuleIO io;
7961 void *ret;
7962
7963 rioInitWithBuffer(&payload, str->ptr);
7964 moduleType *mt_non_const = (moduleType *)mt; /*cast const away*/
7965 moduleInitIOContext(&io, &mt_non_const->entity, &payload, NULL, -1);
7966
7967 /* All RM_Save*() calls always write a version 2 compatible format, so we
7968 * need to make sure we read the same.
7969 */
7970 ret = mt->rdb_load(&io,encver);
7971 if (io.ctx) {
7972 moduleFreeContext(io.ctx);
7973 zfree(io.ctx);
7974 }
7975 return ret;
7976}
7977
7978/* Similar to RM_LoadDataTypeFromStringEncver, original version of the API, kept
7979 * for backward compatibility.
7980 */
7981void *RM_LoadDataTypeFromString(const RedisModuleString *str, const moduleType *mt) {
7982 return RM_LoadDataTypeFromStringEncver(str, mt, 0);
7983}
7984
7985/* Encode a module data type 'mt' value 'data' into serialized form, and return it
7986 * as a newly allocated RedisModuleString.
7987 *
7988 * This call basically reuses the 'rdb_save' callback which module data types
7989 * implement in order to allow a module to arbitrarily serialize/de-serialize
7990 * keys, similar to how the Redis 'DUMP' and 'RESTORE' commands are implemented.
7991 */
7992RedisModuleString *RM_SaveDataTypeToString(RedisModuleCtx *ctx, void *data, const moduleType *mt) {
7993 rio payload;
7994 RedisModuleIO io;
7995
7996 rioInitWithBuffer(&payload,sdsempty());
7997 moduleType *mt_non_const = (moduleType *)mt; /*cast const away*/
7998 moduleInitIOContext(&io, &mt_non_const->entity, &payload, NULL, -1);
7999 mt->rdb_save(&io,data);
8000 if (io.ctx) {
8001 moduleFreeContext(io.ctx);
8002 zfree(io.ctx);
8003 }
8004 if (io.error) {
8005 return NULL;
8006 } else {
8007 robj *str = createObject(OBJ_STRING,payload.io.buffer.ptr);
8008 if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_STRING,str);
8009 return str;
8010 }
8011}
8012
8013/* Returns the name of the key currently being processed. */
8014const RedisModuleString *RM_GetKeyNameFromDigest(RedisModuleDigest *dig) {
8015 return dig->key;
8016}
8017
8018/* Returns the database id of the key currently being processed. */
8019int RM_GetDbIdFromDigest(RedisModuleDigest *dig) {
8020 return dig->dbid;
8021}
8022/* --------------------------------------------------------------------------
8023 * ## AOF API for modules data types
8024 * -------------------------------------------------------------------------- */
8025
8026/* Emits a command into the AOF during the AOF rewriting process. This function
8027 * is only called in the context of the aof_rewrite method of data types exported
8028 * by a module. The command works exactly like RedisModule_Call() in the way
8029 * the parameters are passed, but it does not return anything as the error
8030 * handling is performed by Redis itself. */
8031void RM_EmitAOF(RedisModuleIO *io, const char *cmdname, const char *fmt, ...) {
8032 if (io->error) return;
8033 struct redisCommand *cmd;
8034 robj **argv = NULL;
8035 int argc = 0, flags = 0, j;
8036 va_list ap;
8037
8038 cmd = lookupCommandByCString((char*)cmdname);
8039 if (!cmd) {
8040 serverLog(LL_WARNING,
8041 "Fatal: AOF method for module data type '%s' tried to "
8042 "emit unknown command '%s'",
8043 io->entity->name, cmdname);
8044 io->error = 1;
8045 errno = EINVAL;
8046 return;
8047 }
8048
8049 /* Emit the arguments into the AOF in Redis protocol format. */
8050 va_start(ap, fmt);
8051 argv = moduleCreateArgvFromUserFormat(cmdname,fmt,&argc,&flags,ap);
8052 va_end(ap);
8053 if (argv == NULL) {
8054 serverLog(LL_WARNING,
8055 "Fatal: AOF method for module data type '%s' tried to "
8056 "call RedisModule_EmitAOF() with wrong format specifiers '%s'",
8057 io->entity->name, fmt);
8058 io->error = 1;
8059 errno = EINVAL;
8060 return;
8061 }
8062
8063 /* Bulk count. */
8064 if (!io->error && rioWriteBulkCount(io->rio,'*',argc) == 0)
8065 io->error = 1;
8066
8067 /* Arguments. */
8068 for (j = 0; j < argc; j++) {
8069 if (!io->error && rioWriteBulkObject(io->rio,argv[j]) == 0)
8070 io->error = 1;
8071 decrRefCount(argv[j]);
8072 }
8073 zfree(argv);
8074 return;
8075}
8076
8077/* --------------------------------------------------------------------------
8078 * ## IO context handling
8079 * -------------------------------------------------------------------------- */
8080
8081RedisModuleCtx *RM_GetContextFromIO(RedisModuleIO *io) {
8082 if (io->ctx) return io->ctx; /* Can't have more than one... */
8083 io->ctx = zmalloc(sizeof(RedisModuleCtx));
8084 moduleCreateContext(io->ctx, io->entity->module, REDISMODULE_CTX_NONE);
8085 return io->ctx;
8086}
8087
8088/* Returns the name of the key currently being processed.
8089 * There is no guarantee that the key name is always available, so this may return NULL.
8090 */
8091const RedisModuleString *RM_GetKeyNameFromIO(RedisModuleIO *io) {
8092 return io->key;
8093}
8094
8095/* Returns a RedisModuleString with the name of the key from RedisModuleKey. */
8096const RedisModuleString *RM_GetKeyNameFromModuleKey(RedisModuleKey *key) {
8097 return key ? key->key : NULL;
8098}
8099
8100/* Returns a database id of the key from RedisModuleKey. */
8101int RM_GetDbIdFromModuleKey(RedisModuleKey *key) {
8102 return key ? key->db->id : -1;
8103}
8104
8105/* Returns the database id of the key currently being processed.
8106 * There is no guarantee that this info is always available, so this may return -1.
8107 */
8108int RM_GetDbIdFromIO(RedisModuleIO *io) {
8109 return io->dbid;
8110}
8111
8112/* --------------------------------------------------------------------------
8113 * ## Logging
8114 * -------------------------------------------------------------------------- */
8115
8116/* This is the low level function implementing both:
8117 *
8118 * RM_Log()
8119 * RM_LogIOError()
8120 *
8121 */
8122void moduleLogRaw(RedisModule *module, const char *levelstr, const char *fmt, va_list ap) {
8123 char msg[LOG_MAX_LEN];
8124 size_t name_len;
8125 int level;
8126
8127 if (!strcasecmp(levelstr,"debug")) level = LL_DEBUG;
8128 else if (!strcasecmp(levelstr,"verbose")) level = LL_VERBOSE;
8129 else if (!strcasecmp(levelstr,"notice")) level = LL_NOTICE;
8130 else if (!strcasecmp(levelstr,"warning")) level = LL_WARNING;
8131 else level = LL_VERBOSE; /* Default. */
8132
8133 if (level < server.verbosity) return;
8134
8135 name_len = snprintf(msg, sizeof(msg),"<%s> ", module? module->name: "module");
8136 vsnprintf(msg + name_len, sizeof(msg) - name_len, fmt, ap);
8137 serverLogRaw(level,msg);
8138}
8139
8140/* Produces a log message to the standard Redis log, the format accepts
8141 * printf-alike specifiers, while level is a string describing the log
8142 * level to use when emitting the log, and must be one of the following:
8143 *
8144 * * "debug" (`REDISMODULE_LOGLEVEL_DEBUG`)
8145 * * "verbose" (`REDISMODULE_LOGLEVEL_VERBOSE`)
8146 * * "notice" (`REDISMODULE_LOGLEVEL_NOTICE`)
8147 * * "warning" (`REDISMODULE_LOGLEVEL_WARNING`)
8148 *
8149 * If the specified log level is invalid, verbose is used by default.
8150 * There is a fixed limit to the length of the log line this function is able
8151 * to emit, this limit is not specified but is guaranteed to be more than
8152 * a few lines of text.
8153 *
8154 * The ctx argument may be NULL if cannot be provided in the context of the
8155 * caller for instance threads or callbacks, in which case a generic "module"
8156 * will be used instead of the module name.
8157 */
8158void RM_Log(RedisModuleCtx *ctx, const char *levelstr, const char *fmt, ...) {
8159 va_list ap;
8160 va_start(ap, fmt);
8161 moduleLogRaw(ctx? ctx->module: NULL,levelstr,fmt,ap);
8162 va_end(ap);
8163}
8164
8165/* Log errors from RDB / AOF serialization callbacks.
8166 *
8167 * This function should be used when a callback is returning a critical
8168 * error to the caller since cannot load or save the data for some
8169 * critical reason. */
8170void RM_LogIOError(RedisModuleIO *io, const char *levelstr, const char *fmt, ...) {
8171 va_list ap;
8172 va_start(ap, fmt);
8173 moduleLogRaw(io->entity->module, levelstr, fmt, ap);
8174 va_end(ap);
8175}
8176
8177/* Redis-like assert function.
8178 *
8179 * The macro `RedisModule_Assert(expression)` is recommended, rather than
8180 * calling this function directly.
8181 *
8182 * A failed assertion will shut down the server and produce logging information
8183 * that looks identical to information generated by Redis itself.
8184 */
8185void RM__Assert(const char *estr, const char *file, int line) {
8186 _serverAssert(estr, file, line);
8187}
8188
8189/* Allows adding event to the latency monitor to be observed by the LATENCY
8190 * command. The call is skipped if the latency is smaller than the configured
8191 * latency-monitor-threshold. */
8192void RM_LatencyAddSample(const char *event, mstime_t latency) {
8193 if (latency >= server.latency_monitor_threshold)
8194 latencyAddSample(event, latency);
8195}
8196
8197/* --------------------------------------------------------------------------
8198 * ## Blocking clients from modules
8199 *
8200 * For a guide about blocking commands in modules, see
8201 * https://redis.io/docs/latest/develop/reference/modules/modules-blocking-ops/.
8202 * -------------------------------------------------------------------------- */
8203
8204/* Returns 1 if the client already in the moduleUnblocked list, 0 otherwise. */
8205int isModuleClientUnblocked(client *c) {
8206 RedisModuleBlockedClient *bc = c->bstate.module_blocked_handle;
8207
8208 return bc->unblocked == 1;
8209}
8210
8211/* This is called from blocked.c in order to unblock a client: may be called
8212 * for multiple reasons while the client is in the middle of being blocked
8213 * because the client is terminated, but is also called for cleanup when a
8214 * client is unblocked in a clean way after replaying.
8215 *
8216 * What we do here is just to set the client to NULL in the redis module
8217 * blocked client handle. This way if the client is terminated while there
8218 * is a pending threaded operation involving the blocked client, we'll know
8219 * that the client no longer exists and no reply callback should be called.
8220 *
8221 * The structure RedisModuleBlockedClient will be always deallocated when
8222 * running the list of clients blocked by a module that need to be unblocked. */
8223void unblockClientFromModule(client *c) {
8224 RedisModuleBlockedClient *bc = c->bstate.module_blocked_handle;
8225
8226 /* Call the disconnection callback if any. Note that
8227 * bc->disconnect_callback is set to NULL if the client gets disconnected
8228 * by the module itself or because of a timeout, so the callback will NOT
8229 * get called if this is not an actual disconnection event. */
8230 if (bc->disconnect_callback) {
8231 RedisModuleCtx ctx;
8232 moduleCreateContext(&ctx, bc->module, REDISMODULE_CTX_NONE);
8233 ctx.blocked_privdata = bc->privdata;
8234 ctx.client = bc->client;
8235 bc->disconnect_callback(&ctx,bc);
8236 moduleFreeContext(&ctx);
8237 }
8238
8239 /* If we made it here and client is still blocked it means that the command
8240 * timed-out, client was killed or disconnected and disconnect_callback was
8241 * not implemented (or it was, but RM_UnblockClient was not called from
8242 * within it, as it should).
8243 * We must call moduleUnblockClient in order to free privdata and
8244 * RedisModuleBlockedClient.
8245 *
8246 * Note that we only do that for clients that are blocked on keys, for which
8247 * the contract is that the module should not call RM_UnblockClient under
8248 * normal circumstances.
8249 * Clients implementing threads and working with private data should be
8250 * aware that calling RM_UnblockClient for every blocked client is their
8251 * responsibility, and if they fail to do so memory may leak. Ideally they
8252 * should implement the disconnect and timeout callbacks and call
8253 * RM_UnblockClient, but any other way is also acceptable. */
8254 if (bc->blocked_on_keys && !bc->unblocked)
8255 moduleUnblockClient(c);
8256
8257 bc->client = NULL;
8258}
8259
8260/* Block a client in the context of a module: this function implements both
8261 * RM_BlockClient() and RM_BlockClientOnKeys() depending on the fact the
8262 * keys are passed or not.
8263 *
8264 * When not blocking for keys, the keys, numkeys, and privdata parameters are
8265 * not needed. The privdata in that case must be NULL, since later is
8266 * RM_UnblockClient() that will provide some private data that the reply
8267 * callback will receive.
8268 *
8269 * Instead when blocking for keys, normally RM_UnblockClient() will not be
8270 * called (because the client will unblock when the key is modified), so
8271 * 'privdata' should be provided in that case, so that once the client is
8272 * unlocked and the reply callback is called, it will receive its associated
8273 * private data.
8274 *
8275 * Even when blocking on keys, RM_UnblockClient() can be called however, but
8276 * in that case the privdata argument is disregarded, because we pass the
8277 * reply callback the privdata that is set here while blocking.
8278 *
8279 */
8280RedisModuleBlockedClient *moduleBlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback,
8281 RedisModuleAuthCallback auth_reply_callback,
8282 RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*),
8283 long long timeout_ms, RedisModuleString **keys, int numkeys, void *privdata,
8284 int flags) {
8285 client *c = ctx->client;
8286 int islua = scriptIsRunning();
8287 int ismulti = server.in_exec;
8288
8289 c->bstate.module_blocked_handle = zcalloc(sizeof(RedisModuleBlockedClient));
8290 RedisModuleBlockedClient *bc = c->bstate.module_blocked_handle;
8291 ctx->module->blocked_clients++;
8292
8293 /* We need to handle the invalid operation of calling modules blocking
8294 * commands from Lua or MULTI. We actually create an already aborted
8295 * (client set to NULL) blocked client handle, and actually reply with
8296 * an error. */
8297 bc->client = (islua || ismulti) ? NULL : c;
8298 bc->module = ctx->module;
8299 bc->reply_callback = reply_callback;
8300 bc->auth_reply_cb = auth_reply_callback;
8301 bc->timeout_callback = timeout_callback;
8302 bc->disconnect_callback = NULL; /* Set by RM_SetDisconnectCallback() */
8303 bc->free_privdata = free_privdata;
8304 bc->privdata = privdata;
8305 bc->reply_client = moduleAllocTempClient();
8306 bc->thread_safe_ctx_client = moduleAllocTempClient();
8307 if (bc->client)
8308 bc->reply_client->resp = bc->client->resp;
8309 bc->dbid = c->db->id;
8310 bc->blocked_on_keys = keys != NULL;
8311 bc->unblocked = 0;
8312 bc->background_timer = 0;
8313 bc->background_duration = 0;
8314
8315 mstime_t timeout = 0;
8316 if (timeout_ms) {
8317 mstime_t now = mstime();
8318 if (timeout_ms > LLONG_MAX - now) {
8319 c->bstate.module_blocked_handle = NULL;
8320 addReplyError(c, "timeout is out of range"); /* 'timeout_ms+now' would overflow */
8321 return bc;
8322 }
8323 timeout = timeout_ms + now;
8324 }
8325
8326 if (islua || ismulti) {
8327 c->bstate.module_blocked_handle = NULL;
8328 addReplyError(c, islua ?
8329 "Blocking module command called from Lua script" :
8330 "Blocking module command called from transaction");
8331 } else if (ctx->flags & REDISMODULE_CTX_BLOCKED_REPLY) {
8332 c->bstate.module_blocked_handle = NULL;
8333 addReplyError(c, "Blocking module command called from a Reply callback context");
8334 } else if (!auth_reply_callback && clientHasModuleAuthInProgress(c)) {
8335 c->bstate.module_blocked_handle = NULL;
8336 addReplyError(c, "Clients undergoing module based authentication can only be blocked on auth");
8337 } else {
8338 if (keys) {
8339 blockForKeys(c,BLOCKED_MODULE,keys,numkeys,timeout,flags&REDISMODULE_BLOCK_UNBLOCK_DELETED);
8340 } else {
8341 c->bstate.timeout = timeout;
8342 blockClient(c,BLOCKED_MODULE);
8343 }
8344 }
8345 return bc;
8346}
8347
8348/* This API registers a callback to execute in addition to normal password based authentication.
8349 * Multiple callbacks can be registered across different modules. When a Module is unloaded, all the
8350 * auth callbacks registered by it are unregistered.
8351 * The callbacks are attempted (in the order of most recently registered first) when the AUTH/HELLO
8352 * (with AUTH field provided) commands are called.
8353 * The callbacks will be called with a module context along with a username and a password, and are
8354 * expected to take one of the following actions:
8355 * (1) Authenticate - Use the RM_AuthenticateClient* API and return REDISMODULE_AUTH_HANDLED.
8356 * This will immediately end the auth chain as successful and add the OK reply.
8357 * (2) Deny Authentication - Return REDISMODULE_AUTH_HANDLED without authenticating or blocking the
8358 * client. Optionally, `err` can be set to a custom error message and `err` will be automatically
8359 * freed by the server.
8360 * This will immediately end the auth chain as unsuccessful and add the ERR reply.
8361 * (3) Block a client on authentication - Use the RM_BlockClientOnAuth API and return
8362 * REDISMODULE_AUTH_HANDLED. Here, the client will be blocked until the RM_UnblockClient API is used
8363 * which will trigger the auth reply callback (provided through the RM_BlockClientOnAuth).
8364 * In this reply callback, the Module should authenticate, deny or skip handling authentication.
8365 * (4) Skip handling Authentication - Return REDISMODULE_AUTH_NOT_HANDLED without blocking the
8366 * client. This will allow the engine to attempt the next module auth callback.
8367 * If none of the callbacks authenticate or deny auth, then password based auth is attempted and
8368 * will authenticate or add failure logs and reply to the clients accordingly.
8369 *
8370 * Note: If a client is disconnected while it was in the middle of blocking module auth, that
8371 * occurrence of the AUTH or HELLO command will not be tracked in the INFO command stats.
8372 *
8373 * The following is an example of how non-blocking module based authentication can be used:
8374 *
8375 * int auth_cb(RedisModuleCtx *ctx, RedisModuleString *username, RedisModuleString *password, RedisModuleString **err) {
8376 * const char *user = RedisModule_StringPtrLen(username, NULL);
8377 * const char *pwd = RedisModule_StringPtrLen(password, NULL);
8378 * if (!strcmp(user,"foo") && !strcmp(pwd,"valid_password")) {
8379 * RedisModule_AuthenticateClientWithACLUser(ctx, "foo", 3, NULL, NULL, NULL);
8380 * return REDISMODULE_AUTH_HANDLED;
8381 * }
8382 *
8383 * else if (!strcmp(user,"foo") && !strcmp(pwd,"wrong_password")) {
8384 * RedisModuleString *log = RedisModule_CreateString(ctx, "Module Auth", 11);
8385 * RedisModule_ACLAddLogEntryByUserName(ctx, username, log, REDISMODULE_ACL_LOG_AUTH);
8386 * RedisModule_FreeString(ctx, log);
8387 * const char *err_msg = "Auth denied by Misc Module.";
8388 * *err = RedisModule_CreateString(ctx, err_msg, strlen(err_msg));
8389 * return REDISMODULE_AUTH_HANDLED;
8390 * }
8391 * return REDISMODULE_AUTH_NOT_HANDLED;
8392 * }
8393 *
8394 * int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
8395 * if (RedisModule_Init(ctx,"authmodule",1,REDISMODULE_APIVER_1)== REDISMODULE_ERR)
8396 * return REDISMODULE_ERR;
8397 * RedisModule_RegisterAuthCallback(ctx, auth_cb);
8398 * return REDISMODULE_OK;
8399 * }
8400 */
8401void RM_RegisterAuthCallback(RedisModuleCtx *ctx, RedisModuleAuthCallback cb) {
8402 RedisModuleAuthCtx *auth_ctx = zmalloc(sizeof(RedisModuleAuthCtx));
8403 auth_ctx->module = ctx->module;
8404 auth_ctx->auth_cb = cb;
8405 listAddNodeHead(moduleAuthCallbacks, auth_ctx);
8406}
8407
8408/* Helper function to invoke the free private data callback of a Module blocked client. */
8409void moduleInvokeFreePrivDataCallback(client *c, RedisModuleBlockedClient *bc) {
8410 if (bc->privdata && bc->free_privdata) {
8411 RedisModuleCtx ctx;
8412 int ctx_flags = c == NULL ? REDISMODULE_CTX_BLOCKED_DISCONNECTED : REDISMODULE_CTX_NONE;
8413 moduleCreateContext(&ctx, bc->module, ctx_flags);
8414 ctx.blocked_privdata = bc->privdata;
8415 ctx.client = bc->client;
8416 bc->free_privdata(&ctx,bc->privdata);
8417 moduleFreeContext(&ctx);
8418 }
8419}
8420
8421/* Unregisters all the module auth callbacks that have been registered by this Module. */
8422void moduleUnregisterAuthCBs(RedisModule *module) {
8423 listIter li;
8424 listNode *ln;
8425 listRewind(moduleAuthCallbacks, &li);
8426 while ((ln = listNext(&li))) {
8427 RedisModuleAuthCtx *ctx = listNodeValue(ln);
8428 if (ctx->module == module) {
8429 listDelNode(moduleAuthCallbacks, ln);
8430 zfree(ctx);
8431 }
8432 }
8433}
8434
8435/* Search for & attempt next module auth callback after skipping the ones already attempted.
8436 * Returns the result of the module auth callback. */
8437int attemptNextAuthCb(client *c, robj *username, robj *password, robj **err) {
8438 int handle_next_callback = c->module_auth_ctx == NULL;
8439 RedisModuleAuthCtx *cur_auth_ctx = NULL;
8440 listNode *ln;
8441 listIter li;
8442 listRewind(moduleAuthCallbacks, &li);
8443 int result = REDISMODULE_AUTH_NOT_HANDLED;
8444 while((ln = listNext(&li))) {
8445 cur_auth_ctx = listNodeValue(ln);
8446 /* Skip over the previously attempted auth contexts. */
8447 if (!handle_next_callback) {
8448 handle_next_callback = cur_auth_ctx == c->module_auth_ctx;
8449 continue;
8450 }
8451 /* Remove the module auth complete flag before we attempt the next cb. */
8452 c->flags &= ~CLIENT_MODULE_AUTH_HAS_RESULT;
8453 RedisModuleCtx ctx;
8454 moduleCreateContext(&ctx, cur_auth_ctx->module, REDISMODULE_CTX_NONE);
8455 ctx.client = c;
8456 *err = NULL;
8457 c->module_auth_ctx = cur_auth_ctx;
8458 result = cur_auth_ctx->auth_cb(&ctx, username, password, err);
8459 moduleFreeContext(&ctx);
8460 if (result == REDISMODULE_AUTH_HANDLED) break;
8461 /* If Auth was not handled (allowed/denied/blocked) by the Module, try the next auth cb. */
8462 }
8463 return result;
8464}
8465
8466/* Helper function to handle a reprocessed unblocked auth client.
8467 * Returns REDISMODULE_AUTH_NOT_HANDLED if the client was not reprocessed after a blocking module
8468 * auth operation.
8469 * Otherwise, we attempt the auth reply callback & the free priv data callback, update fields and
8470 * return the result of the reply callback. */
8471int attemptBlockedAuthReplyCallback(client *c, robj *username, robj *password, robj **err) {
8472 int result = REDISMODULE_AUTH_NOT_HANDLED;
8473 if (!c->module_blocked_client) return result;
8474 RedisModuleBlockedClient *bc = (RedisModuleBlockedClient *) c->module_blocked_client;
8475 bc->client = c;
8476 if (bc->auth_reply_cb) {
8477 RedisModuleCtx ctx;
8478 moduleCreateContext(&ctx, bc->module, REDISMODULE_CTX_BLOCKED_REPLY);
8479 ctx.blocked_privdata = bc->privdata;
8480 ctx.blocked_ready_key = NULL;
8481 ctx.client = bc->client;
8482 ctx.blocked_client = bc;
8483 result = bc->auth_reply_cb(&ctx, username, password, err);
8484 moduleFreeContext(&ctx);
8485 }
8486 moduleInvokeFreePrivDataCallback(c, bc);
8487 c->module_blocked_client = NULL;
8488 c->lastcmd->microseconds += bc->background_duration;
8489 bc->module->blocked_clients--;
8490 zfree(bc);
8491 return result;
8492}
8493
8494/* Helper function to attempt Module based authentication through module auth callbacks.
8495 * Here, the Module is expected to authenticate the client using the RedisModule APIs and to add ACL
8496 * logs in case of errors.
8497 * Returns one of the following codes:
8498 * AUTH_OK - Indicates that a module handled and authenticated the client.
8499 * AUTH_ERR - Indicates that a module handled and denied authentication for this client.
8500 * AUTH_NOT_HANDLED - Indicates that authentication was not handled by any Module and that
8501 * normal password based authentication can be attempted next.
8502 * AUTH_BLOCKED - Indicates module authentication is in progress through a blocking implementation.
8503 * In this case, authentication is handled here again after the client is unblocked / reprocessed. */
8504int checkModuleAuthentication(client *c, robj *username, robj *password, robj **err) {
8505 if (!listLength(moduleAuthCallbacks)) return AUTH_NOT_HANDLED;
8506 int result = attemptBlockedAuthReplyCallback(c, username, password, err);
8507 if (result == REDISMODULE_AUTH_NOT_HANDLED) {
8508 result = attemptNextAuthCb(c, username, password, err);
8509 }
8510 if (c->flags & CLIENT_BLOCKED) {
8511 /* Modules are expected to return REDISMODULE_AUTH_HANDLED when blocking clients. */
8512 serverAssert(result == REDISMODULE_AUTH_HANDLED);
8513 return AUTH_BLOCKED;
8514 }
8515 c->module_auth_ctx = NULL;
8516 if (result == REDISMODULE_AUTH_NOT_HANDLED) {
8517 c->flags &= ~CLIENT_MODULE_AUTH_HAS_RESULT;
8518 return AUTH_NOT_HANDLED;
8519 }
8520 if (c->flags & CLIENT_MODULE_AUTH_HAS_RESULT) {
8521 c->flags &= ~CLIENT_MODULE_AUTH_HAS_RESULT;
8522 if (c->authenticated) return AUTH_OK;
8523 }
8524 return AUTH_ERR;
8525}
8526
8527/* This function is called from module.c in order to check if a module
8528 * blocked for BLOCKED_MODULE and subtype 'on keys' (bc->blocked_on_keys true)
8529 * can really be unblocked, since the module was able to serve the client.
8530 * If the callback returns REDISMODULE_OK, then the client can be unblocked,
8531 * otherwise the client remains blocked and we'll retry again when one of
8532 * the keys it blocked for becomes "ready" again.
8533 * This function returns 1 if client was served (and should be unblocked) */
8534int moduleTryServeClientBlockedOnKey(client *c, robj *key) {
8535 int served = 0;
8536 RedisModuleBlockedClient *bc = c->bstate.module_blocked_handle;
8537
8538 /* Protect against re-processing: don't serve clients that are already
8539 * in the unblocking list for any reason (including RM_UnblockClient()
8540 * explicit call). See #6798. */
8541 if (bc->unblocked) return 0;
8542
8543 RedisModuleCtx ctx;
8544 moduleCreateContext(&ctx, bc->module, REDISMODULE_CTX_BLOCKED_REPLY);
8545 ctx.blocked_ready_key = key;
8546 ctx.blocked_privdata = bc->privdata;
8547 ctx.client = bc->client;
8548 ctx.blocked_client = bc;
8549 if (bc->reply_callback(&ctx,(void**)c->argv,c->argc) == REDISMODULE_OK)
8550 served = 1;
8551 moduleFreeContext(&ctx);
8552 return served;
8553}
8554
8555/* Block a client in the context of a blocking command, returning a handle
8556 * which will be used, later, in order to unblock the client with a call to
8557 * RedisModule_UnblockClient(). The arguments specify callback functions
8558 * and a timeout after which the client is unblocked.
8559 *
8560 * The callbacks are called in the following contexts:
8561 *
8562 * reply_callback: called after a successful RedisModule_UnblockClient()
8563 * call in order to reply to the client and unblock it.
8564 *
8565 * timeout_callback: called when the timeout is reached or if `CLIENT UNBLOCK`
8566 * is invoked, in order to send an error to the client.
8567 *
8568 * free_privdata: called in order to free the private data that is passed
8569 * by RedisModule_UnblockClient() call.
8570 *
8571 * Note: RedisModule_UnblockClient should be called for every blocked client,
8572 * even if client was killed, timed-out or disconnected. Failing to do so
8573 * will result in memory leaks.
8574 *
8575 * There are some cases where RedisModule_BlockClient() cannot be used:
8576 *
8577 * 1. If the client is a Lua script.
8578 * 2. If the client is executing a MULTI block.
8579 *
8580 * In these cases, a call to RedisModule_BlockClient() will **not** block the
8581 * client, but instead produce a specific error reply.
8582 *
8583 * A module that registers a timeout_callback function can also be unblocked
8584 * using the `CLIENT UNBLOCK` command, which will trigger the timeout callback.
8585 * If a callback function is not registered, then the blocked client will be
8586 * treated as if it is not in a blocked state and `CLIENT UNBLOCK` will return
8587 * a zero value.
8588 *
8589 * Measuring background time: By default the time spent in the blocked command
8590 * is not account for the total command duration. To include such time you should
8591 * use RM_BlockedClientMeasureTimeStart() and RM_BlockedClientMeasureTimeEnd() one,
8592 * or multiple times within the blocking command background work.
8593 */
8594RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback,
8595 RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*),
8596 long long timeout_ms) {
8597 return moduleBlockClient(ctx,reply_callback,NULL,timeout_callback,free_privdata,timeout_ms, NULL,0,NULL,0);
8598}
8599
8600/* Block the current client for module authentication in the background. If module auth is not in
8601 * progress on the client, the API returns NULL. Otherwise, the client is blocked and the RM_BlockedClient
8602 * is returned similar to the RM_BlockClient API.
8603 * Note: Only use this API from the context of a module auth callback. */
8604RedisModuleBlockedClient *RM_BlockClientOnAuth(RedisModuleCtx *ctx, RedisModuleAuthCallback reply_callback,
8605 void (*free_privdata)(RedisModuleCtx*,void*)) {
8606 if (!clientHasModuleAuthInProgress(ctx->client)) {
8607 addReplyError(ctx->client, "Module blocking client on auth when not currently undergoing module authentication");
8608 return NULL;
8609 }
8610 RedisModuleBlockedClient *bc = moduleBlockClient(ctx,NULL,reply_callback,NULL,free_privdata,0, NULL,0,NULL,0);
8611 if (ctx->client->flags & CLIENT_BLOCKED) {
8612 ctx->client->flags |= CLIENT_PENDING_COMMAND;
8613 }
8614 return bc;
8615}
8616
8617/* Get the private data that was previusely set on a blocked client */
8618void *RM_BlockClientGetPrivateData(RedisModuleBlockedClient *blocked_client) {
8619 return blocked_client->privdata;
8620}
8621
8622/* Set private data on a blocked client */
8623void RM_BlockClientSetPrivateData(RedisModuleBlockedClient *blocked_client, void *private_data) {
8624 blocked_client->privdata = private_data;
8625}
8626
8627/* This call is similar to RedisModule_BlockClient(), however in this case we
8628 * don't just block the client, but also ask Redis to unblock it automatically
8629 * once certain keys become "ready", that is, contain more data.
8630 *
8631 * Basically this is similar to what a typical Redis command usually does,
8632 * like BLPOP or BZPOPMAX: the client blocks if it cannot be served ASAP,
8633 * and later when the key receives new data (a list push for instance), the
8634 * client is unblocked and served.
8635 *
8636 * However in the case of this module API, when the client is unblocked?
8637 *
8638 * 1. If you block on a key of a type that has blocking operations associated,
8639 * like a list, a sorted set, a stream, and so forth, the client may be
8640 * unblocked once the relevant key is targeted by an operation that normally
8641 * unblocks the native blocking operations for that type. So if we block
8642 * on a list key, an RPUSH command may unblock our client and so forth.
8643 * 2. If you are implementing your native data type, or if you want to add new
8644 * unblocking conditions in addition to "1", you can call the modules API
8645 * RedisModule_SignalKeyAsReady().
8646 *
8647 * Anyway we can't be sure if the client should be unblocked just because the
8648 * key is signaled as ready: for instance a successive operation may change the
8649 * key, or a client in queue before this one can be served, modifying the key
8650 * as well and making it empty again. So when a client is blocked with
8651 * RedisModule_BlockClientOnKeys() the reply callback is not called after
8652 * RM_UnblockClient() is called, but every time a key is signaled as ready:
8653 * if the reply callback can serve the client, it returns REDISMODULE_OK
8654 * and the client is unblocked, otherwise it will return REDISMODULE_ERR
8655 * and we'll try again later.
8656 *
8657 * The reply callback can access the key that was signaled as ready by
8658 * calling the API RedisModule_GetBlockedClientReadyKey(), that returns
8659 * just the string name of the key as a RedisModuleString object.
8660 *
8661 * Thanks to this system we can setup complex blocking scenarios, like
8662 * unblocking a client only if a list contains at least 5 items or other
8663 * more fancy logics.
8664 *
8665 * Note that another difference with RedisModule_BlockClient(), is that here
8666 * we pass the private data directly when blocking the client: it will
8667 * be accessible later in the reply callback. Normally when blocking with
8668 * RedisModule_BlockClient() the private data to reply to the client is
8669 * passed when calling RedisModule_UnblockClient() but here the unblocking
8670 * is performed by Redis itself, so we need to have some private data before
8671 * hand. The private data is used to store any information about the specific
8672 * unblocking operation that you are implementing. Such information will be
8673 * freed using the free_privdata callback provided by the user.
8674 *
8675 * However the reply callback will be able to access the argument vector of
8676 * the command, so the private data is often not needed.
8677 *
8678 * Note: Under normal circumstances RedisModule_UnblockClient should not be
8679 * called for clients that are blocked on keys (Either the key will
8680 * become ready or a timeout will occur). If for some reason you do want
8681 * to call RedisModule_UnblockClient it is possible: Client will be
8682 * handled as if it were timed-out (You must implement the timeout
8683 * callback in that case).
8684 */
8685RedisModuleBlockedClient *RM_BlockClientOnKeys(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback,
8686 RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*),
8687 long long timeout_ms, RedisModuleString **keys, int numkeys, void *privdata) {
8688 return moduleBlockClient(ctx,reply_callback,NULL,timeout_callback,free_privdata,timeout_ms, keys,numkeys,privdata,0);
8689}
8690
8691/* Same as RedisModule_BlockClientOnKeys, but can take REDISMODULE_BLOCK_* flags
8692 * Can be either REDISMODULE_BLOCK_UNBLOCK_DEFAULT, which means default behavior (same
8693 * as calling RedisModule_BlockClientOnKeys)
8694 *
8695 * The flags is a bit mask of these:
8696 *
8697 * - `REDISMODULE_BLOCK_UNBLOCK_DELETED`: The clients should to be awakened in case any of `keys` are deleted.
8698 * Mostly useful for commands that require the key to exist (like XREADGROUP)
8699 */
8700RedisModuleBlockedClient *RM_BlockClientOnKeysWithFlags(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback,
8701 RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*),
8702 long long timeout_ms, RedisModuleString **keys, int numkeys, void *privdata,
8703 int flags) {
8704 return moduleBlockClient(ctx,reply_callback,NULL,timeout_callback,free_privdata,timeout_ms, keys,numkeys,privdata,flags);
8705}
8706
8707/* This function is used in order to potentially unblock a client blocked
8708 * on keys with RedisModule_BlockClientOnKeys(). When this function is called,
8709 * all the clients blocked for this key will get their reply_callback called. */
8710void RM_SignalKeyAsReady(RedisModuleCtx *ctx, RedisModuleString *key) {
8711 signalKeyAsReady(ctx->client->db, key, OBJ_MODULE);
8712}
8713
8714/* Implements RM_UnblockClient() and moduleUnblockClient(). */
8715int moduleUnblockClientByHandle(RedisModuleBlockedClient *bc, void *privdata) {
8716 pthread_mutex_lock(&moduleUnblockedClientsMutex);
8717 if (!bc->blocked_on_keys) bc->privdata = privdata;
8718 bc->unblocked = 1;
8719 if (listLength(moduleUnblockedClients) == 0) {
8720 if (write(server.module_pipe[1],"A",1) != 1) {
8721 /* Ignore the error, this is best-effort. */
8722 }
8723 }
8724 listAddNodeTail(moduleUnblockedClients,bc);
8725 pthread_mutex_unlock(&moduleUnblockedClientsMutex);
8726 return REDISMODULE_OK;
8727}
8728
8729/* This API is used by the Redis core to unblock a client that was blocked
8730 * by a module. */
8731void moduleUnblockClient(client *c) {
8732 RedisModuleBlockedClient *bc = c->bstate.module_blocked_handle;
8733 moduleUnblockClientByHandle(bc,NULL);
8734}
8735
8736/* Return true if the client 'c' was blocked by a module using
8737 * RM_BlockClientOnKeys(). */
8738int moduleClientIsBlockedOnKeys(client *c) {
8739 RedisModuleBlockedClient *bc = c->bstate.module_blocked_handle;
8740 return bc->blocked_on_keys;
8741}
8742
8743/* Unblock a client blocked by `RedisModule_BlockedClient`. This will trigger
8744 * the reply callbacks to be called in order to reply to the client.
8745 * The 'privdata' argument will be accessible by the reply callback, so
8746 * the caller of this function can pass any value that is needed in order to
8747 * actually reply to the client.
8748 *
8749 * A common usage for 'privdata' is a thread that computes something that
8750 * needs to be passed to the client, included but not limited some slow
8751 * to compute reply or some reply obtained via networking.
8752 *
8753 * Note 1: this function can be called from threads spawned by the module.
8754 *
8755 * Note 2: when we unblock a client that is blocked for keys using the API
8756 * RedisModule_BlockClientOnKeys(), the privdata argument here is not used.
8757 * Unblocking a client that was blocked for keys using this API will still
8758 * require the client to get some reply, so the function will use the
8759 * "timeout" handler in order to do so (The privdata provided in
8760 * RedisModule_BlockClientOnKeys() is accessible from the timeout
8761 * callback via RM_GetBlockedClientPrivateData). */
8762int RM_UnblockClient(RedisModuleBlockedClient *bc, void *privdata) {
8763 if (bc->blocked_on_keys) {
8764 /* In theory the user should always pass the timeout handler as an
8765 * argument, but better to be safe than sorry. */
8766 if (bc->timeout_callback == NULL) return REDISMODULE_ERR;
8767 if (bc->unblocked) return REDISMODULE_OK;
8768 if (bc->client) bc->blocked_on_keys_explicit_unblock = 1;
8769 }
8770 moduleUnblockClientByHandle(bc,privdata);
8771 return REDISMODULE_OK;
8772}
8773
8774/* Abort a blocked client blocking operation: the client will be unblocked
8775 * without firing any callback. */
8776int RM_AbortBlock(RedisModuleBlockedClient *bc) {
8777 bc->reply_callback = NULL;
8778 bc->disconnect_callback = NULL;
8779 bc->auth_reply_cb = NULL;
8780 return RM_UnblockClient(bc,NULL);
8781}
8782
8783/* Set a callback that will be called if a blocked client disconnects
8784 * before the module has a chance to call RedisModule_UnblockClient()
8785 *
8786 * Usually what you want to do there, is to cleanup your module state
8787 * so that you can call RedisModule_UnblockClient() safely, otherwise
8788 * the client will remain blocked forever if the timeout is large.
8789 *
8790 * Notes:
8791 *
8792 * 1. It is not safe to call Reply* family functions here, it is also
8793 * useless since the client is gone.
8794 *
8795 * 2. This callback is not called if the client disconnects because of
8796 * a timeout. In such a case, the client is unblocked automatically
8797 * and the timeout callback is called.
8798 */
8799void RM_SetDisconnectCallback(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback) {
8800 bc->disconnect_callback = callback;
8801}
8802
8803/* This function will check the moduleUnblockedClients queue in order to
8804 * call the reply callback and really unblock the client.
8805 *
8806 * Clients end into this list because of calls to RM_UnblockClient(),
8807 * however it is possible that while the module was doing work for the
8808 * blocked client, it was terminated by Redis (for timeout or other reasons).
8809 * When this happens the RedisModuleBlockedClient structure in the queue
8810 * will have the 'client' field set to NULL. */
8811void moduleHandleBlockedClients(void) {
8812 listNode *ln;
8813 RedisModuleBlockedClient *bc;
8814
8815 pthread_mutex_lock(&moduleUnblockedClientsMutex);
8816 while (listLength(moduleUnblockedClients)) {
8817 ln = listFirst(moduleUnblockedClients);
8818 bc = ln->value;
8819 client *c = bc->client;
8820 listDelNode(moduleUnblockedClients,ln);
8821 pthread_mutex_unlock(&moduleUnblockedClientsMutex);
8822
8823 /* Release the lock during the loop, as long as we don't
8824 * touch the shared list. */
8825
8826 /* Call the reply callback if the client is valid and we have
8827 * any callback. However the callback is not called if the client
8828 * was blocked on keys (RM_BlockClientOnKeys()), because we already
8829 * called such callback in moduleTryServeClientBlockedOnKey() when
8830 * the key was signaled as ready. */
8831 long long prev_error_replies = server.stat_total_error_replies;
8832 uint64_t reply_us = 0;
8833 if (c && !bc->blocked_on_keys && bc->reply_callback) {
8834 RedisModuleCtx ctx;
8835 moduleCreateContext(&ctx, bc->module, REDISMODULE_CTX_BLOCKED_REPLY);
8836 ctx.blocked_privdata = bc->privdata;
8837 ctx.blocked_ready_key = NULL;
8838 ctx.client = bc->client;
8839 ctx.blocked_client = bc;
8840 monotime replyTimer;
8841 elapsedStart(&replyTimer);
8842 bc->reply_callback(&ctx,(void**)c->argv,c->argc);
8843 reply_us = elapsedUs(replyTimer);
8844 moduleFreeContext(&ctx);
8845 }
8846 if (c && bc->blocked_on_keys_explicit_unblock) {
8847 serverAssert(bc->blocked_on_keys);
8848 moduleBlockedClientTimedOut(c);
8849 }
8850 /* Hold onto the blocked client if module auth is in progress. The reply callback is invoked
8851 * when the client is reprocessed. */
8852 if (c && clientHasModuleAuthInProgress(c)) {
8853 c->module_blocked_client = bc;
8854 } else {
8855 /* Free privdata if any. */
8856 moduleInvokeFreePrivDataCallback(c, bc);
8857 }
8858
8859 /* It is possible that this blocked client object accumulated
8860 * replies to send to the client in a thread safe context.
8861 * We need to glue such replies to the client output buffer and
8862 * free the temporary client we just used for the replies. */
8863 if (c) AddReplyFromClient(c, bc->reply_client);
8864 moduleReleaseTempClient(bc->reply_client);
8865 moduleReleaseTempClient(bc->thread_safe_ctx_client);
8866
8867 /* Update stats now that we've finished the blocking operation.
8868 * This needs to be out of the reply callback above given that a
8869 * module might not define any callback and still do blocking ops.
8870 *
8871 * If the module is blocked on keys updateStatsOnUnblock will be
8872 * called from moduleUnblockClientOnKey
8873 */
8874 if (c && !clientHasModuleAuthInProgress(c) && !bc->blocked_on_keys) {
8875 updateStatsOnUnblock(c, bc->background_duration, reply_us, server.stat_total_error_replies != prev_error_replies);
8876 }
8877
8878 if (c != NULL) {
8879 /* Before unblocking the client, set the disconnect callback
8880 * to NULL, because if we reached this point, the client was
8881 * properly unblocked by the module. */
8882 bc->disconnect_callback = NULL;
8883 unblockClient(c, 1);
8884
8885 /* Update the wait offset, we don't know if this blocked client propagated anything,
8886 * currently we rather not add any API for that, so we just assume it did. */
8887 c->woff = server.master_repl_offset;
8888
8889 /* Put the client in the list of clients that need to write
8890 * if there are pending replies here. This is needed since
8891 * during a non blocking command the client may receive output. */
8892 if (!clientHasModuleAuthInProgress(c) && clientHasPendingReplies(c) &&
8893 !(c->flags & CLIENT_PENDING_WRITE) && c->conn)
8894 {
8895 c->flags |= CLIENT_PENDING_WRITE;
8896 listLinkNodeHead(server.clients_pending_write, &c->clients_pending_write_node);
8897 }
8898 }
8899
8900 /* Free 'bc' only after unblocking the client, since it is
8901 * referenced in the client blocking context, and must be valid
8902 * when calling unblockClient(). */
8903 if (!(c && clientHasModuleAuthInProgress(c))) {
8904 bc->module->blocked_clients--;
8905 zfree(bc);
8906 }
8907
8908 /* Lock again before to iterate the loop. */
8909 pthread_mutex_lock(&moduleUnblockedClientsMutex);
8910 }
8911 pthread_mutex_unlock(&moduleUnblockedClientsMutex);
8912}
8913
8914/* Check if the specified client can be safely timed out using
8915 * moduleBlockedClientTimedOut().
8916 */
8917int moduleBlockedClientMayTimeout(client *c) {
8918 if (c->bstate.btype != BLOCKED_MODULE)
8919 return 1;
8920
8921 RedisModuleBlockedClient *bc = c->bstate.module_blocked_handle;
8922 return (bc && bc->timeout_callback != NULL);
8923}
8924
8925/* Called when our client timed out. After this function unblockClient()
8926 * is called, and it will invalidate the blocked client. So this function
8927 * does not need to do any cleanup. Eventually the module will call the
8928 * API to unblock the client and the memory will be released.
8929 *
8930 * This function should only be called from the main thread, we must handle the unblocking
8931 * of the client synchronously. This ensures that we can reply to the client before
8932 * resetClient() is called. */
8933void moduleBlockedClientTimedOut(client *c) {
8934 RedisModuleBlockedClient *bc = c->bstate.module_blocked_handle;
8935
8936 RedisModuleCtx ctx;
8937 moduleCreateContext(&ctx, bc->module, REDISMODULE_CTX_BLOCKED_TIMEOUT);
8938 ctx.client = bc->client;
8939 ctx.blocked_client = bc;
8940 ctx.blocked_privdata = bc->privdata;
8941
8942 long long prev_error_replies = server.stat_total_error_replies;
8943
8944 if (bc->timeout_callback) {
8945 /* In theory, the user should always pass the timeout handler as an
8946 * argument, but better to be safe than sorry. */
8947 bc->timeout_callback(&ctx,(void**)c->argv,c->argc);
8948 }
8949
8950 moduleFreeContext(&ctx);
8951
8952 updateStatsOnUnblock(c, bc->background_duration, 0, server.stat_total_error_replies != prev_error_replies);
8953
8954 /* For timeout events, we do not want to call the disconnect callback,
8955 * because the blocked client will be automatically disconnected in
8956 * this case, and the user can still hook using the timeout callback. */
8957 bc->disconnect_callback = NULL;
8958}
8959
8960/* Return non-zero if a module command was called in order to fill the
8961 * reply for a blocked client. */
8962int RM_IsBlockedReplyRequest(RedisModuleCtx *ctx) {
8963 return (ctx->flags & REDISMODULE_CTX_BLOCKED_REPLY) != 0;
8964}
8965
8966/* Return non-zero if a module command was called in order to fill the
8967 * reply for a blocked client that timed out. */
8968int RM_IsBlockedTimeoutRequest(RedisModuleCtx *ctx) {
8969 return (ctx->flags & REDISMODULE_CTX_BLOCKED_TIMEOUT) != 0;
8970}
8971
8972/* Get the private data set by RedisModule_UnblockClient() */
8973void *RM_GetBlockedClientPrivateData(RedisModuleCtx *ctx) {
8974 return ctx->blocked_privdata;
8975}
8976
8977/* Get the key that is ready when the reply callback is called in the context
8978 * of a client blocked by RedisModule_BlockClientOnKeys(). */
8979RedisModuleString *RM_GetBlockedClientReadyKey(RedisModuleCtx *ctx) {
8980 return ctx->blocked_ready_key;
8981}
8982
8983/* Get the blocked client associated with a given context.
8984 * This is useful in the reply and timeout callbacks of blocked clients,
8985 * before sometimes the module has the blocked client handle references
8986 * around, and wants to cleanup it. */
8987RedisModuleBlockedClient *RM_GetBlockedClientHandle(RedisModuleCtx *ctx) {
8988 return ctx->blocked_client;
8989}
8990
8991/* Return true if when the free callback of a blocked client is called,
8992 * the reason for the client to be unblocked is that it disconnected
8993 * while it was blocked. */
8994int RM_BlockedClientDisconnected(RedisModuleCtx *ctx) {
8995 return (ctx->flags & REDISMODULE_CTX_BLOCKED_DISCONNECTED) != 0;
8996}
8997
8998/* --------------------------------------------------------------------------
8999 * ## Thread Safe Contexts
9000 * -------------------------------------------------------------------------- */
9001
9002/* Return a context which can be used inside threads to make Redis context
9003 * calls with certain modules APIs. If 'bc' is not NULL then the module will
9004 * be bound to a blocked client, and it will be possible to use the
9005 * `RedisModule_Reply*` family of functions to accumulate a reply for when the
9006 * client will be unblocked. Otherwise the thread safe context will be
9007 * detached by a specific client.
9008 *
9009 * To call non-reply APIs, the thread safe context must be prepared with:
9010 *
9011 * RedisModule_ThreadSafeContextLock(ctx);
9012 * ... make your call here ...
9013 * RedisModule_ThreadSafeContextUnlock(ctx);
9014 *
9015 * This is not needed when using `RedisModule_Reply*` functions, assuming
9016 * that a blocked client was used when the context was created, otherwise
9017 * no RedisModule_Reply* call should be made at all.
9018 *
9019 * NOTE: If you're creating a detached thread safe context (bc is NULL),
9020 * consider using `RM_GetDetachedThreadSafeContext` which will also retain
9021 * the module ID and thus be more useful for logging. */
9022RedisModuleCtx *RM_GetThreadSafeContext(RedisModuleBlockedClient *bc) {
9023 RedisModuleCtx *ctx = zmalloc(sizeof(*ctx));
9024 RedisModule *module = bc ? bc->module : NULL;
9025 int flags = REDISMODULE_CTX_THREAD_SAFE;
9026
9027 /* Creating a new client object is costly. To avoid that, we have an
9028 * internal pool of client objects. In blockClient(), a client object is
9029 * assigned to bc->thread_safe_ctx_client to be used for the thread safe
9030 * context.
9031 * For detached thread safe contexts, we create a new client object.
9032 * Otherwise, as this function can be called from different threads, we
9033 * would need to synchronize access to internal pool of client objects.
9034 * Assuming creating detached context is rare and not that performance
9035 * critical, we avoid synchronizing access to the client pool by creating
9036 * a new client */
9037 if (!bc) flags |= REDISMODULE_CTX_NEW_CLIENT;
9038 moduleCreateContext(ctx, module, flags);
9039 /* Even when the context is associated with a blocked client, we can't
9040 * access it safely from another thread, so we use a fake client here
9041 * in order to keep things like the currently selected database and similar
9042 * things. */
9043 if (bc) {
9044 ctx->blocked_client = bc;
9045 ctx->client = bc->thread_safe_ctx_client;
9046 selectDb(ctx->client,bc->dbid);
9047 if (bc->client) {
9048 ctx->client->id = bc->client->id;
9049 ctx->client->resp = bc->client->resp;
9050 }
9051 }
9052 return ctx;
9053}
9054
9055/* Return a detached thread safe context that is not associated with any
9056 * specific blocked client, but is associated with the module's context.
9057 *
9058 * This is useful for modules that wish to hold a global context over
9059 * a long term, for purposes such as logging. */
9060RedisModuleCtx *RM_GetDetachedThreadSafeContext(RedisModuleCtx *ctx) {
9061 RedisModuleCtx *new_ctx = zmalloc(sizeof(*new_ctx));
9062 /* We create a new client object for the detached context.
9063 * See RM_GetThreadSafeContext() for more information */
9064 moduleCreateContext(new_ctx, ctx->module,
9065 REDISMODULE_CTX_THREAD_SAFE|REDISMODULE_CTX_NEW_CLIENT);
9066 return new_ctx;
9067}
9068
9069/* Release a thread safe context. */
9070void RM_FreeThreadSafeContext(RedisModuleCtx *ctx) {
9071 moduleFreeContext(ctx);
9072 zfree(ctx);
9073}
9074
9075void moduleGILAfterLock(void) {
9076 /* We should never get here if we already inside a module
9077 * code block which already opened a context. */
9078 serverAssert(server.execution_nesting == 0);
9079 /* Bump up the nesting level to prevent immediate propagation
9080 * of possible RM_Call from th thread */
9081 enterExecutionUnit(1, 0);
9082}
9083
9084/* Acquire the server lock before executing a thread safe API call.
9085 * This is not needed for `RedisModule_Reply*` calls when there is
9086 * a blocked client connected to the thread safe context. */
9087void RM_ThreadSafeContextLock(RedisModuleCtx *ctx) {
9088 UNUSED(ctx);
9089 moduleAcquireGIL();
9090 moduleGILAfterLock();
9091}
9092
9093/* Similar to RM_ThreadSafeContextLock but this function
9094 * would not block if the server lock is already acquired.
9095 *
9096 * If successful (lock acquired) REDISMODULE_OK is returned,
9097 * otherwise REDISMODULE_ERR is returned and errno is set
9098 * accordingly. */
9099int RM_ThreadSafeContextTryLock(RedisModuleCtx *ctx) {
9100 UNUSED(ctx);
9101
9102 int res = moduleTryAcquireGIL();
9103 if(res != 0) {
9104 errno = res;
9105 return REDISMODULE_ERR;
9106 }
9107 moduleGILAfterLock();
9108 return REDISMODULE_OK;
9109}
9110
9111void moduleGILBeforeUnlock(void) {
9112 /* We should never get here if we already inside a module
9113 * code block which already opened a context, except
9114 * the bump-up from moduleGILAcquired. */
9115 serverAssert(server.execution_nesting == 1);
9116 /* Restore nesting level and propagate pending commands
9117 * (because it's unclear when thread safe contexts are
9118 * released we have to propagate here). */
9119 exitExecutionUnit();
9120 postExecutionUnitOperations();
9121}
9122
9123/* Release the server lock after a thread safe API call was executed. */
9124void RM_ThreadSafeContextUnlock(RedisModuleCtx *ctx) {
9125 UNUSED(ctx);
9126 moduleGILBeforeUnlock();
9127 moduleReleaseGIL();
9128}
9129
9130void moduleAcquireGIL(void) {
9131 pthread_mutex_lock(&moduleGIL);
9132}
9133
9134int moduleTryAcquireGIL(void) {
9135 return pthread_mutex_trylock(&moduleGIL);
9136}
9137
9138void moduleReleaseGIL(void) {
9139 pthread_mutex_unlock(&moduleGIL);
9140}
9141
9142
9143/* --------------------------------------------------------------------------
9144 * ## Module Keyspace Notifications API
9145 * -------------------------------------------------------------------------- */
9146
9147/* Subscribe to keyspace notifications. This is a low-level version of the
9148 * keyspace-notifications API. A module can register callbacks to be notified
9149 * when keyspace events occur.
9150 *
9151 * Notification events are filtered by their type (string events, set events,
9152 * etc), and the subscriber callback receives only events that match a specific
9153 * mask of event types.
9154 *
9155 * When subscribing to notifications with RedisModule_SubscribeToKeyspaceEvents
9156 * the module must provide an event type-mask, denoting the events the subscriber
9157 * is interested in. This can be an ORed mask of any of the following flags:
9158 *
9159 * - REDISMODULE_NOTIFY_GENERIC: Generic commands like DEL, EXPIRE, RENAME
9160 * - REDISMODULE_NOTIFY_STRING: String events
9161 * - REDISMODULE_NOTIFY_LIST: List events
9162 * - REDISMODULE_NOTIFY_SET: Set events
9163 * - REDISMODULE_NOTIFY_HASH: Hash events
9164 * - REDISMODULE_NOTIFY_ZSET: Sorted Set events
9165 * - REDISMODULE_NOTIFY_EXPIRED: Expiration events
9166 * - REDISMODULE_NOTIFY_EVICTED: Eviction events
9167 * - REDISMODULE_NOTIFY_STREAM: Stream events
9168 * - REDISMODULE_NOTIFY_MODULE: Module types events
9169 * - REDISMODULE_NOTIFY_KEYMISS: Key-miss events
9170 * Notice, key-miss event is the only type
9171 * of event that is fired from within a read command.
9172 * Performing RM_Call with a write command from within
9173 * this notification is wrong and discourage. It will
9174 * cause the read command that trigger the event to be
9175 * replicated to the AOF/Replica.
9176 *
9177 * - REDISMODULE_NOTIFY_NEW: New key notification
9178 * - REDISMODULE_NOTIFY_OVERWRITTEN: Overwritten events
9179 * - REDISMODULE_NOTIFY_TYPE_CHANGED: Type-changed events
9180 * - REDISMODULE_NOTIFY_KEY_TRIMMED: Key trimmed events after a slot migration operation
9181 * - REDISMODULE_NOTIFY_ALL: All events (Excluding REDISMODULE_NOTIFY_KEYMISS,
9182 * REDISMODULE_NOTIFY_NEW, REDISMODULE_NOTIFY_OVERWRITTEN,
9183 * REDISMODULE_NOTIFY_TYPE_CHANGED
9184 * and REDISMODULE_NOTIFY_KEY_TRIMMED)
9185 * - REDISMODULE_NOTIFY_LOADED: A special notification available only for modules,
9186 * indicates that the key was loaded from persistence.
9187 * Notice, when this event fires, the given key
9188 * can not be retained, use RM_CreateStringFromString
9189 * instead.
9190 *
9191 * We do not distinguish between key events and keyspace events, and it is up
9192 * to the module to filter the actions taken based on the key.
9193 *
9194 * The subscriber signature is:
9195 *
9196 * int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type,
9197 * const char *event,
9198 * RedisModuleString *key);
9199 *
9200 * `type` is the event type bit, that must match the mask given at registration
9201 * time. The event string is the actual command being executed, and key is the
9202 * relevant Redis key.
9203 *
9204 * Notification callback gets executed with a redis context that can not be
9205 * used to send anything to the client, and has the db number where the event
9206 * occurred as its selected db number.
9207 *
9208 * Notice that it is not necessary to enable notifications in redis.conf for
9209 * module notifications to work.
9210 *
9211 * Warning: the notification callbacks are performed in a synchronous manner,
9212 * so notification callbacks must to be fast, or they would slow Redis down.
9213 * If you need to take long actions, use threads to offload them.
9214 *
9215 * Moreover, the fact that the notification is executed synchronously means
9216 * that the notification code will be executed in the middle on Redis logic
9217 * (commands logic, eviction, expire). Changing the key space while the logic
9218 * runs is dangerous and discouraged. In order to react to key space events with
9219 * write actions, please refer to `RM_AddPostNotificationJob`.
9220 *
9221 * See https://redis.io/docs/latest/develop/use/keyspace-notifications/ for more information.
9222 */
9223int RM_SubscribeToKeyspaceEvents(RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc callback) {
9224 RedisModuleKeyspaceSubscriber *sub = zmalloc(sizeof(*sub));
9225 sub->module = ctx->module;
9226 sub->event_mask = types;
9227 sub->notify_callback = callback;
9228 sub->active = 0;
9229
9230 listAddNodeTail(moduleKeyspaceSubscribers, sub);
9231 return REDISMODULE_OK;
9232}
9233
9234/*
9235 * RM_UnsubscribeFromKeyspaceEvents - Unregister a module's callback from keyspace notifications for specific event types.
9236 *
9237 * This function removes a previously registered subscription identified by both the event mask and the callback function.
9238 * It is useful to reduce performance overhead when the module no longer requires notifications for certain events.
9239 *
9240 * Parameters:
9241 * - ctx: The RedisModuleCtx associated with the calling module.
9242 * - types: The event mask representing the keyspace notification types to unsubscribe from.
9243 * - callback: The callback function pointer that was originally registered for these events.
9244 *
9245 * Returns:
9246 * - REDISMODULE_OK on successful removal of the subscription.
9247 * - REDISMODULE_ERR if no matching subscription was found or if invalid parameters were provided.
9248 */
9249int RM_UnsubscribeFromKeyspaceEvents(RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc callback) {
9250 if (!ctx || !callback) return REDISMODULE_ERR;
9251 int removed = 0;
9252 listIter li;
9253 listNode *ln;
9254 listRewind(moduleKeyspaceSubscribers,&li);
9255 while ((ln = listNext(&li))) {
9256 RedisModuleKeyspaceSubscriber *sub = ln->value;
9257 if (sub->event_mask == types && sub->notify_callback == callback && sub->module == ctx->module) {
9258 zfree(sub);
9259 listDelNode(moduleKeyspaceSubscribers, ln);
9260 removed++;
9261 }
9262 }
9263 return removed > 0 ? REDISMODULE_OK : REDISMODULE_ERR;
9264}
9265
9266/* Check any subscriber for event */
9267int moduleHasSubscribersForKeyspaceEvent(int type) {
9268 listIter li;
9269 listNode *ln;
9270 listRewind(moduleKeyspaceSubscribers,&li);
9271 while((ln = listNext(&li))) {
9272 RedisModuleKeyspaceSubscriber *sub = ln->value;
9273 if (sub->event_mask & type) return 1;
9274 }
9275 return 0;
9276}
9277
9278void firePostExecutionUnitJobs(void) {
9279 /* Avoid propagation of commands.
9280 * In that way, postExecutionUnitOperations will prevent
9281 * recursive calls to firePostExecutionUnitJobs.
9282 * This is a special case where we need to increase 'execution_nesting'
9283 * but we do not want to update the cached time */
9284 enterExecutionUnit(0, 0);
9285 while (listLength(modulePostExecUnitJobs) > 0) {
9286 listNode *ln = listFirst(modulePostExecUnitJobs);
9287 RedisModulePostExecUnitJob *job = listNodeValue(ln);
9288 listDelNode(modulePostExecUnitJobs, ln);
9289
9290 RedisModuleCtx ctx;
9291 moduleCreateContext(&ctx, job->module, REDISMODULE_CTX_TEMP_CLIENT);
9292 selectDb(ctx.client, job->dbid);
9293
9294 job->callback(&ctx, job->pd);
9295 if (job->free_pd) job->free_pd(job->pd);
9296
9297 moduleFreeContext(&ctx);
9298 zfree(job);
9299 }
9300 exitExecutionUnit();
9301}
9302
9303/* When running inside a key space notification callback, it is dangerous and highly discouraged to perform any write
9304 * operation (See `RM_SubscribeToKeyspaceEvents`). In order to still perform write actions in this scenario,
9305 * Redis provides `RM_AddPostNotificationJob` API. The API allows to register a job callback which Redis will call
9306 * when the following condition are promised to be fulfilled:
9307 * 1. It is safe to perform any write operation.
9308 * 2. The job will be called atomically along side the key space notification.
9309 *
9310 * Notice, one job might trigger key space notifications that will trigger more jobs.
9311 * This raises a concerns of entering an infinite loops, we consider infinite loops
9312 * as a logical bug that need to be fixed in the module, an attempt to protect against
9313 * infinite loops by halting the execution could result in violation of the feature correctness
9314 * and so Redis will make no attempt to protect the module from infinite loops.
9315 *
9316 * 'free_pd' can be NULL and in such case will not be used.
9317 *
9318 * Return REDISMODULE_OK on success and REDISMODULE_ERR if was called while loading data from disk (AOF or RDB) or
9319 * if the instance is a readonly replica. */
9320int RM_AddPostNotificationJob(RedisModuleCtx *ctx, RedisModulePostNotificationJobFunc callback, void *privdata, void (*free_privdata)(void*)) {
9321 if (server.loading|| (server.masterhost && server.repl_slave_ro)) {
9322 return REDISMODULE_ERR;
9323 }
9324 RedisModulePostExecUnitJob *job = zmalloc(sizeof(*job));
9325 job->module = ctx->module;
9326 job->callback = callback;
9327 job->pd = privdata;
9328 job->free_pd = free_privdata;
9329 job->dbid = ctx->client->db->id;
9330
9331 listAddNodeTail(modulePostExecUnitJobs, job);
9332 return REDISMODULE_OK;
9333}
9334
9335/* Get the configured bitmap of notify-keyspace-events (Could be used
9336 * for additional filtering in RedisModuleNotificationFunc) */
9337int RM_GetNotifyKeyspaceEvents(void) {
9338 return server.notify_keyspace_events;
9339}
9340
9341/* Expose notifyKeyspaceEvent to modules */
9342int RM_NotifyKeyspaceEvent(RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key) {
9343 if (!ctx || !ctx->client)
9344 return REDISMODULE_ERR;
9345 notifyKeyspaceEvent(type, (char *)event, key, ctx->client->db->id);
9346 return REDISMODULE_OK;
9347}
9348
9349/* Dispatcher for keyspace notifications to module subscriber functions.
9350 * This gets called only if at least one module requested to be notified on
9351 * keyspace notifications */
9352void moduleNotifyKeyspaceEvent(int type, const char *event, robj *key, int dbid) {
9353 /* Don't do anything if there aren't any subscribers */
9354 if (listLength(moduleKeyspaceSubscribers) == 0) return;
9355
9356 /* Ugly hack to handle modules which use write commands from within
9357 * notify_callback, which they should NOT do!
9358 * Modules should use RedisModules_AddPostNotificationJob instead.
9359 *
9360 * Anyway, we want any propagated commands from within notify_callback
9361 * to be propagated inside a MULTI/EXEC together with the original
9362 * command that caused the KSN.
9363 * Note that it's only relevant for KSNs which are not generated from within
9364 * call(), for example active-expiry and eviction (because anyway
9365 * execution_nesting is incremented from within call())
9366 *
9367 * In order to do that we increment the execution_nesting counter, thus
9368 * preventing postExecutionUnitOperations (from within moduleFreeContext)
9369 * from propagating commands from CB.
9370 *
9371 * This is a special case where we need to increase 'execution_nesting'
9372 * but we do not want to update the cached time */
9373 enterExecutionUnit(0, 0);
9374
9375 listIter li;
9376 listNode *ln;
9377 listRewind(moduleKeyspaceSubscribers,&li);
9378
9379 /* Remove irrelevant flags from the type mask */
9380 type &= ~(NOTIFY_KEYEVENT | NOTIFY_KEYSPACE);
9381
9382 while((ln = listNext(&li))) {
9383 RedisModuleKeyspaceSubscriber *sub = ln->value;
9384 /* Only notify subscribers on events matching the registration,
9385 * and avoid subscribers triggering themselves */
9386 if ((sub->event_mask & type) &&
9387 (sub->active == 0 || (sub->module->options & REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS))) {
9388 RedisModuleCtx ctx;
9389 moduleCreateContext(&ctx, sub->module, REDISMODULE_CTX_TEMP_CLIENT);
9390 selectDb(ctx.client, dbid);
9391
9392 /* mark the handler as active to avoid reentrant loops.
9393 * If the subscriber performs an action triggering itself,
9394 * it will not be notified about it. */
9395 int prev_active = sub->active;
9396 sub->active = 1;
9397 server.allow_access_expired++;
9398 server.allow_access_trimmed++;
9399 sub->notify_callback(&ctx, type, event, key);
9400 server.allow_access_expired--;
9401 server.allow_access_trimmed--;
9402 sub->active = prev_active;
9403 moduleFreeContext(&ctx);
9404 }
9405 }
9406
9407 exitExecutionUnit();
9408}
9409
9410/* Unsubscribe any notification subscribers this module has upon unloading */
9411void moduleUnsubscribeNotifications(RedisModule *module) {
9412 listIter li;
9413 listNode *ln;
9414 listRewind(moduleKeyspaceSubscribers,&li);
9415 while((ln = listNext(&li))) {
9416 RedisModuleKeyspaceSubscriber *sub = ln->value;
9417 if (sub->module == module) {
9418 listDelNode(moduleKeyspaceSubscribers, ln);
9419 zfree(sub);
9420 }
9421 }
9422}
9423
9424/* --------------------------------------------------------------------------
9425 * ## Modules Cluster API
9426 * -------------------------------------------------------------------------- */
9427
9428/* The Cluster message callback function pointer type. */
9429typedef void (*RedisModuleClusterMessageReceiver)(RedisModuleCtx *ctx, const char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len);
9430
9431/* This structure identifies a registered caller: it must match a given module
9432 * ID, for a given message type. The callback function is just the function
9433 * that was registered as receiver. */
9434typedef struct moduleClusterReceiver {
9435 uint64_t module_id;
9436 RedisModuleClusterMessageReceiver callback;
9437 struct RedisModule *module;
9438 struct moduleClusterReceiver *next;
9439} moduleClusterReceiver;
9440
9441typedef struct moduleClusterNodeInfo {
9442 int flags;
9443 char ip[NET_IP_STR_LEN];
9444 int port;
9445 char master_id[40]; /* Only if flags & REDISMODULE_NODE_MASTER is true. */
9446} mdouleClusterNodeInfo;
9447
9448/* We have an array of message types: each bucket is a linked list of
9449 * configured receivers. */
9450static moduleClusterReceiver *clusterReceivers[UINT8_MAX];
9451
9452/* Dispatch the message to the right module receiver. */
9453void moduleCallClusterReceivers(const char *sender_id, uint64_t module_id, uint8_t type, const unsigned char *payload, uint32_t len) {
9454 moduleClusterReceiver *r = clusterReceivers[type];
9455 while(r) {
9456 if (r->module_id == module_id) {
9457 RedisModuleCtx ctx;
9458 moduleCreateContext(&ctx, r->module, REDISMODULE_CTX_TEMP_CLIENT);
9459 r->callback(&ctx,sender_id,type,payload,len);
9460 moduleFreeContext(&ctx);
9461 return;
9462 }
9463 r = r->next;
9464 }
9465}
9466
9467/* Register a callback receiver for cluster messages of type 'type'. If there
9468 * was already a registered callback, this will replace the callback function
9469 * with the one provided, otherwise if the callback is set to NULL and there
9470 * is already a callback for this function, the callback is unregistered
9471 * (so this API call is also used in order to delete the receiver). */
9472void RM_RegisterClusterMessageReceiver(RedisModuleCtx *ctx, uint8_t type, RedisModuleClusterMessageReceiver callback) {
9473 if (!server.cluster_enabled) return;
9474
9475 uint64_t module_id = moduleTypeEncodeId(ctx->module->name,0);
9476 moduleClusterReceiver *r = clusterReceivers[type], *prev = NULL;
9477 while(r) {
9478 if (r->module_id == module_id) {
9479 /* Found! Set or delete. */
9480 if (callback) {
9481 r->callback = callback;
9482 } else {
9483 /* Delete the receiver entry if the user is setting
9484 * it to NULL. Just unlink the receiver node from the
9485 * linked list. */
9486 if (prev)
9487 prev->next = r->next;
9488 else
9489 clusterReceivers[type]->next = r->next;
9490 zfree(r);
9491 }
9492 return;
9493 }
9494 prev = r;
9495 r = r->next;
9496 }
9497
9498 /* Not found, let's add it. */
9499 if (callback) {
9500 r = zmalloc(sizeof(*r));
9501 r->module_id = module_id;
9502 r->module = ctx->module;
9503 r->callback = callback;
9504 r->next = clusterReceivers[type];
9505 clusterReceivers[type] = r;
9506 }
9507}
9508
9509/* Send a message to all the nodes in the cluster if `target` is NULL, otherwise
9510 * at the specified target, which is a REDISMODULE_NODE_ID_LEN bytes node ID, as
9511 * returned by the receiver callback or by the nodes iteration functions.
9512 *
9513 * The function returns REDISMODULE_OK if the message was successfully sent,
9514 * otherwise if the node is not connected or such node ID does not map to any
9515 * known cluster node, REDISMODULE_ERR is returned. */
9516int RM_SendClusterMessage(RedisModuleCtx *ctx, const char *target_id, uint8_t type, const char *msg, uint32_t len) {
9517 if (!server.cluster_enabled) return REDISMODULE_ERR;
9518 uint64_t module_id = moduleTypeEncodeId(ctx->module->name,0);
9519 if (clusterSendModuleMessageToTarget(target_id,module_id,type,msg,len) == C_OK)
9520 return REDISMODULE_OK;
9521 else
9522 return REDISMODULE_ERR;
9523}
9524
9525/* Return an array of string pointers, each string pointer points to a cluster
9526 * node ID of exactly REDISMODULE_NODE_ID_LEN bytes (without any null term).
9527 * The number of returned node IDs is stored into `*numnodes`.
9528 * However if this function is called by a module not running an a Redis
9529 * instance with Redis Cluster enabled, NULL is returned instead.
9530 *
9531 * The IDs returned can be used with RedisModule_GetClusterNodeInfo() in order
9532 * to get more information about single node.
9533 *
9534 * The array returned by this function must be freed using the function
9535 * RedisModule_FreeClusterNodesList().
9536 *
9537 * Example:
9538 *
9539 * size_t count, j;
9540 * char **ids = RedisModule_GetClusterNodesList(ctx,&count);
9541 * for (j = 0; j < count; j++) {
9542 * RedisModule_Log(ctx,"notice","Node %.*s",
9543 * REDISMODULE_NODE_ID_LEN,ids[j]);
9544 * }
9545 * RedisModule_FreeClusterNodesList(ids);
9546 */
9547char **RM_GetClusterNodesList(RedisModuleCtx *ctx, size_t *numnodes) {
9548 UNUSED(ctx);
9549
9550 if (!server.cluster_enabled) return NULL;
9551 return getClusterNodesList(numnodes);
9552}
9553
9554/* Free the node list obtained with RedisModule_GetClusterNodesList. */
9555void RM_FreeClusterNodesList(char **ids) {
9556 if (ids == NULL) return;
9557 for (int j = 0; ids[j]; j++) zfree(ids[j]);
9558 zfree(ids);
9559}
9560
9561/* Return this node ID (REDISMODULE_CLUSTER_ID_LEN bytes) or NULL if the cluster
9562 * is disabled. */
9563const char *RM_GetMyClusterID(void) {
9564 if (!server.cluster_enabled) return NULL;
9565 return getMyClusterId();
9566}
9567
9568/* Return the number of nodes in the cluster, regardless of their state
9569 * (handshake, noaddress, ...) so that the number of active nodes may actually
9570 * be smaller, but not greater than this number. If the instance is not in
9571 * cluster mode, zero is returned. */
9572size_t RM_GetClusterSize(void) {
9573 if (!server.cluster_enabled) return 0;
9574 return getClusterSize();
9575}
9576
9577/* Populate the specified info for the node having as ID the specified 'id',
9578 * then returns REDISMODULE_OK. Otherwise if the format of node ID is invalid
9579 * or the node ID does not exist from the POV of this local node, REDISMODULE_ERR
9580 * is returned.
9581 *
9582 * The arguments `ip`, `master_id`, `port` and `flags` can be NULL in case we don't
9583 * need to populate back certain info. If an `ip` and `master_id` (only populated
9584 * if the instance is a slave) are specified, they point to buffers holding
9585 * at least REDISMODULE_NODE_ID_LEN bytes. The strings written back as `ip`
9586 * and `master_id` are not null terminated.
9587 *
9588 * The list of flags reported is the following:
9589 *
9590 * * REDISMODULE_NODE_MYSELF: This node
9591 * * REDISMODULE_NODE_MASTER: The node is a master
9592 * * REDISMODULE_NODE_SLAVE: The node is a replica
9593 * * REDISMODULE_NODE_PFAIL: We see the node as failing
9594 * * REDISMODULE_NODE_FAIL: The cluster agrees the node is failing
9595 * * REDISMODULE_NODE_NOFAILOVER: The slave is configured to never failover
9596 */
9597int RM_GetClusterNodeInfo(RedisModuleCtx *ctx, const char *id, char *ip, char *master_id, int *port, int *flags) {
9598 UNUSED(ctx);
9599
9600 clusterNode *node = clusterLookupNode(id, CLUSTER_NAMELEN);
9601 if (node == NULL || clusterNodePending(node))
9602 {
9603 return REDISMODULE_ERR;
9604 }
9605
9606 if (ip) redis_strlcpy(ip, clusterNodeIp(node),NET_IP_STR_LEN);
9607
9608 if (master_id) {
9609 /* If the information is not available, the function will set the
9610 * field to zero bytes, so that when the field can't be populated the
9611 * function kinda remains predictable. */
9612 if (clusterNodeIsSlave(node) && clusterNodeGetSlaveof(node))
9613 memcpy(master_id, clusterNodeGetName(clusterNodeGetSlaveof(node)) ,REDISMODULE_NODE_ID_LEN);
9614 else
9615 memset(master_id,0,REDISMODULE_NODE_ID_LEN);
9616 }
9617 if (port) *port = getNodeDefaultClientPort(node);
9618
9619 /* As usually we have to remap flags for modules, in order to ensure
9620 * we can provide binary compatibility. */
9621 if (flags) {
9622 *flags = 0;
9623 if (clusterNodeIsMyself(node)) *flags |= REDISMODULE_NODE_MYSELF;
9624 if (clusterNodeIsMaster(node)) *flags |= REDISMODULE_NODE_MASTER;
9625 if (clusterNodeIsSlave(node)) *flags |= REDISMODULE_NODE_SLAVE;
9626 if (clusterNodeTimedOut(node)) *flags |= REDISMODULE_NODE_PFAIL;
9627 if (clusterNodeIsFailing(node)) *flags |= REDISMODULE_NODE_FAIL;
9628 if (clusterNodeIsNoFailover(node)) *flags |= REDISMODULE_NODE_NOFAILOVER;
9629 }
9630 return REDISMODULE_OK;
9631}
9632
9633/* Set Redis Cluster flags in order to change the normal behavior of
9634 * Redis Cluster, especially with the goal of disabling certain functions.
9635 * This is useful for modules that use the Cluster API in order to create
9636 * a different distributed system, but still want to use the Redis Cluster
9637 * message bus. Flags that can be set:
9638 *
9639 * * CLUSTER_MODULE_FLAG_NO_FAILOVER
9640 * * CLUSTER_MODULE_FLAG_NO_REDIRECTION
9641 *
9642 * With the following effects:
9643 *
9644 * * NO_FAILOVER: prevent Redis Cluster slaves from failing over a dead master.
9645 * Also disables the replica migration feature.
9646 *
9647 * * NO_REDIRECTION: Every node will accept any key, without trying to perform
9648 * partitioning according to the Redis Cluster algorithm.
9649 * Slots information will still be propagated across the
9650 * cluster, but without effect. */
9651void RM_SetClusterFlags(RedisModuleCtx *ctx, uint64_t flags) {
9652 UNUSED(ctx);
9653 server.cluster_module_flags = CLUSTER_MODULE_FLAG_NONE;
9654 if (flags & REDISMODULE_CLUSTER_FLAG_NO_FAILOVER)
9655 server.cluster_module_flags |= CLUSTER_MODULE_FLAG_NO_FAILOVER;
9656 if (flags & REDISMODULE_CLUSTER_FLAG_NO_REDIRECTION)
9657 server.cluster_module_flags |= CLUSTER_MODULE_FLAG_NO_REDIRECTION;
9658}
9659
9660/* RM_ClusterDisableTrim allows a module to temporarily prevent slot trimming
9661 * after a slot migration. This is useful when the module has asynchronous
9662 * operations that rely on keys in migrating slots, which would be trimmed.
9663 *
9664 * The module must call RM_ClusterEnableTrim once it has completed those
9665 * operations to re-enable trimming.
9666 *
9667 * Trimming uses a reference counter: every call to RM_ClusterDisableTrim
9668 * increments the counter, and every RM_ClusterEnableTrim call decrements it.
9669 * Trimming remains disabled as long as the counter is greater than zero.
9670 *
9671 * Disable automatic slot trimming. */
9672int RM_ClusterDisableTrim(RedisModuleCtx *ctx) {
9673 UNUSED(ctx);
9674 if (server.cluster_module_trim_disablers < INT_MAX) {
9675 server.cluster_module_trim_disablers++;
9676 return REDISMODULE_OK;
9677 }
9678 return REDISMODULE_ERR;
9679}
9680
9681/* Enable automatic slot trimming. See also comments on RM_ClusterDisableTrim. */
9682int RM_ClusterEnableTrim(RedisModuleCtx *ctx) {
9683 UNUSED(ctx);
9684 if (server.cluster_module_trim_disablers > 0) {
9685 server.cluster_module_trim_disablers--;
9686 return REDISMODULE_OK;
9687 }
9688 return REDISMODULE_ERR;
9689}
9690
9691/* Returns the cluster slot of a key, similar to the `CLUSTER KEYSLOT` command.
9692 * This function works even if cluster mode is not enabled. */
9693unsigned int RM_ClusterKeySlot(RedisModuleString *key) {
9694 return keyHashSlot(key->ptr, sdslen(key->ptr));
9695}
9696
9697/* Like `RM_ClusterKeySlot`, but gets a char pointer and a length.
9698 * Returns the cluster slot of a key, similar to the `CLUSTER KEYSLOT` command.
9699 * This function works even if cluster mode is not enabled. */
9700unsigned int RM_ClusterKeySlotC(const char *keystr, size_t keylen) {
9701 return keyHashSlot(keystr, keylen);
9702}
9703
9704/* Returns a short string that can be used as a key or as a hash tag in a key,
9705 * such that the key maps to the given cluster slot. Returns NULL if slot is not
9706 * a valid slot. */
9707const char *RM_ClusterCanonicalKeyNameInSlot(unsigned int slot) {
9708 return (slot < CLUSTER_SLOTS) ? crc16_slot_table[slot] : NULL;
9709}
9710
9711/* Returns 1 if keys in the specified slot can be accessed by this node, 0 otherwise.
9712 *
9713 * This function returns 1 in the following cases:
9714 * - The slot is owned by this node or by its master if this node is a replica
9715 * - The slot is being imported under the old slot migration approach (CLUSTER SETSLOT <slot> IMPORTING ..)
9716 * - Not in cluster mode (all slots are accessible)
9717 *
9718 * Returns 0 for:
9719 * - Invalid slot numbers (< 0 or >= 16384)
9720 * - Slots owned by other nodes
9721 */
9722int RM_ClusterCanAccessKeysInSlot(int slot) {
9723 if (slot < 0 || slot >= CLUSTER_SLOTS) return 0;
9724 return clusterCanAccessKeysInSlot(slot);
9725}
9726
9727/* Propagate commands along with slot migration.
9728 *
9729 * This function allows modules to add commands that will be sent to the
9730 * destination node before the actual slot migration begins. It should only be
9731 * called during the REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_MODULE_PROPAGATE event.
9732 *
9733 * This function can be called multiple times within the same event to
9734 * replicate multiple commands. All commands will be sent before the
9735 * actual slot data migration begins.
9736 *
9737 * Note: This function is only available in the fork child process just before
9738 * slot snapshot delivery begins.
9739 *
9740 * On success REDISMODULE_OK is returned, otherwise
9741 * REDISMODULE_ERR is returned and errno is set to the following values:
9742 *
9743 * * EINVAL: function arguments or format specifiers are invalid.
9744 * * EBADF: not called in the correct context, e.g. not called in the REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_MODULE_PROPAGATE event.
9745 * * ENOENT: command does not exist.
9746 * * ENOTSUP: command is cross-slot.
9747 * * ERANGE: command contains keys that are not within the migrating slot range.
9748 */
9749int RM_ClusterPropagateForSlotMigration(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
9750 int argc = 0, flags = 0;
9751 robj **argv = NULL;
9752 struct redisCommand *cmd;
9753 va_list ap;
9754
9755 if (ctx == NULL || cmdname == NULL || fmt == NULL) {
9756 errno = EINVAL;
9757 return REDISMODULE_ERR;
9758 }
9759
9760 errno = 0;
9761 cmd = lookupCommandByCString((char*)cmdname);
9762 if (!cmd) {
9763 errno = ENOENT;
9764 return REDISMODULE_ERR;
9765 }
9766
9767 va_start(ap, fmt);
9768 argv = moduleCreateArgvFromUserFormat(cmdname, fmt, &argc, &flags, ap);
9769 va_end(ap);
9770 if (argv == NULL) {
9771 errno = EINVAL;
9772 return REDISMODULE_ERR;
9773 }
9774
9775 int ret = asmModulePropagateBeforeSlotSnapshot(cmd, argv, argc);
9776 int saved_errno = errno;
9777
9778 /* Release the argv. */
9779 for (int i = 0; i < argc; i++) decrRefCount(argv[i]);
9780 zfree(argv);
9781 errno = saved_errno;
9782 return ret == C_OK ? REDISMODULE_OK : REDISMODULE_ERR;
9783}
9784
9785/* Returns the locally owned slot ranges for the node.
9786 *
9787 * An optional `ctx` can be provided to enable auto-memory management.
9788 * If cluster mode is disabled, the array will include all slots (0–16383).
9789 * If the node is a replica, the slot ranges of its master are returned.
9790 *
9791 * The returned array must be freed with RM_ClusterFreeSlotRanges().
9792 */
9793RedisModuleSlotRangeArray *RM_ClusterGetLocalSlotRanges(RedisModuleCtx *ctx) {
9794 slotRangeArray *slots = clusterGetLocalSlotRanges();
9795 if (ctx) autoMemoryAdd(ctx, REDISMODULE_AM_SLOTRANGEARRAY, slots);
9796 return (RedisModuleSlotRangeArray *)slots;
9797}
9798
9799/* Frees a slot range array returned by RM_ClusterGetLocalSlotRanges().
9800 * Pass the `ctx` pointer only if the array was created with a context. */
9801void RM_ClusterFreeSlotRanges(RedisModuleCtx *ctx, RedisModuleSlotRangeArray *slots) {
9802 if (ctx) autoMemoryFreed(ctx, REDISMODULE_AM_SLOTRANGEARRAY, slots);
9803 slotRangeArrayFree((slotRangeArray *)slots);
9804}
9805
9806/* --------------------------------------------------------------------------
9807 * ## Modules Timers API
9808 *
9809 * Module timers are a high precision "green timers" abstraction where
9810 * every module can register even millions of timers without problems, even if
9811 * the actual event loop will just have a single timer that is used to awake the
9812 * module timers subsystem in order to process the next event.
9813 *
9814 * All the timers are stored into a radix tree, ordered by expire time, when
9815 * the main Redis event loop timer callback is called, we try to process all
9816 * the timers already expired one after the other. Then we re-enter the event
9817 * loop registering a timer that will expire when the next to process module
9818 * timer will expire.
9819 *
9820 * Every time the list of active timers drops to zero, we unregister the
9821 * main event loop timer, so that there is no overhead when such feature is
9822 * not used.
9823 * -------------------------------------------------------------------------- */
9824
9825static rax *Timers; /* The radix tree of all the timers sorted by expire. */
9826long long aeTimer = -1; /* Main event loop (ae.c) timer identifier. */
9827
9828typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data);
9829
9830/* The timer descriptor, stored as value in the radix tree. */
9831typedef struct RedisModuleTimer {
9832 RedisModule *module; /* Module reference. */
9833 RedisModuleTimerProc callback; /* The callback to invoke on expire. */
9834 void *data; /* Private data for the callback. */
9835 int dbid; /* Database number selected by the original client. */
9836} RedisModuleTimer;
9837
9838/* This is the timer handler that is called by the main event loop. We schedule
9839 * this timer to be called when the nearest of our module timers will expire. */
9840int moduleTimerHandler(struct aeEventLoop *eventLoop, long long id, void *clientData) {
9841 UNUSED(eventLoop);
9842 UNUSED(id);
9843 UNUSED(clientData);
9844
9845 /* To start let's try to fire all the timers already expired. */
9846 raxIterator ri;
9847 raxStart(&ri,Timers);
9848 uint64_t now = ustime();
9849 long long next_period = 0;
9850 while(1) {
9851 raxSeek(&ri,"^",NULL,0);
9852 if (!raxNext(&ri)) break;
9853 uint64_t expiretime;
9854 memcpy(&expiretime,ri.key,sizeof(expiretime));
9855 expiretime = ntohu64(expiretime);
9856 if (now >= expiretime) {
9857 RedisModuleTimer *timer = ri.data;
9858 RedisModuleCtx ctx;
9859 moduleCreateContext(&ctx,timer->module,REDISMODULE_CTX_TEMP_CLIENT);
9860 selectDb(ctx.client, timer->dbid);
9861 timer->callback(&ctx,timer->data);
9862 moduleFreeContext(&ctx);
9863 raxRemove(Timers,(unsigned char*)ri.key,ri.key_len,NULL);
9864 zfree(timer);
9865 } else {
9866 /* We call ustime() again instead of using the cached 'now' so that
9867 * 'next_period' isn't affected by the time it took to execute
9868 * previous calls to 'callback.
9869 * We need to cast 'expiretime' so that the compiler will not treat
9870 * the difference as unsigned (Causing next_period to be huge) in
9871 * case expiretime < ustime() */
9872 next_period = ((long long)expiretime-ustime())/1000; /* Scale to milliseconds. */
9873 break;
9874 }
9875 }
9876 raxStop(&ri);
9877
9878 /* Reschedule the next timer or cancel it. */
9879 if (next_period <= 0) next_period = 1;
9880 if (raxSize(Timers) > 0) {
9881 return next_period;
9882 } else {
9883 aeTimer = -1;
9884 return AE_NOMORE;
9885 }
9886}
9887
9888/* Create a new timer that will fire after `period` milliseconds, and will call
9889 * the specified function using `data` as argument. The returned timer ID can be
9890 * used to get information from the timer or to stop it before it fires.
9891 * Note that for the common use case of a repeating timer (Re-registration
9892 * of the timer inside the RedisModuleTimerProc callback) it matters when
9893 * this API is called:
9894 * If it is called at the beginning of 'callback' it means
9895 * the event will triggered every 'period'.
9896 * If it is called at the end of 'callback' it means
9897 * there will 'period' milliseconds gaps between events.
9898 * (If the time it takes to execute 'callback' is negligible the two
9899 * statements above mean the same) */
9900RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data) {
9901 RedisModuleTimer *timer = zmalloc(sizeof(*timer));
9902 timer->module = ctx->module;
9903 timer->callback = callback;
9904 timer->data = data;
9905 timer->dbid = ctx->client ? ctx->client->db->id : 0;
9906 uint64_t expiretime = ustime()+period*1000;
9907 uint64_t key;
9908
9909 while(1) {
9910 key = htonu64(expiretime);
9911 if (!raxFind(Timers, (unsigned char*)&key,sizeof(key),NULL)) {
9912 raxInsert(Timers,(unsigned char*)&key,sizeof(key),timer,NULL);
9913 break;
9914 } else {
9915 expiretime++;
9916 }
9917 }
9918
9919 /* We need to install the main event loop timer if it's not already
9920 * installed, or we may need to refresh its period if we just installed
9921 * a timer that will expire sooner than any other else (i.e. the timer
9922 * we just installed is the first timer in the Timers rax). */
9923 if (aeTimer != -1) {
9924 raxIterator ri;
9925 raxStart(&ri,Timers);
9926 raxSeek(&ri,"^",NULL,0);
9927 raxNext(&ri);
9928 if (memcmp(ri.key,&key,sizeof(key)) == 0) {
9929 /* This is the first key, we need to re-install the timer according
9930 * to the just added event. */
9931 aeDeleteTimeEvent(server.el,aeTimer);
9932 aeTimer = -1;
9933 }
9934 raxStop(&ri);
9935 }
9936
9937 /* If we have no main timer (the old one was invalidated, or this is the
9938 * first module timer we have), install one. */
9939 if (aeTimer == -1)
9940 aeTimer = aeCreateTimeEvent(server.el,period,moduleTimerHandler,NULL,NULL);
9941
9942 return key;
9943}
9944
9945/* Stop a timer, returns REDISMODULE_OK if the timer was found, belonged to the
9946 * calling module, and was stopped, otherwise REDISMODULE_ERR is returned.
9947 * If not NULL, the data pointer is set to the value of the data argument when
9948 * the timer was created. */
9949int RM_StopTimer(RedisModuleCtx *ctx, RedisModuleTimerID id, void **data) {
9950 void *result;
9951 if (!raxFind(Timers,(unsigned char*)&id,sizeof(id),&result))
9952 return REDISMODULE_ERR;
9953 RedisModuleTimer *timer = result;
9954 if (timer->module != ctx->module)
9955 return REDISMODULE_ERR;
9956 if (data) *data = timer->data;
9957 raxRemove(Timers,(unsigned char*)&id,sizeof(id),NULL);
9958 zfree(timer);
9959 return REDISMODULE_OK;
9960}
9961
9962/* Obtain information about a timer: its remaining time before firing
9963 * (in milliseconds), and the private data pointer associated with the timer.
9964 * If the timer specified does not exist or belongs to a different module
9965 * no information is returned and the function returns REDISMODULE_ERR, otherwise
9966 * REDISMODULE_OK is returned. The arguments remaining or data can be NULL if
9967 * the caller does not need certain information. */
9968int RM_GetTimerInfo(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remaining, void **data) {
9969 void *result;
9970 if (!raxFind(Timers,(unsigned char*)&id,sizeof(id),&result))
9971 return REDISMODULE_ERR;
9972 RedisModuleTimer *timer = result;
9973 if (timer->module != ctx->module)
9974 return REDISMODULE_ERR;
9975 if (remaining) {
9976 int64_t rem = ntohu64(id)-ustime();
9977 if (rem < 0) rem = 0;
9978 *remaining = rem/1000; /* Scale to milliseconds. */
9979 }
9980 if (data) *data = timer->data;
9981 return REDISMODULE_OK;
9982}
9983
9984/* Query timers to see if any timer belongs to the module.
9985 * Return 1 if any timer was found, otherwise 0 would be returned. */
9986int moduleHoldsTimer(struct RedisModule *module) {
9987 raxIterator iter;
9988 int found = 0;
9989 raxStart(&iter,Timers);
9990 raxSeek(&iter,"^",NULL,0);
9991 while (raxNext(&iter)) {
9992 RedisModuleTimer *timer = iter.data;
9993 if (timer->module == module) {
9994 found = 1;
9995 break;
9996 }
9997 }
9998 raxStop(&iter);
9999 return found;
10000}
10001
10002/* --------------------------------------------------------------------------
10003 * ## Modules EventLoop API
10004 * --------------------------------------------------------------------------*/
10005
10006typedef struct EventLoopData {
10007 RedisModuleEventLoopFunc rFunc;
10008 RedisModuleEventLoopFunc wFunc;
10009 void *user_data;
10010} EventLoopData;
10011
10012typedef struct EventLoopOneShot {
10013 RedisModuleEventLoopOneShotFunc func;
10014 void *user_data;
10015} EventLoopOneShot;
10016
10017list *moduleEventLoopOneShots;
10018static pthread_mutex_t moduleEventLoopMutex = PTHREAD_MUTEX_INITIALIZER;
10019
10020static int eventLoopToAeMask(int mask) {
10021 int aeMask = 0;
10022 if (mask & REDISMODULE_EVENTLOOP_READABLE)
10023 aeMask |= AE_READABLE;
10024 if (mask & REDISMODULE_EVENTLOOP_WRITABLE)
10025 aeMask |= AE_WRITABLE;
10026 return aeMask;
10027}
10028
10029static int eventLoopFromAeMask(int ae_mask) {
10030 int mask = 0;
10031 if (ae_mask & AE_READABLE)
10032 mask |= REDISMODULE_EVENTLOOP_READABLE;
10033 if (ae_mask & AE_WRITABLE)
10034 mask |= REDISMODULE_EVENTLOOP_WRITABLE;
10035 return mask;
10036}
10037
10038static void eventLoopCbReadable(struct aeEventLoop *ae, int fd, void *user_data, int ae_mask) {
10039 UNUSED(ae);
10040 EventLoopData *data = user_data;
10041 data->rFunc(fd, data->user_data, eventLoopFromAeMask(ae_mask));
10042}
10043
10044static void eventLoopCbWritable(struct aeEventLoop *ae, int fd, void *user_data, int ae_mask) {
10045 UNUSED(ae);
10046 EventLoopData *data = user_data;
10047 data->wFunc(fd, data->user_data, eventLoopFromAeMask(ae_mask));
10048}
10049
10050/* Add a pipe / socket event to the event loop.
10051 *
10052 * * `mask` must be one of the following values:
10053 *
10054 * * `REDISMODULE_EVENTLOOP_READABLE`
10055 * * `REDISMODULE_EVENTLOOP_WRITABLE`
10056 * * `REDISMODULE_EVENTLOOP_READABLE | REDISMODULE_EVENTLOOP_WRITABLE`
10057 *
10058 * On success REDISMODULE_OK is returned, otherwise
10059 * REDISMODULE_ERR is returned and errno is set to the following values:
10060 *
10061 * * ERANGE: `fd` is negative or higher than `maxclients` Redis config.
10062 * * EINVAL: `callback` is NULL or `mask` value is invalid.
10063 *
10064 * `errno` might take other values in case of an internal error.
10065 *
10066 * Example:
10067 *
10068 * void onReadable(int fd, void *user_data, int mask) {
10069 * char buf[32];
10070 * int bytes = read(fd,buf,sizeof(buf));
10071 * printf("Read %d bytes \n", bytes);
10072 * }
10073 * RM_EventLoopAdd(fd, REDISMODULE_EVENTLOOP_READABLE, onReadable, NULL);
10074 */
10075int RM_EventLoopAdd(int fd, int mask, RedisModuleEventLoopFunc func, void *user_data) {
10076 if (fd < 0 || fd >= aeGetSetSize(server.el)) {
10077 errno = ERANGE;
10078 return REDISMODULE_ERR;
10079 }
10080
10081 if (!func || mask & ~(REDISMODULE_EVENTLOOP_READABLE |
10082 REDISMODULE_EVENTLOOP_WRITABLE)) {
10083 errno = EINVAL;
10084 return REDISMODULE_ERR;
10085 }
10086
10087 /* We are going to register stub callbacks to 'ae' for two reasons:
10088 *
10089 * - "ae" callback signature is different from RedisModuleEventLoopCallback,
10090 * that will be handled it in our stub callbacks.
10091 * - We need to remap 'mask' value to provide binary compatibility.
10092 *
10093 * For the stub callbacks, saving user 'callback' and 'user_data' in an
10094 * EventLoopData object and passing it to ae, later, we'll extract
10095 * 'callback' and 'user_data' from that.
10096 */
10097 EventLoopData *data = aeGetFileClientData(server.el, fd);
10098 if (!data)
10099 data = zcalloc(sizeof(*data));
10100
10101 aeFileProc *aeProc;
10102 if (mask & REDISMODULE_EVENTLOOP_READABLE)
10103 aeProc = eventLoopCbReadable;
10104 else
10105 aeProc = eventLoopCbWritable;
10106
10107 int aeMask = eventLoopToAeMask(mask);
10108
10109 if (aeCreateFileEvent(server.el, fd, aeMask, aeProc, data) != AE_OK) {
10110 if (aeGetFileEvents(server.el, fd) == AE_NONE)
10111 zfree(data);
10112 return REDISMODULE_ERR;
10113 }
10114
10115 data->user_data = user_data;
10116 if (mask & REDISMODULE_EVENTLOOP_READABLE)
10117 data->rFunc = func;
10118 if (mask & REDISMODULE_EVENTLOOP_WRITABLE)
10119 data->wFunc = func;
10120
10121 errno = 0;
10122 return REDISMODULE_OK;
10123}
10124
10125/* Delete a pipe / socket event from the event loop.
10126 *
10127 * * `mask` must be one of the following values:
10128 *
10129 * * `REDISMODULE_EVENTLOOP_READABLE`
10130 * * `REDISMODULE_EVENTLOOP_WRITABLE`
10131 * * `REDISMODULE_EVENTLOOP_READABLE | REDISMODULE_EVENTLOOP_WRITABLE`
10132 *
10133 * On success REDISMODULE_OK is returned, otherwise
10134 * REDISMODULE_ERR is returned and errno is set to the following values:
10135 *
10136 * * ERANGE: `fd` is negative or higher than `maxclients` Redis config.
10137 * * EINVAL: `mask` value is invalid.
10138 */
10139int RM_EventLoopDel(int fd, int mask) {
10140 if (fd < 0 || fd >= aeGetSetSize(server.el)) {
10141 errno = ERANGE;
10142 return REDISMODULE_ERR;
10143 }
10144
10145 if (mask & ~(REDISMODULE_EVENTLOOP_READABLE |
10146 REDISMODULE_EVENTLOOP_WRITABLE)) {
10147 errno = EINVAL;
10148 return REDISMODULE_ERR;
10149 }
10150
10151 /* After deleting the event, if fd does not have any registered event
10152 * anymore, we can free the EventLoopData object. */
10153 EventLoopData *data = aeGetFileClientData(server.el, fd);
10154 aeDeleteFileEvent(server.el, fd, eventLoopToAeMask(mask));
10155 if (aeGetFileEvents(server.el, fd) == AE_NONE)
10156 zfree(data);
10157
10158 errno = 0;
10159 return REDISMODULE_OK;
10160}
10161
10162/* This function can be called from other threads to trigger callback on Redis
10163 * main thread. On success REDISMODULE_OK is returned. If `func` is NULL
10164 * REDISMODULE_ERR is returned and errno is set to EINVAL.
10165 */
10166int RM_EventLoopAddOneShot(RedisModuleEventLoopOneShotFunc func, void *user_data) {
10167 if (!func) {
10168 errno = EINVAL;
10169 return REDISMODULE_ERR;
10170 }
10171
10172 EventLoopOneShot *oneshot = zmalloc(sizeof(*oneshot));
10173 oneshot->func = func;
10174 oneshot->user_data = user_data;
10175
10176 pthread_mutex_lock(&moduleEventLoopMutex);
10177 if (!moduleEventLoopOneShots) moduleEventLoopOneShots = listCreate();
10178 listAddNodeTail(moduleEventLoopOneShots, oneshot);
10179 pthread_mutex_unlock(&moduleEventLoopMutex);
10180
10181 if (write(server.module_pipe[1],"A",1) != 1) {
10182 /* Pipe is non-blocking, write() may fail if it's full. */
10183 }
10184
10185 errno = 0;
10186 return REDISMODULE_OK;
10187}
10188
10189/* This function will check the moduleEventLoopOneShots queue in order to
10190 * call the callback for the registered oneshot events. */
10191static void eventLoopHandleOneShotEvents(void) {
10192 pthread_mutex_lock(&moduleEventLoopMutex);
10193 if (moduleEventLoopOneShots) {
10194 while (listLength(moduleEventLoopOneShots)) {
10195 listNode *ln = listFirst(moduleEventLoopOneShots);
10196 EventLoopOneShot *oneshot = ln->value;
10197 listDelNode(moduleEventLoopOneShots, ln);
10198 /* Unlock mutex before the callback. Another oneshot event can be
10199 * added in the callback, it will need to lock the mutex. */
10200 pthread_mutex_unlock(&moduleEventLoopMutex);
10201 oneshot->func(oneshot->user_data);
10202 zfree(oneshot);
10203 /* Lock again for the next iteration */
10204 pthread_mutex_lock(&moduleEventLoopMutex);
10205 }
10206 }
10207 pthread_mutex_unlock(&moduleEventLoopMutex);
10208}
10209
10210/* --------------------------------------------------------------------------
10211 * ## Modules ACL API
10212 *
10213 * Implements a hook into the authentication and authorization within Redis.
10214 * --------------------------------------------------------------------------*/
10215
10216/* This function is called when a client's user has changed and invokes the
10217 * client's user changed callback if it was set. This callback should
10218 * cleanup any state the module was tracking about this client.
10219 *
10220 * A client's user can be changed through the AUTH command, module
10221 * authentication, and when a client is freed. */
10222void moduleNotifyUserChanged(client *c) {
10223 if (c->auth_callback) {
10224 c->auth_callback(c->id, c->auth_callback_privdata);
10225
10226 /* The callback will fire exactly once, even if the user remains
10227 * the same. It is expected to completely clean up the state
10228 * so all references are cleared here. */
10229 c->auth_callback = NULL;
10230 c->auth_callback_privdata = NULL;
10231 c->auth_module = NULL;
10232 }
10233}
10234
10235void revokeClientAuthentication(client *c) {
10236 /* Freeing the client would result in moduleNotifyUserChanged() to be
10237 * called later, however since we use revokeClientAuthentication() also
10238 * in moduleFreeAuthenticatedClients() to implement module unloading, we
10239 * do this action ASAP: this way if the module is unloaded, when the client
10240 * is eventually freed we don't rely on the module to still exist. */
10241 moduleNotifyUserChanged(c);
10242
10243 deauthenticateAndCloseClient(c);
10244}
10245
10246/* Cleanup all clients that have been authenticated with this module. This
10247 * is called from onUnload() to give the module a chance to cleanup any
10248 * resources associated with clients it has authenticated. */
10249static void moduleFreeAuthenticatedClients(RedisModule *module) {
10250 listIter li;
10251 listNode *ln;
10252 listRewind(server.clients,&li);
10253 while ((ln = listNext(&li)) != NULL) {
10254 client *c = listNodeValue(ln);
10255 if (!c->auth_module) continue;
10256
10257 RedisModule *auth_module = (RedisModule *) c->auth_module;
10258 if (auth_module == module) {
10259 revokeClientAuthentication(c);
10260 }
10261 }
10262}
10263
10264/* Creates a Redis ACL user that the module can use to authenticate a client.
10265 * After obtaining the user, the module should set what such user can do
10266 * using the RM_SetUserACL() function. Once configured, the user
10267 * can be used in order to authenticate a connection, with the specified
10268 * ACL rules, using the RedisModule_AuthClientWithUser() function.
10269 *
10270 * Note that:
10271 *
10272 * * Users created here are not listed by the ACL command.
10273 * * Users created here are not checked for duplicated name, so it's up to
10274 * the module calling this function to take care of not creating users
10275 * with the same name.
10276 * * The created user can be used to authenticate multiple Redis connections.
10277 *
10278 * The caller can later free the user using the function
10279 * RM_FreeModuleUser(). When this function is called, if there are
10280 * still clients authenticated with this user, they are disconnected.
10281 * The function to free the user should only be used when the caller really
10282 * wants to invalidate the user to define a new one with different
10283 * capabilities. */
10284RedisModuleUser *RM_CreateModuleUser(const char *name) {
10285 RedisModuleUser *new_user = zmalloc(sizeof(RedisModuleUser));
10286 new_user->user = ACLCreateUnlinkedUser();
10287 new_user->free_user = 1;
10288
10289 /* Free the previous temporarily assigned name to assign the new one */
10290 sdsfree(new_user->user->name);
10291 new_user->user->name = sdsnew(name);
10292 return new_user;
10293}
10294
10295/* Frees a given user and disconnects all of the clients that have been
10296 * authenticated with it. See RM_CreateModuleUser for detailed usage.*/
10297int RM_FreeModuleUser(RedisModuleUser *user) {
10298 if (user->free_user)
10299 ACLFreeUserAndKillClients(user->user);
10300 zfree(user);
10301 return REDISMODULE_OK;
10302}
10303
10304/* Sets the permissions of a user created through the redis module
10305 * interface. The syntax is the same as ACL SETUSER, so refer to the
10306 * documentation in acl.c for more information. See RM_CreateModuleUser
10307 * for detailed usage.
10308 *
10309 * Returns REDISMODULE_OK on success and REDISMODULE_ERR on failure
10310 * and will set an errno describing why the operation failed. */
10311int RM_SetModuleUserACL(RedisModuleUser *user, const char* acl) {
10312 return ACLSetUser(user->user, acl, -1);
10313}
10314
10315/* Sets the permission of a user with a complete ACL string, such as one
10316 * would use on the redis ACL SETUSER command line API. This differs from
10317 * RM_SetModuleUserACL, which only takes single ACL operations at a time.
10318 *
10319 * Returns REDISMODULE_OK on success and REDISMODULE_ERR on failure
10320 * if a RedisModuleString is provided in error, a string describing the error
10321 * will be returned */
10322int RM_SetModuleUserACLString(RedisModuleCtx *ctx, RedisModuleUser *user, const char *acl, RedisModuleString **error) {
10323 serverAssert(user != NULL);
10324
10325 int argc;
10326 sds *argv = sdssplitargs(acl, &argc);
10327
10328 sds err = ACLStringSetUser(user->user, NULL, argv, argc);
10329
10330 sdsfreesplitres(argv, argc);
10331
10332 if (err) {
10333 if (error) {
10334 *error = createObject(OBJ_STRING, err);
10335 if (ctx != NULL) autoMemoryAdd(ctx, REDISMODULE_AM_STRING, *error);
10336 } else {
10337 sdsfree(err);
10338 }
10339
10340 return REDISMODULE_ERR;
10341 }
10342
10343 return REDISMODULE_OK;
10344}
10345
10346/* Get the ACL string for a given user
10347 * Returns a RedisModuleString
10348 */
10349RedisModuleString *RM_GetModuleUserACLString(RedisModuleUser *user) {
10350 serverAssert(user != NULL);
10351
10352 return ACLDescribeUser(user->user);
10353}
10354
10355/* Retrieve the user name of the client connection behind the current context.
10356 * The user name can be used later, in order to get a RedisModuleUser.
10357 * See more information in RM_GetModuleUserFromUserName.
10358 *
10359 * The returned string must be released with RedisModule_FreeString() or by
10360 * enabling automatic memory management. */
10361RedisModuleString *RM_GetCurrentUserName(RedisModuleCtx *ctx) {
10362 /* Sometimes, the user isn't passed along the call stack or isn't
10363 * even set, so we need to check for the members to avoid crashes. */
10364 if (ctx->client == NULL || ctx->client->user == NULL || ctx->client->user->name == NULL) {
10365 return NULL;
10366 }
10367
10368 return RM_CreateString(ctx,ctx->client->user->name,sdslen(ctx->client->user->name));
10369}
10370
10371/* A RedisModuleUser can be used to check if command, key or channel can be executed or
10372 * accessed according to the ACLs rules associated with that user.
10373 * When a Module wants to do ACL checks on a general ACL user (not created by RM_CreateModuleUser),
10374 * it can get the RedisModuleUser from this API, based on the user name retrieved by RM_GetCurrentUserName.
10375 *
10376 * Since a general ACL user can be deleted at any time, this RedisModuleUser should be used only in the context
10377 * where this function was called. In order to do ACL checks out of that context, the Module can store the user name,
10378 * and call this API at any other context.
10379 *
10380 * Returns NULL if the user is disabled or the user does not exist.
10381 * The caller should later free the user using the function RM_FreeModuleUser().*/
10382RedisModuleUser *RM_GetModuleUserFromUserName(RedisModuleString *name) {
10383 /* First, verify that the user exist */
10384 user *acl_user = ACLGetUserByName(name->ptr, sdslen(name->ptr));
10385 if (acl_user == NULL) {
10386 return NULL;
10387 }
10388
10389 RedisModuleUser *new_user = zmalloc(sizeof(RedisModuleUser));
10390 new_user->user = acl_user;
10391 new_user->free_user = 0;
10392 return new_user;
10393}
10394
10395/* Checks if the command can be executed by the user, according to the ACLs associated with it.
10396 *
10397 * On success a REDISMODULE_OK is returned, otherwise
10398 * REDISMODULE_ERR is returned and errno is set to the following values:
10399 *
10400 * * ENOENT: Specified command does not exist.
10401 * * EACCES: Command cannot be executed, according to ACL rules
10402 */
10403int RM_ACLCheckCommandPermissions(RedisModuleUser *user, RedisModuleString **argv, int argc) {
10404 int keyidxptr;
10405 struct redisCommand *cmd;
10406
10407 /* Find command */
10408 if ((cmd = lookupCommand(argv, argc)) == NULL) {
10409 errno = ENOENT;
10410 return REDISMODULE_ERR;
10411 }
10412
10413 if (ACLCheckAllUserCommandPerm(user->user, cmd, argv, argc, NULL, &keyidxptr) != ACL_OK) {
10414 errno = EACCES;
10415 return REDISMODULE_ERR;
10416 }
10417
10418 return REDISMODULE_OK;
10419}
10420
10421/* Check if the key can be accessed by the user according to the ACLs attached to the user
10422 * and the flags representing the key access. The flags are the same that are used in the
10423 * keyspec for logical operations. These flags are documented in RedisModule_SetCommandInfo as
10424 * the REDISMODULE_CMD_KEY_ACCESS, REDISMODULE_CMD_KEY_UPDATE, REDISMODULE_CMD_KEY_INSERT,
10425 * and REDISMODULE_CMD_KEY_DELETE flags.
10426 *
10427 * If no flags are supplied, the user is still required to have some access to the key for
10428 * this command to return successfully.
10429 *
10430 * If the user is able to access the key then REDISMODULE_OK is returned, otherwise
10431 * REDISMODULE_ERR is returned and errno is set to one of the following values:
10432 *
10433 * * EINVAL: The provided flags are invalid.
10434 * * EACCESS: The user does not have permission to access the key.
10435 */
10436int RM_ACLCheckKeyPermissions(RedisModuleUser *user, RedisModuleString *key, int flags) {
10437 const int allow_mask = (REDISMODULE_CMD_KEY_ACCESS
10438 | REDISMODULE_CMD_KEY_INSERT
10439 | REDISMODULE_CMD_KEY_DELETE
10440 | REDISMODULE_CMD_KEY_UPDATE);
10441
10442 if ((flags & allow_mask) != flags) {
10443 errno = EINVAL;
10444 return REDISMODULE_ERR;
10445 }
10446
10447 int keyspec_flags = moduleConvertKeySpecsFlags(flags, 0);
10448 if (ACLUserCheckKeyPerm(user->user, key->ptr, sdslen(key->ptr), keyspec_flags) != ACL_OK) {
10449 errno = EACCES;
10450 return REDISMODULE_ERR;
10451 }
10452
10453 return REDISMODULE_OK;
10454}
10455
10456/* Check if the user can access keys matching the given key prefix according to the ACLs
10457 * attached to the user and the flags representing key access. The flags are the same that
10458 * are used in the keyspec for logical operations. These flags are documented in
10459 * RedisModule_SetCommandInfo as the REDISMODULE_CMD_KEY_ACCESS,
10460 * REDISMODULE_CMD_KEY_UPDATE, REDISMODULE_CMD_KEY_INSERT, and REDISMODULE_CMD_KEY_DELETE flags.
10461 *
10462 * If no flags are supplied, the user is still required to have some access to keys matching
10463 * the prefix for this command to return successfully.
10464 *
10465 * If the user is able to access keys matching the prefix, then REDISMODULE_OK is returned.
10466 * Otherwise, REDISMODULE_ERR is returned and errno is set to one of the following values:
10467 *
10468 * * EINVAL: The provided flags are invalid.
10469 * * EACCES: The user does not have permission to access keys matching the prefix.
10470 */
10471int RM_ACLCheckKeyPrefixPermissions(RedisModuleUser *user, RedisModuleString *prefix, int flags) {
10472 const int allow_mask = (REDISMODULE_CMD_KEY_ACCESS
10473 | REDISMODULE_CMD_KEY_INSERT
10474 | REDISMODULE_CMD_KEY_DELETE
10475 | REDISMODULE_CMD_KEY_UPDATE);
10476
10477 if ((flags & allow_mask) != flags) {
10478 errno = EINVAL;
10479 return REDISMODULE_ERR;
10480 }
10481
10482 int keyspec_flags = moduleConvertKeySpecsFlags(flags, 0);
10483
10484 /* Add the prefix flag to the keyspec flags */
10485 keyspec_flags |= CMD_KEY_PREFIX;
10486
10487 if (ACLUserCheckKeyPerm(user->user, prefix->ptr, sdslen(prefix->ptr), keyspec_flags) != ACL_OK) {
10488 errno = EACCES;
10489 return REDISMODULE_ERR;
10490 }
10491
10492 return REDISMODULE_OK;
10493}
10494
10495/* Check if the pubsub channel can be accessed by the user based off of the given
10496 * access flags. See RM_ChannelAtPosWithFlags for more information about the
10497 * possible flags that can be passed in.
10498 *
10499 * If the user is able to access the pubsub channel then REDISMODULE_OK is returned, otherwise
10500 * REDISMODULE_ERR is returned and errno is set to one of the following values:
10501 *
10502 * * EINVAL: The provided flags are invalid.
10503 * * EACCESS: The user does not have permission to access the pubsub channel.
10504 */
10505int RM_ACLCheckChannelPermissions(RedisModuleUser *user, RedisModuleString *ch, int flags) {
10506 const int allow_mask = (REDISMODULE_CMD_CHANNEL_PUBLISH
10507 | REDISMODULE_CMD_CHANNEL_SUBSCRIBE
10508 | REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE
10509 | REDISMODULE_CMD_CHANNEL_PATTERN);
10510
10511 if ((flags & allow_mask) != flags) {
10512 errno = EINVAL;
10513 return REDISMODULE_ERR;
10514 }
10515
10516 /* Unsubscribe permissions are currently always allowed. */
10517 if (flags & REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE){
10518 return REDISMODULE_OK;
10519 }
10520
10521 int is_pattern = flags & REDISMODULE_CMD_CHANNEL_PATTERN;
10522 if (ACLUserCheckChannelPerm(user->user, ch->ptr, is_pattern) != ACL_OK)
10523 return REDISMODULE_ERR;
10524
10525 return REDISMODULE_OK;
10526}
10527
10528/* Helper function to map a RedisModuleACLLogEntryReason to ACL Log entry reason. */
10529int moduleGetACLLogEntryReason(RedisModuleACLLogEntryReason reason) {
10530 int acl_reason = 0;
10531 switch (reason) {
10532 case REDISMODULE_ACL_LOG_AUTH: acl_reason = ACL_DENIED_AUTH; break;
10533 case REDISMODULE_ACL_LOG_KEY: acl_reason = ACL_DENIED_KEY; break;
10534 case REDISMODULE_ACL_LOG_CHANNEL: acl_reason = ACL_DENIED_CHANNEL; break;
10535 case REDISMODULE_ACL_LOG_CMD: acl_reason = ACL_DENIED_CMD; break;
10536 default: break;
10537 }
10538 return acl_reason;
10539}
10540
10541/* Adds a new entry in the ACL log.
10542 * Returns REDISMODULE_OK on success and REDISMODULE_ERR on error.
10543 *
10544 * For more information about ACL log, please refer to https://redis.io/commands/acl-log */
10545int RM_ACLAddLogEntry(RedisModuleCtx *ctx, RedisModuleUser *user, RedisModuleString *object, RedisModuleACLLogEntryReason reason) {
10546 int acl_reason = moduleGetACLLogEntryReason(reason);
10547 if (!acl_reason) return REDISMODULE_ERR;
10548 addACLLogEntry(ctx->client, acl_reason, ACL_LOG_CTX_MODULE, -1, user->user->name, sdsdup(object->ptr));
10549 return REDISMODULE_OK;
10550}
10551
10552/* Adds a new entry in the ACL log with the `username` RedisModuleString provided.
10553 * Returns REDISMODULE_OK on success and REDISMODULE_ERR on error.
10554 *
10555 * For more information about ACL log, please refer to https://redis.io/commands/acl-log */
10556int RM_ACLAddLogEntryByUserName(RedisModuleCtx *ctx, RedisModuleString *username, RedisModuleString *object, RedisModuleACLLogEntryReason reason) {
10557 int acl_reason = moduleGetACLLogEntryReason(reason);
10558 if (!acl_reason) return REDISMODULE_ERR;
10559 addACLLogEntry(ctx->client, acl_reason, ACL_LOG_CTX_MODULE, -1, username->ptr, sdsdup(object->ptr));
10560 return REDISMODULE_OK;
10561}
10562
10563/* Authenticate the client associated with the context with
10564 * the provided user. Returns REDISMODULE_OK on success and
10565 * REDISMODULE_ERR on error.
10566 *
10567 * This authentication can be tracked with the optional callback and private
10568 * data fields. The callback will be called whenever the user of the client
10569 * changes. This callback should be used to cleanup any state that is being
10570 * kept in the module related to the client authentication. It will only be
10571 * called once, even when the user hasn't changed, in order to allow for a
10572 * new callback to be specified. If this authentication does not need to be
10573 * tracked, pass in NULL for the callback and privdata.
10574 *
10575 * If client_id is not NULL, it will be filled with the id of the client
10576 * that was authenticated. This can be used with the
10577 * RM_DeauthenticateAndCloseClient() API in order to deauthenticate a
10578 * previously authenticated client if the authentication is no longer valid.
10579 *
10580 * For expensive authentication operations, it is recommended to block the
10581 * client and do the authentication in the background and then attach the user
10582 * to the client in a threadsafe context. */
10583static int authenticateClientWithUser(RedisModuleCtx *ctx, user *user, RedisModuleUserChangedFunc callback, void *privdata, uint64_t *client_id) {
10584 if (user->flags & USER_FLAG_DISABLED) {
10585 return REDISMODULE_ERR;
10586 }
10587
10588 /* Avoid settings which are meaningless and will be lost */
10589 if (!ctx->client || (ctx->client->flags & CLIENT_MODULE)) {
10590 return REDISMODULE_ERR;
10591 }
10592
10593 moduleNotifyUserChanged(ctx->client);
10594
10595 ctx->client->user = user;
10596 ctx->client->authenticated = 1;
10597
10598 if (clientHasModuleAuthInProgress(ctx->client)) {
10599 ctx->client->flags |= CLIENT_MODULE_AUTH_HAS_RESULT;
10600 }
10601
10602 if (callback) {
10603 ctx->client->auth_callback = callback;
10604 ctx->client->auth_callback_privdata = privdata;
10605 ctx->client->auth_module = ctx->module;
10606 }
10607
10608 if (client_id) {
10609 *client_id = ctx->client->id;
10610 }
10611
10612 return REDISMODULE_OK;
10613}
10614
10615
10616/* Authenticate the current context's user with the provided redis acl user.
10617 * Returns REDISMODULE_ERR if the user is disabled.
10618 *
10619 * See authenticateClientWithUser for information about callback, client_id,
10620 * and general usage for authentication. */
10621int RM_AuthenticateClientWithUser(RedisModuleCtx *ctx, RedisModuleUser *module_user, RedisModuleUserChangedFunc callback, void *privdata, uint64_t *client_id) {
10622 return authenticateClientWithUser(ctx, module_user->user, callback, privdata, client_id);
10623}
10624
10625/* Authenticate the current context's user with the provided redis acl user.
10626 * Returns REDISMODULE_ERR if the user is disabled or the user does not exist.
10627 *
10628 * See authenticateClientWithUser for information about callback, client_id,
10629 * and general usage for authentication. */
10630int RM_AuthenticateClientWithACLUser(RedisModuleCtx *ctx, const char *name, size_t len, RedisModuleUserChangedFunc callback, void *privdata, uint64_t *client_id) {
10631 user *acl_user = ACLGetUserByName(name, len);
10632
10633 if (!acl_user) {
10634 return REDISMODULE_ERR;
10635 }
10636 return authenticateClientWithUser(ctx, acl_user, callback, privdata, client_id);
10637}
10638
10639/* Deauthenticate and close the client. The client resources will not be
10640 * immediately freed, but will be cleaned up in a background job. This is
10641 * the recommended way to deauthenticate a client since most clients can't
10642 * handle users becoming deauthenticated. Returns REDISMODULE_ERR when the
10643 * client doesn't exist and REDISMODULE_OK when the operation was successful.
10644 *
10645 * The client ID is returned from the RM_AuthenticateClientWithUser and
10646 * RM_AuthenticateClientWithACLUser APIs, but can be obtained through
10647 * the CLIENT api or through server events.
10648 *
10649 * This function is not thread safe, and must be executed within the context
10650 * of a command or thread safe context. */
10651int RM_DeauthenticateAndCloseClient(RedisModuleCtx *ctx, uint64_t client_id) {
10652 UNUSED(ctx);
10653 client *c = lookupClientByID(client_id);
10654 if (c == NULL) return REDISMODULE_ERR;
10655
10656 /* Revoke also marks client to be closed ASAP */
10657 revokeClientAuthentication(c);
10658 return REDISMODULE_OK;
10659}
10660
10661/* Redact the client command argument specified at the given position. Redacted arguments
10662 * are obfuscated in user facing commands such as SLOWLOG or MONITOR, as well as
10663 * never being written to server logs. This command may be called multiple times on the
10664 * same position.
10665 *
10666 * Note that the command name, position 0, can not be redacted.
10667 *
10668 * Returns REDISMODULE_OK if the argument was redacted and REDISMODULE_ERR if there
10669 * was an invalid parameter passed in or the position is outside the client
10670 * argument range. */
10671int RM_RedactClientCommandArgument(RedisModuleCtx *ctx, int pos) {
10672 if (!ctx || !ctx->client || pos <= 0 || ctx->client->argc <= pos) {
10673 return REDISMODULE_ERR;
10674 }
10675 redactClientCommandArgument(ctx->client, pos);
10676 return REDISMODULE_OK;
10677}
10678
10679/* Return the X.509 client-side certificate used by the client to authenticate
10680 * this connection.
10681 *
10682 * The return value is an allocated RedisModuleString that is a X.509 certificate
10683 * encoded in PEM (Base64) format. It should be freed (or auto-freed) by the caller.
10684 *
10685 * A NULL value is returned in the following conditions:
10686 *
10687 * - Connection ID does not exist
10688 * - Connection is not a TLS connection
10689 * - Connection is a TLS connection but no client certificate was used
10690 */
10691RedisModuleString *RM_GetClientCertificate(RedisModuleCtx *ctx, uint64_t client_id) {
10692 client *c = lookupClientByID(client_id);
10693 if (c == NULL) return NULL;
10694
10695 sds cert = connGetPeerCert(c->conn);
10696 if (!cert) return NULL;
10697
10698 RedisModuleString *s = createObject(OBJ_STRING, cert);
10699 if (ctx != NULL) autoMemoryAdd(ctx, REDISMODULE_AM_STRING, s);
10700
10701 return s;
10702}
10703
10704/* --------------------------------------------------------------------------
10705 * ## Modules Dictionary API
10706 *
10707 * Implements a sorted dictionary (actually backed by a radix tree) with
10708 * the usual get / set / del / num-items API, together with an iterator
10709 * capable of going back and forth.
10710 * -------------------------------------------------------------------------- */
10711
10712/* Create a new dictionary. The 'ctx' pointer can be the current module context
10713 * or NULL, depending on what you want. Please follow the following rules:
10714 *
10715 * 1. Use a NULL context if you plan to retain a reference to this dictionary
10716 * that will survive the time of the module callback where you created it.
10717 * 2. Use a NULL context if no context is available at the time you are creating
10718 * the dictionary (of course...).
10719 * 3. However use the current callback context as 'ctx' argument if the
10720 * dictionary time to live is just limited to the callback scope. In this
10721 * case, if enabled, you can enjoy the automatic memory management that will
10722 * reclaim the dictionary memory, as well as the strings returned by the
10723 * Next / Prev dictionary iterator calls.
10724 */
10725RedisModuleDict *RM_CreateDict(RedisModuleCtx *ctx) {
10726 struct RedisModuleDict *d = zmalloc(sizeof(*d));
10727 d->rax = raxNew();
10728 if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_DICT,d);
10729 return d;
10730}
10731
10732/* Free a dictionary created with RM_CreateDict(). You need to pass the
10733 * context pointer 'ctx' only if the dictionary was created using the
10734 * context instead of passing NULL. */
10735void RM_FreeDict(RedisModuleCtx *ctx, RedisModuleDict *d) {
10736 if (ctx != NULL) autoMemoryFreed(ctx,REDISMODULE_AM_DICT,d);
10737 raxFree(d->rax);
10738 zfree(d);
10739}
10740
10741/* Return the size of the dictionary (number of keys). */
10742uint64_t RM_DictSize(RedisModuleDict *d) {
10743 return raxSize(d->rax);
10744}
10745
10746/* Store the specified key into the dictionary, setting its value to the
10747 * pointer 'ptr'. If the key was added with success, since it did not
10748 * already exist, REDISMODULE_OK is returned. Otherwise if the key already
10749 * exists the function returns REDISMODULE_ERR. */
10750int RM_DictSetC(RedisModuleDict *d, void *key, size_t keylen, void *ptr) {
10751 int retval = raxTryInsert(d->rax,key,keylen,ptr,NULL);
10752 return (retval == 1) ? REDISMODULE_OK : REDISMODULE_ERR;
10753}
10754
10755/* Like RedisModule_DictSetC() but will replace the key with the new
10756 * value if the key already exists. */
10757int RM_DictReplaceC(RedisModuleDict *d, void *key, size_t keylen, void *ptr) {
10758 int retval = raxInsert(d->rax,key,keylen,ptr,NULL);
10759 return (retval == 1) ? REDISMODULE_OK : REDISMODULE_ERR;
10760}
10761
10762/* Like RedisModule_DictSetC() but takes the key as a RedisModuleString. */
10763int RM_DictSet(RedisModuleDict *d, RedisModuleString *key, void *ptr) {
10764 return RM_DictSetC(d,key->ptr,sdslen(key->ptr),ptr);
10765}
10766
10767/* Like RedisModule_DictReplaceC() but takes the key as a RedisModuleString. */
10768int RM_DictReplace(RedisModuleDict *d, RedisModuleString *key, void *ptr) {
10769 return RM_DictReplaceC(d,key->ptr,sdslen(key->ptr),ptr);
10770}
10771
10772/* Return the value stored at the specified key. The function returns NULL
10773 * both in the case the key does not exist, or if you actually stored
10774 * NULL at key. So, optionally, if the 'nokey' pointer is not NULL, it will
10775 * be set by reference to 1 if the key does not exist, or to 0 if the key
10776 * exists. */
10777void *RM_DictGetC(RedisModuleDict *d, void *key, size_t keylen, int *nokey) {
10778 void *res = NULL;
10779 int found = raxFind(d->rax,key,keylen,&res);
10780 if (nokey) *nokey = !found;
10781 return res;
10782}
10783
10784/* Like RedisModule_DictGetC() but takes the key as a RedisModuleString. */
10785void *RM_DictGet(RedisModuleDict *d, RedisModuleString *key, int *nokey) {
10786 return RM_DictGetC(d,key->ptr,sdslen(key->ptr),nokey);
10787}
10788
10789/* Remove the specified key from the dictionary, returning REDISMODULE_OK if
10790 * the key was found and deleted, or REDISMODULE_ERR if instead there was
10791 * no such key in the dictionary. When the operation is successful, if
10792 * 'oldval' is not NULL, then '*oldval' is set to the value stored at the
10793 * key before it was deleted. Using this feature it is possible to get
10794 * a pointer to the value (for instance in order to release it), without
10795 * having to call RedisModule_DictGet() before deleting the key. */
10796int RM_DictDelC(RedisModuleDict *d, void *key, size_t keylen, void *oldval) {
10797 int retval = raxRemove(d->rax,key,keylen,oldval);
10798 return retval ? REDISMODULE_OK : REDISMODULE_ERR;
10799}
10800
10801/* Like RedisModule_DictDelC() but gets the key as a RedisModuleString. */
10802int RM_DictDel(RedisModuleDict *d, RedisModuleString *key, void *oldval) {
10803 return RM_DictDelC(d,key->ptr,sdslen(key->ptr),oldval);
10804}
10805
10806/* Return an iterator, setup in order to start iterating from the specified
10807 * key by applying the operator 'op', which is just a string specifying the
10808 * comparison operator to use in order to seek the first element. The
10809 * operators available are:
10810 *
10811 * * `^` -- Seek the first (lexicographically smaller) key.
10812 * * `$` -- Seek the last (lexicographically bigger) key.
10813 * * `>` -- Seek the first element greater than the specified key.
10814 * * `>=` -- Seek the first element greater or equal than the specified key.
10815 * * `<` -- Seek the first element smaller than the specified key.
10816 * * `<=` -- Seek the first element smaller or equal than the specified key.
10817 * * `==` -- Seek the first element matching exactly the specified key.
10818 *
10819 * Note that for `^` and `$` the passed key is not used, and the user may
10820 * just pass NULL with a length of 0.
10821 *
10822 * If the element to start the iteration cannot be seeked based on the
10823 * key and operator passed, RedisModule_DictNext() / Prev() will just return
10824 * REDISMODULE_ERR at the first call, otherwise they'll produce elements.
10825 */
10826RedisModuleDictIter *RM_DictIteratorStartC(RedisModuleDict *d, const char *op, void *key, size_t keylen) {
10827 RedisModuleDictIter *di = zmalloc(sizeof(*di));
10828 di->dict = d;
10829 raxStart(&di->ri,d->rax);
10830 raxSeek(&di->ri,op,key,keylen);
10831 return di;
10832}
10833
10834/* Exactly like RedisModule_DictIteratorStartC, but the key is passed as a
10835 * RedisModuleString. */
10836RedisModuleDictIter *RM_DictIteratorStart(RedisModuleDict *d, const char *op, RedisModuleString *key) {
10837 return RM_DictIteratorStartC(d,op,key->ptr,sdslen(key->ptr));
10838}
10839
10840/* Release the iterator created with RedisModule_DictIteratorStart(). This call
10841 * is mandatory otherwise a memory leak is introduced in the module. */
10842void RM_DictIteratorStop(RedisModuleDictIter *di) {
10843 raxStop(&di->ri);
10844 zfree(di);
10845}
10846
10847/* After its creation with RedisModule_DictIteratorStart(), it is possible to
10848 * change the currently selected element of the iterator by using this
10849 * API call. The result based on the operator and key is exactly like
10850 * the function RedisModule_DictIteratorStart(), however in this case the
10851 * return value is just REDISMODULE_OK in case the seeked element was found,
10852 * or REDISMODULE_ERR in case it was not possible to seek the specified
10853 * element. It is possible to reseek an iterator as many times as you want. */
10854int RM_DictIteratorReseekC(RedisModuleDictIter *di, const char *op, void *key, size_t keylen) {
10855 return raxSeek(&di->ri,op,key,keylen);
10856}
10857
10858/* Like RedisModule_DictIteratorReseekC() but takes the key as a
10859 * RedisModuleString. */
10860int RM_DictIteratorReseek(RedisModuleDictIter *di, const char *op, RedisModuleString *key) {
10861 return RM_DictIteratorReseekC(di,op,key->ptr,sdslen(key->ptr));
10862}
10863
10864/* Return the current item of the dictionary iterator `di` and steps to the
10865 * next element. If the iterator already yield the last element and there
10866 * are no other elements to return, NULL is returned, otherwise a pointer
10867 * to a string representing the key is provided, and the `*keylen` length
10868 * is set by reference (if keylen is not NULL). The `*dataptr`, if not NULL
10869 * is set to the value of the pointer stored at the returned key as auxiliary
10870 * data (as set by the RedisModule_DictSet API).
10871 *
10872 * Usage example:
10873 *
10874 * ... create the iterator here ...
10875 * char *key;
10876 * void *data;
10877 * while((key = RedisModule_DictNextC(iter,&keylen,&data)) != NULL) {
10878 * printf("%.*s %p\n", (int)keylen, key, data);
10879 * }
10880 *
10881 * The returned pointer is of type void because sometimes it makes sense
10882 * to cast it to a `char*` sometimes to an unsigned `char*` depending on the
10883 * fact it contains or not binary data, so this API ends being more
10884 * comfortable to use.
10885 *
10886 * The validity of the returned pointer is until the next call to the
10887 * next/prev iterator step. Also the pointer is no longer valid once the
10888 * iterator is released. */
10889void *RM_DictNextC(RedisModuleDictIter *di, size_t *keylen, void **dataptr) {
10890 if (!raxNext(&di->ri)) return NULL;
10891 if (keylen) *keylen = di->ri.key_len;
10892 if (dataptr) *dataptr = di->ri.data;
10893 return di->ri.key;
10894}
10895
10896/* This function is exactly like RedisModule_DictNext() but after returning
10897 * the currently selected element in the iterator, it selects the previous
10898 * element (lexicographically smaller) instead of the next one. */
10899void *RM_DictPrevC(RedisModuleDictIter *di, size_t *keylen, void **dataptr) {
10900 if (!raxPrev(&di->ri)) return NULL;
10901 if (keylen) *keylen = di->ri.key_len;
10902 if (dataptr) *dataptr = di->ri.data;
10903 return di->ri.key;
10904}
10905
10906/* Like RedisModuleNextC(), but instead of returning an internally allocated
10907 * buffer and key length, it returns directly a module string object allocated
10908 * in the specified context 'ctx' (that may be NULL exactly like for the main
10909 * API RedisModule_CreateString).
10910 *
10911 * The returned string object should be deallocated after use, either manually
10912 * or by using a context that has automatic memory management active. */
10913RedisModuleString *RM_DictNext(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr) {
10914 size_t keylen;
10915 void *key = RM_DictNextC(di,&keylen,dataptr);
10916 if (key == NULL) return NULL;
10917 return RM_CreateString(ctx,key,keylen);
10918}
10919
10920/* Like RedisModule_DictNext() but after returning the currently selected
10921 * element in the iterator, it selects the previous element (lexicographically
10922 * smaller) instead of the next one. */
10923RedisModuleString *RM_DictPrev(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr) {
10924 size_t keylen;
10925 void *key = RM_DictPrevC(di,&keylen,dataptr);
10926 if (key == NULL) return NULL;
10927 return RM_CreateString(ctx,key,keylen);
10928}
10929
10930/* Compare the element currently pointed by the iterator to the specified
10931 * element given by key/keylen, according to the operator 'op' (the set of
10932 * valid operators are the same valid for RedisModule_DictIteratorStart).
10933 * If the comparison is successful the command returns REDISMODULE_OK
10934 * otherwise REDISMODULE_ERR is returned.
10935 *
10936 * This is useful when we want to just emit a lexicographical range, so
10937 * in the loop, as we iterate elements, we can also check if we are still
10938 * on range.
10939 *
10940 * The function return REDISMODULE_ERR if the iterator reached the
10941 * end of elements condition as well. */
10942int RM_DictCompareC(RedisModuleDictIter *di, const char *op, void *key, size_t keylen) {
10943 if (raxEOF(&di->ri)) return REDISMODULE_ERR;
10944 int res = raxCompare(&di->ri,op,key,keylen);
10945 return res ? REDISMODULE_OK : REDISMODULE_ERR;
10946}
10947
10948/* Like RedisModule_DictCompareC but gets the key to compare with the current
10949 * iterator key as a RedisModuleString. */
10950int RM_DictCompare(RedisModuleDictIter *di, const char *op, RedisModuleString *key) {
10951 if (raxEOF(&di->ri)) return REDISMODULE_ERR;
10952 int res = raxCompare(&di->ri,op,key->ptr,sdslen(key->ptr));
10953 return res ? REDISMODULE_OK : REDISMODULE_ERR;
10954}
10955
10956
10957
10958
10959/* --------------------------------------------------------------------------
10960 * ## Modules Info fields
10961 * -------------------------------------------------------------------------- */
10962
10963int RM_InfoEndDictField(RedisModuleInfoCtx *ctx);
10964
10965/* Used to start a new section, before adding any fields. the section name will
10966 * be prefixed by `<modulename>_` and must only include A-Z,a-z,0-9.
10967 * NULL or empty string indicates the default section (only `<modulename>`) is used.
10968 * When return value is REDISMODULE_ERR, the section should and will be skipped. */
10969int RM_InfoAddSection(RedisModuleInfoCtx *ctx, const char *name) {
10970 sds full_name = sdsdup(ctx->module->name);
10971 if (name != NULL && strlen(name) > 0)
10972 full_name = sdscatfmt(full_name, "_%s", name);
10973
10974 /* Implicitly end dicts, instead of returning an error which is likely un checked. */
10975 if (ctx->in_dict_field)
10976 RM_InfoEndDictField(ctx);
10977
10978 /* proceed only if:
10979 * 1) no section was requested (emit all)
10980 * 2) the module name was requested (emit all)
10981 * 3) this specific section was requested. */
10982 if (ctx->requested_sections) {
10983 if ((!full_name || !dictFind(ctx->requested_sections, full_name)) &&
10984 (!dictFind(ctx->requested_sections, ctx->module->name)))
10985 {
10986 sdsfree(full_name);
10987 ctx->in_section = 0;
10988 return REDISMODULE_ERR;
10989 }
10990 }
10991 if (ctx->sections++) ctx->info = sdscat(ctx->info,"\r\n");
10992 ctx->info = sdscatfmt(ctx->info, "# %S\r\n", full_name);
10993 ctx->in_section = 1;
10994 sdsfree(full_name);
10995 return REDISMODULE_OK;
10996}
10997
10998/* Starts a dict field, similar to the ones in INFO KEYSPACE. Use normal
10999 * RedisModule_InfoAddField* functions to add the items to this field, and
11000 * terminate with RedisModule_InfoEndDictField. */
11001int RM_InfoBeginDictField(RedisModuleInfoCtx *ctx, const char *name) {
11002 if (!ctx->in_section)
11003 return REDISMODULE_ERR;
11004 /* Implicitly end dicts, instead of returning an error which is likely un checked. */
11005 if (ctx->in_dict_field)
11006 RM_InfoEndDictField(ctx);
11007 char *tmpmodname, *tmpname;
11008 ctx->info = sdscatfmt(ctx->info,
11009 "%s_%s:",
11010 getSafeInfoString(ctx->module->name, strlen(ctx->module->name), &tmpmodname),
11011 getSafeInfoString(name, strlen(name), &tmpname));
11012 if (tmpmodname != NULL) zfree(tmpmodname);
11013 if (tmpname != NULL) zfree(tmpname);
11014 ctx->in_dict_field = 1;
11015 return REDISMODULE_OK;
11016}
11017
11018/* Ends a dict field, see RedisModule_InfoBeginDictField */
11019int RM_InfoEndDictField(RedisModuleInfoCtx *ctx) {
11020 if (!ctx->in_dict_field)
11021 return REDISMODULE_ERR;
11022 /* trim the last ',' if found. */
11023 if (ctx->info[sdslen(ctx->info)-1]==',')
11024 sdsIncrLen(ctx->info, -1);
11025 ctx->info = sdscat(ctx->info, "\r\n");
11026 ctx->in_dict_field = 0;
11027 return REDISMODULE_OK;
11028}
11029
11030/* Used by RedisModuleInfoFunc to add info fields.
11031 * Each field will be automatically prefixed by `<modulename>_`.
11032 * Field names or values must not include `\r\n` or `:`. */
11033int RM_InfoAddFieldString(RedisModuleInfoCtx *ctx, const char *field, RedisModuleString *value) {
11034 if (!ctx->in_section)
11035 return REDISMODULE_ERR;
11036 if (ctx->in_dict_field) {
11037 ctx->info = sdscatfmt(ctx->info,
11038 "%s=%S,",
11039 field,
11040 (sds)value->ptr);
11041 return REDISMODULE_OK;
11042 }
11043 ctx->info = sdscatfmt(ctx->info,
11044 "%s_%s:%S\r\n",
11045 ctx->module->name,
11046 field,
11047 (sds)value->ptr);
11048 return REDISMODULE_OK;
11049}
11050
11051/* See RedisModule_InfoAddFieldString(). */
11052int RM_InfoAddFieldCString(RedisModuleInfoCtx *ctx, const char *field, const char *value) {
11053 if (!ctx->in_section)
11054 return REDISMODULE_ERR;
11055 if (ctx->in_dict_field) {
11056 ctx->info = sdscatfmt(ctx->info,
11057 "%s=%s,",
11058 field,
11059 value);
11060 return REDISMODULE_OK;
11061 }
11062 ctx->info = sdscatfmt(ctx->info,
11063 "%s_%s:%s\r\n",
11064 ctx->module->name,
11065 field,
11066 value);
11067 return REDISMODULE_OK;
11068}
11069
11070/* See RedisModule_InfoAddFieldString(). */
11071int RM_InfoAddFieldDouble(RedisModuleInfoCtx *ctx, const char *field, double value) {
11072 if (!ctx->in_section)
11073 return REDISMODULE_ERR;
11074 if (ctx->in_dict_field) {
11075 ctx->info = sdscatprintf(ctx->info,
11076 "%s=%.17g,",
11077 field,
11078 value);
11079 return REDISMODULE_OK;
11080 }
11081 ctx->info = sdscatprintf(ctx->info,
11082 "%s_%s:%.17g\r\n",
11083 ctx->module->name,
11084 field,
11085 value);
11086 return REDISMODULE_OK;
11087}
11088
11089/* See RedisModule_InfoAddFieldString(). */
11090int RM_InfoAddFieldLongLong(RedisModuleInfoCtx *ctx, const char *field, long long value) {
11091 if (!ctx->in_section)
11092 return REDISMODULE_ERR;
11093 if (ctx->in_dict_field) {
11094 ctx->info = sdscatfmt(ctx->info,
11095 "%s=%I,",
11096 field,
11097 value);
11098 return REDISMODULE_OK;
11099 }
11100 ctx->info = sdscatfmt(ctx->info,
11101 "%s_%s:%I\r\n",
11102 ctx->module->name,
11103 field,
11104 value);
11105 return REDISMODULE_OK;
11106}
11107
11108/* See RedisModule_InfoAddFieldString(). */
11109int RM_InfoAddFieldULongLong(RedisModuleInfoCtx *ctx, const char *field, unsigned long long value) {
11110 if (!ctx->in_section)
11111 return REDISMODULE_ERR;
11112 if (ctx->in_dict_field) {
11113 ctx->info = sdscatfmt(ctx->info,
11114 "%s=%U,",
11115 field,
11116 value);
11117 return REDISMODULE_OK;
11118 }
11119 ctx->info = sdscatfmt(ctx->info,
11120 "%s_%s:%U\r\n",
11121 ctx->module->name,
11122 field,
11123 value);
11124 return REDISMODULE_OK;
11125}
11126
11127/* Registers callback for the INFO command. The callback should add INFO fields
11128 * by calling the `RedisModule_InfoAddField*()` functions. */
11129int RM_RegisterInfoFunc(RedisModuleCtx *ctx, RedisModuleInfoFunc cb) {
11130 ctx->module->info_cb = cb;
11131 return REDISMODULE_OK;
11132}
11133
11134sds modulesCollectInfo(sds info, dict *sections_dict, int for_crash_report, int sections) {
11135 dictIterator di;
11136 dictEntry *de;
11137
11138 dictInitIterator(&di, modules);
11139 while ((de = dictNext(&di)) != NULL) {
11140 struct RedisModule *module = dictGetVal(de);
11141 if (!module->info_cb)
11142 continue;
11143 RedisModuleInfoCtx info_ctx = {module, sections_dict, info, sections, 0, 0};
11144 module->info_cb(&info_ctx, for_crash_report);
11145 /* Implicitly end dicts (no way to handle errors, and we must add the newline). */
11146 if (info_ctx.in_dict_field)
11147 RM_InfoEndDictField(&info_ctx);
11148 info = info_ctx.info;
11149 sections = info_ctx.sections;
11150 }
11151 dictResetIterator(&di);
11152 return info;
11153}
11154
11155/* Get information about the server similar to the one that returns from the
11156 * INFO command. This function takes an optional 'section' argument that may
11157 * be NULL. The return value holds the output and can be used with
11158 * RedisModule_ServerInfoGetField and alike to get the individual fields.
11159 * When done, it needs to be freed with RedisModule_FreeServerInfo or with the
11160 * automatic memory management mechanism if enabled. */
11161RedisModuleServerInfoData *RM_GetServerInfo(RedisModuleCtx *ctx, const char *section) {
11162 struct RedisModuleServerInfoData *d = zmalloc(sizeof(*d));
11163 d->rax = raxNew();
11164 if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_INFO,d);
11165 int all = 0, everything = 0;
11166 robj *argv[1];
11167 argv[0] = section ? createStringObject(section, strlen(section)) : NULL;
11168 dict *section_dict = genInfoSectionDict(argv, section ? 1 : 0, NULL, &all, &everything);
11169 sds info = genRedisInfoString(section_dict, all, everything);
11170 int totlines, i;
11171 sds *lines = sdssplitlen(info, sdslen(info), "\r\n", 2, &totlines);
11172 for(i=0; i<totlines; i++) {
11173 sds line = lines[i];
11174 if (line[0]=='#') continue;
11175 char *sep = strchr(line, ':');
11176 if (!sep) continue;
11177 unsigned char *key = (unsigned char*)line;
11178 size_t keylen = (intptr_t)sep-(intptr_t)line;
11179 sds val = sdsnewlen(sep+1,sdslen(line)-((intptr_t)sep-(intptr_t)line)-1);
11180 if (!raxTryInsert(d->rax,key,keylen,val,NULL))
11181 sdsfree(val);
11182 }
11183 sdsfree(info);
11184 sdsfreesplitres(lines,totlines);
11185 releaseInfoSectionDict(section_dict);
11186 if(argv[0]) decrRefCount(argv[0]);
11187 return d;
11188}
11189
11190/* Free data created with RM_GetServerInfo(). You need to pass the
11191 * context pointer 'ctx' only if the dictionary was created using the
11192 * context instead of passing NULL. */
11193void RM_FreeServerInfo(RedisModuleCtx *ctx, RedisModuleServerInfoData *data) {
11194 if (ctx != NULL) autoMemoryFreed(ctx,REDISMODULE_AM_INFO,data);
11195 raxFreeWithCallback(data->rax, sdsfreegeneric);
11196 zfree(data);
11197}
11198
11199/* Get the value of a field from data collected with RM_GetServerInfo(). You
11200 * need to pass the context pointer 'ctx' only if you want to use auto memory
11201 * mechanism to release the returned string. Return value will be NULL if the
11202 * field was not found. */
11203RedisModuleString *RM_ServerInfoGetField(RedisModuleCtx *ctx, RedisModuleServerInfoData *data, const char* field) {
11204 void *result;
11205 if (!raxFind(data->rax, (unsigned char *)field, strlen(field), &result))
11206 return NULL;
11207 sds val = result;
11208 RedisModuleString *o = createStringObject(val,sdslen(val));
11209 if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
11210 return o;
11211}
11212
11213/* Similar to RM_ServerInfoGetField, but returns a char* which should not be freed but the caller. */
11214const char *RM_ServerInfoGetFieldC(RedisModuleServerInfoData *data, const char* field) {
11215 void *result = NULL;
11216 raxFind(data->rax, (unsigned char *)field, strlen(field), &result);
11217 return result;
11218}
11219
11220/* Get the value of a field from data collected with RM_GetServerInfo(). If the
11221 * field is not found, or is not numerical or out of range, return value will be
11222 * 0, and the optional out_err argument will be set to REDISMODULE_ERR. */
11223long long RM_ServerInfoGetFieldSigned(RedisModuleServerInfoData *data, const char* field, int *out_err) {
11224 long long ll;
11225 void *result;
11226 if (!raxFind(data->rax, (unsigned char *)field, strlen(field), &result)) {
11227 if (out_err) *out_err = REDISMODULE_ERR;
11228 return 0;
11229 }
11230 sds val = result;
11231 if (!string2ll(val,sdslen(val),&ll)) {
11232 if (out_err) *out_err = REDISMODULE_ERR;
11233 return 0;
11234 }
11235 if (out_err) *out_err = REDISMODULE_OK;
11236 return ll;
11237}
11238
11239/* Get the value of a field from data collected with RM_GetServerInfo(). If the
11240 * field is not found, or is not numerical or out of range, return value will be
11241 * 0, and the optional out_err argument will be set to REDISMODULE_ERR. */
11242unsigned long long RM_ServerInfoGetFieldUnsigned(RedisModuleServerInfoData *data, const char* field, int *out_err) {
11243 unsigned long long ll;
11244 void *result;
11245 if (!raxFind(data->rax, (unsigned char *)field, strlen(field), &result)) {
11246 if (out_err) *out_err = REDISMODULE_ERR;
11247 return 0;
11248 }
11249 sds val = result;
11250 if (!string2ull(val,&ll)) {
11251 if (out_err) *out_err = REDISMODULE_ERR;
11252 return 0;
11253 }
11254 if (out_err) *out_err = REDISMODULE_OK;
11255 return ll;
11256}
11257
11258/* Get the value of a field from data collected with RM_GetServerInfo(). If the
11259 * field is not found, or is not a double, return value will be 0, and the
11260 * optional out_err argument will be set to REDISMODULE_ERR. */
11261double RM_ServerInfoGetFieldDouble(RedisModuleServerInfoData *data, const char* field, int *out_err) {
11262 double dbl;
11263 void *result;
11264 if (!raxFind(data->rax, (unsigned char *)field, strlen(field), &result)) {
11265 if (out_err) *out_err = REDISMODULE_ERR;
11266 return 0;
11267 }
11268 sds val = result;
11269 if (!string2d(val,sdslen(val),&dbl)) {
11270 if (out_err) *out_err = REDISMODULE_ERR;
11271 return 0;
11272 }
11273 if (out_err) *out_err = REDISMODULE_OK;
11274 return dbl;
11275}
11276
11277/* --------------------------------------------------------------------------
11278 * ## Modules utility APIs
11279 * -------------------------------------------------------------------------- */
11280
11281/* Return random bytes using SHA1 in counter mode with a /dev/urandom
11282 * initialized seed. This function is fast so can be used to generate
11283 * many bytes without any effect on the operating system entropy pool.
11284 * Currently this function is not thread safe. */
11285void RM_GetRandomBytes(unsigned char *dst, size_t len) {
11286 getRandomBytes(dst,len);
11287}
11288
11289/* Like RedisModule_GetRandomBytes() but instead of setting the string to
11290 * random bytes the string is set to random characters in the in the
11291 * hex charset [0-9a-f]. */
11292void RM_GetRandomHexChars(char *dst, size_t len) {
11293 getRandomHexChars(dst,len);
11294}
11295
11296/* --------------------------------------------------------------------------
11297 * ## Modules API exporting / importing
11298 * -------------------------------------------------------------------------- */
11299
11300/* This function is called by a module in order to export some API with a
11301 * given name. Other modules will be able to use this API by calling the
11302 * symmetrical function RM_GetSharedAPI() and casting the return value to
11303 * the right function pointer.
11304 *
11305 * The function will return REDISMODULE_OK if the name is not already taken,
11306 * otherwise REDISMODULE_ERR will be returned and no operation will be
11307 * performed.
11308 *
11309 * IMPORTANT: the apiname argument should be a string literal with static
11310 * lifetime. The API relies on the fact that it will always be valid in
11311 * the future. */
11312int RM_ExportSharedAPI(RedisModuleCtx *ctx, const char *apiname, void *func) {
11313 RedisModuleSharedAPI *sapi = zmalloc(sizeof(*sapi));
11314 sapi->module = ctx->module;
11315 sapi->func = func;
11316 if (dictAdd(server.sharedapi, (char*)apiname, sapi) != DICT_OK) {
11317 zfree(sapi);
11318 return REDISMODULE_ERR;
11319 }
11320 return REDISMODULE_OK;
11321}
11322
11323/* Request an exported API pointer. The return value is just a void pointer
11324 * that the caller of this function will be required to cast to the right
11325 * function pointer, so this is a private contract between modules.
11326 *
11327 * If the requested API is not available then NULL is returned. Because
11328 * modules can be loaded at different times with different order, this
11329 * function calls should be put inside some module generic API registering
11330 * step, that is called every time a module attempts to execute a
11331 * command that requires external APIs: if some API cannot be resolved, the
11332 * command should return an error.
11333 *
11334 * Here is an example:
11335 *
11336 * int ... myCommandImplementation(void) {
11337 * if (getExternalAPIs() == 0) {
11338 * reply with an error here if we cannot have the APIs
11339 * }
11340 * // Use the API:
11341 * myFunctionPointer(foo);
11342 * }
11343 *
11344 * And the function registerAPI() is:
11345 *
11346 * int getExternalAPIs(void) {
11347 * static int api_loaded = 0;
11348 * if (api_loaded != 0) return 1; // APIs already resolved.
11349 *
11350 * myFunctionPointer = RedisModule_GetSharedAPI("...");
11351 * if (myFunctionPointer == NULL) return 0;
11352 *
11353 * return 1;
11354 * }
11355 */
11356void *RM_GetSharedAPI(RedisModuleCtx *ctx, const char *apiname) {
11357 dictEntry *de = dictFind(server.sharedapi, apiname);
11358 if (de == NULL) return NULL;
11359 RedisModuleSharedAPI *sapi = dictGetVal(de);
11360 if (listSearchKey(sapi->module->usedby,ctx->module) == NULL) {
11361 listAddNodeTail(sapi->module->usedby,ctx->module);
11362 listAddNodeTail(ctx->module->using,sapi->module);
11363 }
11364 return sapi->func;
11365}
11366
11367/* Remove all the APIs registered by the specified module. Usually you
11368 * want this when the module is going to be unloaded. This function
11369 * assumes that's caller responsibility to make sure the APIs are not
11370 * used by other modules.
11371 *
11372 * The number of unregistered APIs is returned. */
11373int moduleUnregisterSharedAPI(RedisModule *module) {
11374 int count = 0;
11375 dictIterator di;
11376 dictEntry *de;
11377 dictInitSafeIterator(&di, server.sharedapi);
11378 while ((de = dictNext(&di)) != NULL) {
11379 const char *apiname = dictGetKey(de);
11380 RedisModuleSharedAPI *sapi = dictGetVal(de);
11381 if (sapi->module == module) {
11382 dictDelete(server.sharedapi,apiname);
11383 zfree(sapi);
11384 count++;
11385 }
11386 }
11387 dictResetIterator(&di);
11388 return count;
11389}
11390
11391/* Remove the specified module as an user of APIs of ever other module.
11392 * This is usually called when a module is unloaded.
11393 *
11394 * Returns the number of modules this module was using APIs from. */
11395int moduleUnregisterUsedAPI(RedisModule *module) {
11396 listIter li;
11397 listNode *ln;
11398 int count = 0;
11399
11400 listRewind(module->using,&li);
11401 while((ln = listNext(&li))) {
11402 RedisModule *used = ln->value;
11403 listNode *ln = listSearchKey(used->usedby,module);
11404 if (ln) {
11405 listDelNode(used->usedby,ln);
11406 count++;
11407 }
11408 }
11409 return count;
11410}
11411
11412/* Unregister all filters registered by a module.
11413 * This is called when a module is being unloaded.
11414 *
11415 * Returns the number of filters unregistered. */
11416int moduleUnregisterFilters(RedisModule *module) {
11417 listIter li;
11418 listNode *ln;
11419 int count = 0;
11420
11421 listRewind(module->filters,&li);
11422 while((ln = listNext(&li))) {
11423 RedisModuleCommandFilter *filter = ln->value;
11424 listNode *ln = listSearchKey(moduleCommandFilters,filter);
11425 if (ln) {
11426 listDelNode(moduleCommandFilters,ln);
11427 count++;
11428 }
11429 zfree(filter);
11430 }
11431 return count;
11432}
11433
11434/* --------------------------------------------------------------------------
11435 * ## Module Command Filter API
11436 * -------------------------------------------------------------------------- */
11437
11438/* Register a new command filter function.
11439 *
11440 * Command filtering makes it possible for modules to extend Redis by plugging
11441 * into the execution flow of all commands.
11442 *
11443 * A registered filter gets called before Redis executes *any* command. This
11444 * includes both core Redis commands and commands registered by any module. The
11445 * filter applies in all execution paths including:
11446 *
11447 * 1. Invocation by a client.
11448 * 2. Invocation through `RedisModule_Call()` by any module.
11449 * 3. Invocation through Lua `redis.call()`.
11450 * 4. Replication of a command from a master.
11451 *
11452 * The filter executes in a special filter context, which is different and more
11453 * limited than a RedisModuleCtx. Because the filter affects any command, it
11454 * must be implemented in a very efficient way to reduce the performance impact
11455 * on Redis. All Redis Module API calls that require a valid context (such as
11456 * `RedisModule_Call()`, `RedisModule_OpenKey()`, etc.) are not supported in a
11457 * filter context.
11458 *
11459 * The `RedisModuleCommandFilterCtx` can be used to inspect or modify the
11460 * executed command and its arguments. As the filter executes before Redis
11461 * begins processing the command, any change will affect the way the command is
11462 * processed. For example, a module can override Redis commands this way:
11463 *
11464 * 1. Register a `MODULE.SET` command which implements an extended version of
11465 * the Redis `SET` command.
11466 * 2. Register a command filter which detects invocation of `SET` on a specific
11467 * pattern of keys. Once detected, the filter will replace the first
11468 * argument from `SET` to `MODULE.SET`.
11469 * 3. When filter execution is complete, Redis considers the new command name
11470 * and therefore executes the module's own command.
11471 *
11472 * Note that in the above use case, if `MODULE.SET` itself uses
11473 * `RedisModule_Call()` the filter will be applied on that call as well. If
11474 * that is not desired, the `REDISMODULE_CMDFILTER_NOSELF` flag can be set when
11475 * registering the filter.
11476 *
11477 * The `REDISMODULE_CMDFILTER_NOSELF` flag prevents execution flows that
11478 * originate from the module's own `RM_Call()` from reaching the filter. This
11479 * flag is effective for all execution flows, including nested ones, as long as
11480 * the execution begins from the module's command context or a thread-safe
11481 * context that is associated with a blocking command.
11482 *
11483 * Detached thread-safe contexts are *not* associated with the module and cannot
11484 * be protected by this flag.
11485 *
11486 * If multiple filters are registered (by the same or different modules), they
11487 * are executed in the order of registration.
11488 */
11489RedisModuleCommandFilter *RM_RegisterCommandFilter(RedisModuleCtx *ctx, RedisModuleCommandFilterFunc callback, int flags) {
11490 RedisModuleCommandFilter *filter = zmalloc(sizeof(*filter));
11491 filter->module = ctx->module;
11492 filter->callback = callback;
11493 filter->flags = flags;
11494
11495 listAddNodeTail(moduleCommandFilters, filter);
11496 listAddNodeTail(ctx->module->filters, filter);
11497 return filter;
11498}
11499
11500/* Unregister a command filter.
11501 */
11502int RM_UnregisterCommandFilter(RedisModuleCtx *ctx, RedisModuleCommandFilter *filter) {
11503 listNode *ln;
11504
11505 /* A module can only remove its own filters */
11506 if (filter->module != ctx->module) return REDISMODULE_ERR;
11507
11508 ln = listSearchKey(moduleCommandFilters,filter);
11509 if (!ln) return REDISMODULE_ERR;
11510 listDelNode(moduleCommandFilters,ln);
11511
11512 ln = listSearchKey(ctx->module->filters,filter);
11513 if (!ln) return REDISMODULE_ERR; /* Shouldn't happen */
11514 listDelNode(ctx->module->filters,ln);
11515
11516 zfree(filter);
11517
11518 return REDISMODULE_OK;
11519}
11520
11521void moduleCallCommandFilters(client *c) {
11522 if (listLength(moduleCommandFilters) == 0) return;
11523
11524 listIter li;
11525 listNode *ln;
11526 listRewind(moduleCommandFilters,&li);
11527
11528 RedisModuleCommandFilterCtx filter = {
11529 .argv = c->argv,
11530 .argv_len = c->argv_len,
11531 .argc = c->argc,
11532 .c = c
11533 };
11534
11535 while((ln = listNext(&li))) {
11536 RedisModuleCommandFilter *f = ln->value;
11537
11538 /* Skip filter if REDISMODULE_CMDFILTER_NOSELF is set and module is
11539 * currently processing a command.
11540 */
11541 if ((f->flags & REDISMODULE_CMDFILTER_NOSELF) && f->module->in_call) continue;
11542
11543 /* Call filter */
11544 f->callback(&filter);
11545 }
11546
11547 /* If the filter sets a new command, including command or subcommand,
11548 * the command looked up will be invalid. */
11549 c->lookedcmd = NULL;
11550
11551 c->argv = filter.argv;
11552 c->argv_len = filter.argv_len;
11553 c->argc = filter.argc;
11554
11555 /* Update pending command if it exists. */
11556 pendingCommand *pcmd = c->current_pending_cmd;
11557 if (pcmd) {
11558 pcmd->argv = filter.argv;
11559 pcmd->argc = filter.argc;
11560 pcmd->argv_len = filter.argv_len;
11561 pcmd->cmd = NULL;
11562 pcmd->slot = INVALID_CLUSTER_SLOT;
11563 pcmd->flags = 0;
11564
11565 /* Reset keys result */
11566 getKeysFreeResult(&pcmd->keys_result);
11567 pcmd->keys_result = (getKeysResult)GETKEYS_RESULT_INIT;
11568 }
11569}
11570
11571/* Return the number of arguments a filtered command has. The number of
11572 * arguments include the command itself.
11573 */
11574int RM_CommandFilterArgsCount(RedisModuleCommandFilterCtx *fctx)
11575{
11576 return fctx->argc;
11577}
11578
11579/* Return the specified command argument. The first argument (position 0) is
11580 * the command itself, and the rest are user-provided args.
11581 */
11582RedisModuleString *RM_CommandFilterArgGet(RedisModuleCommandFilterCtx *fctx, int pos)
11583{
11584 if (pos < 0 || pos >= fctx->argc) return NULL;
11585 return fctx->argv[pos];
11586}
11587
11588/* Modify the filtered command by inserting a new argument at the specified
11589 * position. The specified RedisModuleString argument may be used by Redis
11590 * after the filter context is destroyed, so it must not be auto-memory
11591 * allocated, freed or used elsewhere.
11592 */
11593int RM_CommandFilterArgInsert(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg)
11594{
11595 int i;
11596
11597 if (pos < 0 || pos > fctx->argc) return REDISMODULE_ERR;
11598
11599 if (fctx->argv_len < fctx->argc+1) {
11600 fctx->argv_len = fctx->argc+1;
11601 fctx->argv = zrealloc(fctx->argv, fctx->argv_len*sizeof(RedisModuleString *));
11602 }
11603 for (i = fctx->argc; i > pos; i--) {
11604 fctx->argv[i] = fctx->argv[i-1];
11605 }
11606 fctx->argv[pos] = arg;
11607 fctx->argc++;
11608
11609 return REDISMODULE_OK;
11610}
11611
11612/* Modify the filtered command by replacing an existing argument with a new one.
11613 * The specified RedisModuleString argument may be used by Redis after the
11614 * filter context is destroyed, so it must not be auto-memory allocated, freed
11615 * or used elsewhere.
11616 */
11617int RM_CommandFilterArgReplace(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg)
11618{
11619 if (pos < 0 || pos >= fctx->argc) return REDISMODULE_ERR;
11620
11621 decrRefCount(fctx->argv[pos]);
11622 fctx->argv[pos] = arg;
11623
11624 return REDISMODULE_OK;
11625}
11626
11627/* Modify the filtered command by deleting an argument at the specified
11628 * position.
11629 */
11630int RM_CommandFilterArgDelete(RedisModuleCommandFilterCtx *fctx, int pos)
11631{
11632 int i;
11633 if (pos < 0 || pos >= fctx->argc) return REDISMODULE_ERR;
11634
11635 decrRefCount(fctx->argv[pos]);
11636 for (i = pos; i < fctx->argc-1; i++) {
11637 fctx->argv[i] = fctx->argv[i+1];
11638 }
11639 fctx->argc--;
11640
11641 return REDISMODULE_OK;
11642}
11643
11644/* Get Client ID for client that issued the command we are filtering */
11645unsigned long long RM_CommandFilterGetClientId(RedisModuleCommandFilterCtx *fctx) {
11646 return fctx->c->id;
11647}
11648
11649/* For a given pointer allocated via RedisModule_Alloc() or
11650 * RedisModule_Realloc(), return the amount of memory allocated for it.
11651 * Note that this may be different (larger) than the memory we allocated
11652 * with the allocation calls, since sometimes the underlying allocator
11653 * will allocate more memory.
11654 */
11655size_t RM_MallocSize(void* ptr) {
11656 return zmalloc_size(ptr);
11657}
11658
11659/* Similar to RM_MallocSize, the difference is that RM_MallocUsableSize
11660 * returns the usable size of memory by the module. */
11661size_t RM_MallocUsableSize(void *ptr) {
11662 /* It is safe to use 'zmalloc_usable_size()' to manipulate additional
11663 * memory space, as we guarantee that the compiler can recognize this
11664 * after 'RM_Alloc', 'RM_TryAlloc', 'RM_Realloc', or 'RM_Calloc'. */
11665 return zmalloc_usable_size(ptr);
11666}
11667
11668/* Same as RM_MallocSize, except it works on RedisModuleString pointers.
11669 */
11670size_t RM_MallocSizeString(RedisModuleString* str) {
11671 serverAssert(str->type == OBJ_STRING);
11672 return sizeof(*str) + getStringObjectSdsUsedMemory(str);
11673}
11674
11675/* Same as RM_MallocSize, except it works on RedisModuleDict pointers.
11676 * Note that the returned value is only the overhead of the underlying structures,
11677 * it does not include the allocation size of the keys and values.
11678 */
11679size_t RM_MallocSizeDict(RedisModuleDict* dict) {
11680 size_t size = sizeof(RedisModuleDict) + sizeof(rax);
11681 size += dict->rax->numnodes * sizeof(raxNode);
11682 /* For more info about this weird line, see streamRadixTreeMemoryUsage */
11683 size += dict->rax->numnodes * sizeof(long)*30;
11684 return size;
11685}
11686
11687/* Return the a number between 0 to 1 indicating the amount of memory
11688 * currently used, relative to the Redis "maxmemory" configuration.
11689 *
11690 * * 0 - No memory limit configured.
11691 * * Between 0 and 1 - The percentage of the memory used normalized in 0-1 range.
11692 * * Exactly 1 - Memory limit reached.
11693 * * Greater 1 - More memory used than the configured limit.
11694 */
11695float RM_GetUsedMemoryRatio(void){
11696 float level;
11697 getMaxmemoryState(NULL, NULL, NULL, &level);
11698 return level;
11699}
11700
11701/* --------------------------------------------------------------------------
11702 * ## Scanning keyspace and hashes
11703 * -------------------------------------------------------------------------- */
11704
11705typedef void (*RedisModuleScanCB)(RedisModuleCtx *ctx, RedisModuleString *keyname, RedisModuleKey *key, void *privdata);
11706typedef struct {
11707 RedisModuleCtx *ctx;
11708 void* user_data;
11709 RedisModuleScanCB fn;
11710} ScanCBData;
11711
11712typedef struct RedisModuleScanCursor{
11713 unsigned long long cursor;
11714 int done;
11715}RedisModuleScanCursor;
11716
11717static void moduleScanCallback(void *privdata, const dictEntry *de, dictEntryLink plink) {
11718 UNUSED(plink);
11719 ScanCBData *data = privdata;
11720 kvobj *keyvalObj = dictGetKey(de);
11721 sds key = kvobjGetKey(keyvalObj);
11722 RedisModuleString *keyname = createObject(OBJ_STRING,sdsdup(key));
11723
11724 /* Setup the key handle. */
11725 RedisModuleKey kp = {0};
11726 moduleInitKey(&kp, data->ctx, keyname, keyvalObj, REDISMODULE_READ);
11727
11728 data->fn(data->ctx, keyname, &kp, data->user_data);
11729
11730 moduleCloseKey(&kp);
11731 decrRefCount(keyname);
11732}
11733
11734/* Create a new cursor to be used with RedisModule_Scan */
11735RedisModuleScanCursor *RM_ScanCursorCreate(void) {
11736 RedisModuleScanCursor* cursor = zmalloc(sizeof(*cursor));
11737 cursor->cursor = 0;
11738 cursor->done = 0;
11739 return cursor;
11740}
11741
11742/* Restart an existing cursor. The keys will be rescanned. */
11743void RM_ScanCursorRestart(RedisModuleScanCursor *cursor) {
11744 cursor->cursor = 0;
11745 cursor->done = 0;
11746}
11747
11748/* Destroy the cursor struct. */
11749void RM_ScanCursorDestroy(RedisModuleScanCursor *cursor) {
11750 zfree(cursor);
11751}
11752
11753/* Scan API that allows a module to scan all the keys and value in
11754 * the selected db.
11755 *
11756 * Callback for scan implementation.
11757 *
11758 * void scan_callback(RedisModuleCtx *ctx, RedisModuleString *keyname,
11759 * RedisModuleKey *key, void *privdata);
11760 *
11761 * - `ctx`: the redis module context provided to for the scan.
11762 * - `keyname`: owned by the caller and need to be retained if used after this
11763 * function.
11764 * - `key`: holds info on the key and value, it is provided as best effort, in
11765 * some cases it might be NULL, in which case the user should (can) use
11766 * RedisModule_OpenKey() (and CloseKey too).
11767 * when it is provided, it is owned by the caller and will be free when the
11768 * callback returns.
11769 * - `privdata`: the user data provided to RedisModule_Scan().
11770 *
11771 * The way it should be used:
11772 *
11773 * RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
11774 * while(RedisModule_Scan(ctx, c, callback, privateData));
11775 * RedisModule_ScanCursorDestroy(c);
11776 *
11777 * It is also possible to use this API from another thread while the lock
11778 * is acquired during the actual call to RM_Scan:
11779 *
11780 * RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
11781 * RedisModule_ThreadSafeContextLock(ctx);
11782 * while(RedisModule_Scan(ctx, c, callback, privateData)){
11783 * RedisModule_ThreadSafeContextUnlock(ctx);
11784 * // do some background job
11785 * RedisModule_ThreadSafeContextLock(ctx);
11786 * }
11787 * RedisModule_ScanCursorDestroy(c);
11788 *
11789 * The function will return 1 if there are more elements to scan and
11790 * 0 otherwise, possibly setting errno if the call failed.
11791 *
11792 * It is also possible to restart an existing cursor using RM_ScanCursorRestart.
11793 *
11794 * IMPORTANT: This API is very similar to the Redis SCAN command from the
11795 * point of view of the guarantees it provides. This means that the API
11796 * may report duplicated keys, but guarantees to report at least one time
11797 * every key that was there from the start to the end of the scanning process.
11798 *
11799 * NOTE: If you do database changes within the callback, you should be aware
11800 * that the internal state of the database may change. For instance it is safe
11801 * to delete or modify the current key, but may not be safe to delete any
11802 * other key.
11803 * Moreover playing with the Redis keyspace while iterating may have the
11804 * effect of returning more duplicates. A safe pattern is to store the keys
11805 * names you want to modify elsewhere, and perform the actions on the keys
11806 * later when the iteration is complete. However this can cost a lot of
11807 * memory, so it may make sense to just operate on the current key when
11808 * possible during the iteration, given that this is safe. */
11809int RM_Scan(RedisModuleCtx *ctx, RedisModuleScanCursor *cursor, RedisModuleScanCB fn, void *privdata) {
11810 if (cursor->done) {
11811 errno = ENOENT;
11812 return 0;
11813 }
11814 int ret = 1;
11815 ScanCBData data = { ctx, privdata, fn };
11816 cursor->cursor = dbScan(ctx->client->db, cursor->cursor, moduleScanCallback, &data);
11817 if (cursor->cursor == 0) {
11818 cursor->done = 1;
11819 ret = 0;
11820 }
11821 errno = 0;
11822 return ret;
11823}
11824
11825typedef void (*RedisModuleScanKeyCB)(RedisModuleKey *key, RedisModuleString *field, RedisModuleString *value, void *privdata);
11826typedef struct {
11827 RedisModuleKey *key;
11828 void* user_data;
11829 RedisModuleScanKeyCB fn;
11830} ScanKeyCBData;
11831
11832static void moduleScanKeyCallback(void *privdata, const dictEntry *de, dictEntryLink plink) {
11833 UNUSED(plink);
11834 ScanKeyCBData *data = privdata;
11835 sds key = dictGetKey(de);
11836 kvobj *kv = data->key->kv;
11837 robj *field = NULL;
11838 robj *value = NULL;
11839 if (kv->type == OBJ_SET) {
11840 field = createStringObject(key, sdslen(key));
11841 value = NULL;
11842 } else if (kv->type == OBJ_HASH) {
11843 Entry *e = (Entry *) key;
11844
11845 /* If field is expired and not indicated to access expired, then ignore */
11846 if ((!(data->key->mode & REDISMODULE_OPEN_KEY_ACCESS_EXPIRED)) &&
11847 (entryIsExpired(e)))
11848 return;
11849
11850 /* For hash, the value is stored in the entry (field), not in the dict entry */
11851 sds fieldStr = entryGetField(e);
11852 sds val = entryGetValue(e);
11853
11854 field = createStringObject(fieldStr, sdslen(fieldStr));
11855 value = createStringObject(val, sdslen(val));
11856 } else if (kv->type == OBJ_ZSET) {
11857 zskiplistNode *znode = (zskiplistNode *) key;
11858 sds fieldStr = zslGetNodeElement(znode);
11859 field = createStringObject(fieldStr, sdslen(fieldStr));
11860 value = createStringObjectFromLongDouble(znode->score, 0);
11861 }
11862
11863 serverAssert(field != NULL);
11864 data->fn(data->key, field, value, data->user_data);
11865 decrRefCount(field);
11866 if (value) decrRefCount(value);
11867}
11868
11869/* Scan api that allows a module to scan the elements in a hash, set or sorted set key
11870 *
11871 * Callback for scan implementation.
11872 *
11873 * void scan_callback(RedisModuleKey *key, RedisModuleString* field, RedisModuleString* value, void *privdata);
11874 *
11875 * - key - the redis key context provided to for the scan.
11876 * - field - field name, owned by the caller and need to be retained if used
11877 * after this function.
11878 * - value - value string or NULL for set type, owned by the caller and need to
11879 * be retained if used after this function.
11880 * - privdata - the user data provided to RedisModule_ScanKey.
11881 *
11882 * The way it should be used:
11883 *
11884 * RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
11885 * RedisModuleKey *key = RedisModule_OpenKey(...);
11886 * while(RedisModule_ScanKey(key, c, callback, privateData));
11887 * RedisModule_CloseKey(key);
11888 * RedisModule_ScanCursorDestroy(c);
11889 *
11890 * It is also possible to use this API from another thread while the lock is acquired during
11891 * the actual call to RM_ScanKey, and re-opening the key each time:
11892 *
11893 * RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
11894 * RedisModule_ThreadSafeContextLock(ctx);
11895 * RedisModuleKey *key = RedisModule_OpenKey(...);
11896 * while(RedisModule_ScanKey(ctx, c, callback, privateData)){
11897 * RedisModule_CloseKey(key);
11898 * RedisModule_ThreadSafeContextUnlock(ctx);
11899 * // do some background job
11900 * RedisModule_ThreadSafeContextLock(ctx);
11901 * key = RedisModule_OpenKey(...);
11902 * }
11903 * RedisModule_CloseKey(key);
11904 * RedisModule_ScanCursorDestroy(c);
11905 *
11906 * The function will return 1 if there are more elements to scan and 0 otherwise,
11907 * possibly setting errno if the call failed.
11908 * It is also possible to restart an existing cursor using RM_ScanCursorRestart.
11909 *
11910 * NOTE: Certain operations are unsafe while iterating the object. For instance
11911 * while the API guarantees to return at least one time all the elements that
11912 * are present in the data structure consistently from the start to the end
11913 * of the iteration (see HSCAN and similar commands documentation), the more
11914 * you play with the elements, the more duplicates you may get. In general
11915 * deleting the current element of the data structure is safe, while removing
11916 * the key you are iterating is not safe. */
11917int RM_ScanKey(RedisModuleKey *key, RedisModuleScanCursor *cursor, RedisModuleScanKeyCB fn, void *privdata) {
11918 if (key == NULL || key->kv == NULL) {
11919 errno = EINVAL;
11920 return 0;
11921 }
11922 dict *ht = NULL;
11923 kvobj *kv = key->kv;
11924 if (kv->type == OBJ_SET) {
11925 if (kv->encoding == OBJ_ENCODING_HT)
11926 ht = kv->ptr;
11927 } else if (kv->type == OBJ_HASH) {
11928 if (kv->encoding == OBJ_ENCODING_HT)
11929 ht = kv->ptr;
11930 } else if (kv->type == OBJ_ZSET) {
11931 if (kv->encoding == OBJ_ENCODING_SKIPLIST)
11932 ht = ((zset *)kv->ptr)->dict;
11933 } else {
11934 errno = EINVAL;
11935 return 0;
11936 }
11937 if (cursor->done) {
11938 errno = ENOENT;
11939 return 0;
11940 }
11941 int ret = 1;
11942 if (ht) {
11943 ScanKeyCBData data = { key, privdata, fn };
11944 cursor->cursor = dictScan(ht, cursor->cursor, moduleScanKeyCallback, &data);
11945 if (cursor->cursor == 0) {
11946 cursor->done = 1;
11947 ret = 0;
11948 }
11949 } else if (kv->type == OBJ_SET) {
11950 setTypeIterator si;
11951 sds sdsele;
11952 setTypeInitIterator(&si, kv);
11953 while ((sdsele = setTypeNextObject(&si)) != NULL) {
11954 robj *field = createObject(OBJ_STRING, sdsele);
11955 fn(key, field, NULL, privdata);
11956 decrRefCount(field);
11957 }
11958 setTypeResetIterator(&si);
11959 cursor->cursor = 1;
11960 cursor->done = 1;
11961 ret = 0;
11962 } else if (kv->type == OBJ_ZSET || kv->type == OBJ_HASH) {
11963 unsigned char *lp, *p;
11964 /* is hash with expiry on fields, then lp tuples are [field][value][expire] */
11965 int hfe = kv->type == OBJ_HASH && kv->encoding == OBJ_ENCODING_LISTPACK_EX;
11966
11967 if (kv->type == OBJ_HASH)
11968 lp = hashTypeListpackGetLp(kv);
11969 else
11970 lp = kv->ptr;
11971
11972 p = lpSeek(lp,0);
11973 while(p) {
11974 long long vllField, vllValue, vllExpire;
11975 unsigned int lenField, lenValue;
11976 unsigned char *pField, *pValue;
11977
11978 pField = lpGetValue(p,&lenField,&vllField);
11979 p = lpNext(lp,p);
11980 pValue = lpGetValue(p,&lenValue,&vllValue);
11981 p = lpNext(lp,p);
11982
11983 if (hfe) {
11984 serverAssert(lpGetIntegerValue(p, &vllExpire));
11985 p = lpNext(lp, p);
11986
11987 /* Skip expired fields */
11988 if ((!(key->mode & REDISMODULE_OPEN_KEY_ACCESS_EXPIRED)) &&
11989 (hashTypeIsExpired(kv, vllExpire)))
11990 continue;
11991 }
11992
11993 robj *value = (pValue != NULL) ?
11994 createStringObject((char*)pValue,lenValue) :
11995 createStringObjectFromLongLongWithSds(vllValue);
11996
11997 robj *field = (pField != NULL) ?
11998 createStringObject((char*)pField,lenField) :
11999 createStringObjectFromLongLongWithSds(vllField);
12000 fn(key, field, value, privdata);
12001
12002 decrRefCount(field);
12003 decrRefCount(value);
12004 }
12005 cursor->cursor = 1;
12006 cursor->done = 1;
12007 ret = 0;
12008 }
12009 errno = 0;
12010 return ret;
12011}
12012
12013/* --------------------------------------------------------------------------
12014 * ## Module fork API
12015 * -------------------------------------------------------------------------- */
12016
12017/* Create a background child process with the current frozen snapshot of the
12018 * main process where you can do some processing in the background without
12019 * affecting / freezing the traffic and no need for threads and GIL locking.
12020 * Note that Redis allows for only one concurrent fork.
12021 * When the child wants to exit, it should call RedisModule_ExitFromChild.
12022 * If the parent wants to kill the child it should call RedisModule_KillForkChild
12023 * The done handler callback will be executed on the parent process when the
12024 * child existed (but not when killed)
12025 * Return: -1 on failure, on success the parent process will get a positive PID
12026 * of the child, and the child process will get 0.
12027 */
12028int RM_Fork(RedisModuleForkDoneHandler cb, void *user_data) {
12029 pid_t childpid;
12030
12031 if ((childpid = redisFork(CHILD_TYPE_MODULE)) == 0) {
12032 /* Child */
12033 redisSetProcTitle("redis-module-fork");
12034 } else if (childpid == -1) {
12035 serverLog(LL_WARNING,"Can't fork for module: %s", strerror(errno));
12036 } else {
12037 /* Parent */
12038 moduleForkInfo.done_handler = cb;
12039 moduleForkInfo.done_handler_user_data = user_data;
12040 serverLog(LL_VERBOSE, "Module fork started pid: %ld ", (long) childpid);
12041 }
12042 return childpid;
12043}
12044
12045/* The module is advised to call this function from the fork child once in a while,
12046 * so that it can report progress and COW memory to the parent which will be
12047 * reported in INFO.
12048 * The `progress` argument should between 0 and 1, or -1 when not available. */
12049void RM_SendChildHeartbeat(double progress) {
12050 sendChildInfoGeneric(CHILD_INFO_TYPE_CURRENT_INFO, 0, progress, "Module fork");
12051}
12052
12053/* Call from the child process when you want to terminate it.
12054 * retcode will be provided to the done handler executed on the parent process.
12055 */
12056int RM_ExitFromChild(int retcode) {
12057 sendChildCowInfo(CHILD_INFO_TYPE_MODULE_COW_SIZE, "Module fork");
12058 exitFromChild(retcode, 0);
12059 return REDISMODULE_OK;
12060}
12061
12062/* Kill the active module forked child, if there is one active and the
12063 * pid matches, and returns C_OK. Otherwise if there is no active module
12064 * child or the pid does not match, return C_ERR without doing anything. */
12065int TerminateModuleForkChild(int child_pid, int wait) {
12066 /* Module child should be active and pid should match. */
12067 if (server.child_type != CHILD_TYPE_MODULE ||
12068 server.child_pid != child_pid) return C_ERR;
12069
12070 int statloc;
12071 serverLog(LL_VERBOSE,"Killing running module fork child: %ld",
12072 (long) server.child_pid);
12073 if (kill(server.child_pid,SIGUSR1) != -1 && wait) {
12074 while(waitpid(server.child_pid, &statloc, 0) !=
12075 server.child_pid);
12076 }
12077 /* Reset the buffer accumulating changes while the child saves. */
12078 resetChildState();
12079 moduleForkInfo.done_handler = NULL;
12080 moduleForkInfo.done_handler_user_data = NULL;
12081 return C_OK;
12082}
12083
12084/* Can be used to kill the forked child process from the parent process.
12085 * child_pid would be the return value of RedisModule_Fork. */
12086int RM_KillForkChild(int child_pid) {
12087 /* Kill module child, wait for child exit. */
12088 if (TerminateModuleForkChild(child_pid,1) == C_OK)
12089 return REDISMODULE_OK;
12090 else
12091 return REDISMODULE_ERR;
12092}
12093
12094void ModuleForkDoneHandler(int exitcode, int bysignal) {
12095 serverLog(LL_NOTICE,
12096 "Module fork exited pid: %ld, retcode: %d, bysignal: %d",
12097 (long) server.child_pid, exitcode, bysignal);
12098 if (moduleForkInfo.done_handler) {
12099 moduleForkInfo.done_handler(exitcode, bysignal,
12100 moduleForkInfo.done_handler_user_data);
12101 }
12102
12103 moduleForkInfo.done_handler = NULL;
12104 moduleForkInfo.done_handler_user_data = NULL;
12105}
12106
12107/* --------------------------------------------------------------------------
12108 * ## Server hooks implementation
12109 * -------------------------------------------------------------------------- */
12110
12111/* This must be synced with REDISMODULE_EVENT_*
12112 * We use -1 (MAX_UINT64) to denote that this event doesn't have
12113 * a data structure associated with it. We use MAX_UINT64 on purpose,
12114 * in order to pass the check in RedisModule_SubscribeToServerEvent. */
12115static uint64_t moduleEventVersions[] = {
12116 REDISMODULE_REPLICATIONINFO_VERSION, /* REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED */
12117 -1, /* REDISMODULE_EVENT_PERSISTENCE */
12118 REDISMODULE_FLUSHINFO_VERSION, /* REDISMODULE_EVENT_FLUSHDB */
12119 -1, /* REDISMODULE_EVENT_LOADING */
12120 REDISMODULE_CLIENTINFO_VERSION, /* REDISMODULE_EVENT_CLIENT_CHANGE */
12121 -1, /* REDISMODULE_EVENT_SHUTDOWN */
12122 -1, /* REDISMODULE_EVENT_REPLICA_CHANGE */
12123 -1, /* REDISMODULE_EVENT_MASTER_LINK_CHANGE */
12124 REDISMODULE_CRON_LOOP_VERSION, /* REDISMODULE_EVENT_CRON_LOOP */
12125 REDISMODULE_MODULE_CHANGE_VERSION, /* REDISMODULE_EVENT_MODULE_CHANGE */
12126 REDISMODULE_LOADING_PROGRESS_VERSION, /* REDISMODULE_EVENT_LOADING_PROGRESS */
12127 REDISMODULE_SWAPDBINFO_VERSION, /* REDISMODULE_EVENT_SWAPDB */
12128 -1, /* REDISMODULE_EVENT_REPL_BACKUP */
12129 -1, /* REDISMODULE_EVENT_FORK_CHILD */
12130 -1, /* REDISMODULE_EVENT_REPL_ASYNC_LOAD */
12131 -1, /* REDISMODULE_EVENT_EVENTLOOP */
12132 -1, /* REDISMODULE_EVENT_CONFIG */
12133 REDISMODULE_KEYINFO_VERSION, /* REDISMODULE_EVENT_KEY */
12134 REDISMODULE_CLUSTER_SLOT_MIGRATION_INFO_VERSION, /* REDISMODULE_EVENT_CLUSTER_SLOT_MIGRATION */
12135 REDISMODULE_CLUSTER_SLOT_MIGRATION_TRIMINFO_VERSION, /* REDISMODULE_EVENT_CLUSTER_SLOT_MIGRATION_TRIM */
12136};
12137
12138/* Register to be notified, via a callback, when the specified server event
12139 * happens. The callback is called with the event as argument, and an additional
12140 * argument which is a void pointer and should be cased to a specific type
12141 * that is event-specific (but many events will just use NULL since they do not
12142 * have additional information to pass to the callback).
12143 *
12144 * If the callback is NULL and there was a previous subscription, the module
12145 * will be unsubscribed. If there was a previous subscription and the callback
12146 * is not null, the old callback will be replaced with the new one.
12147 *
12148 * The callback must be of this type:
12149 *
12150 * int (*RedisModuleEventCallback)(RedisModuleCtx *ctx,
12151 * RedisModuleEvent eid,
12152 * uint64_t subevent,
12153 * void *data);
12154 *
12155 * The 'ctx' is a normal Redis module context that the callback can use in
12156 * order to call other modules APIs. The 'eid' is the event itself, this
12157 * is only useful in the case the module subscribed to multiple events: using
12158 * the 'id' field of this structure it is possible to check if the event
12159 * is one of the events we registered with this callback. The 'subevent' field
12160 * depends on the event that fired.
12161 *
12162 * Finally the 'data' pointer may be populated, only for certain events, with
12163 * more relevant data.
12164 *
12165 * Here is a list of events you can use as 'eid' and related sub events:
12166 *
12167 * * RedisModuleEvent_ReplicationRoleChanged:
12168 *
12169 * This event is called when the instance switches from master
12170 * to replica or the other way around, however the event is
12171 * also called when the replica remains a replica but starts to
12172 * replicate with a different master.
12173 *
12174 * The following sub events are available:
12175 *
12176 * * `REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_MASTER`
12177 * * `REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_REPLICA`
12178 *
12179 * The 'data' field can be casted by the callback to a
12180 * `RedisModuleReplicationInfo` structure with the following fields:
12181 *
12182 * int master; // true if master, false if replica
12183 * char *masterhost; // master instance hostname for NOW_REPLICA
12184 * int masterport; // master instance port for NOW_REPLICA
12185 * char *replid1; // Main replication ID
12186 * char *replid2; // Secondary replication ID
12187 * uint64_t repl1_offset; // Main replication offset
12188 * uint64_t repl2_offset; // Offset of replid2 validity
12189 *
12190 * * RedisModuleEvent_Persistence
12191 *
12192 * This event is called when RDB saving or AOF rewriting starts
12193 * and ends. The following sub events are available:
12194 *
12195 * * `REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START`
12196 * * `REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START`
12197 * * `REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START`
12198 * * `REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START`
12199 * * `REDISMODULE_SUBEVENT_PERSISTENCE_ENDED`
12200 * * `REDISMODULE_SUBEVENT_PERSISTENCE_FAILED`
12201 *
12202 * The above events are triggered not just when the user calls the
12203 * relevant commands like BGSAVE, but also when a saving operation
12204 * or AOF rewriting occurs because of internal server triggers.
12205 * The SYNC_RDB_START sub events are happening in the foreground due to
12206 * SAVE command, FLUSHALL, or server shutdown, and the other RDB and
12207 * AOF sub events are executed in a background fork child, so any
12208 * action the module takes can only affect the generated AOF or RDB,
12209 * but will not be reflected in the parent process and affect connected
12210 * clients and commands. Also note that the AOF_START sub event may end
12211 * up saving RDB content in case of an AOF with rdb-preamble.
12212 *
12213 * * RedisModuleEvent_FlushDB
12214 *
12215 * The FLUSHALL, FLUSHDB or an internal flush (for instance
12216 * because of replication, after the replica synchronization)
12217 * happened. The following sub events are available:
12218 *
12219 * * `REDISMODULE_SUBEVENT_FLUSHDB_START`
12220 * * `REDISMODULE_SUBEVENT_FLUSHDB_END`
12221 *
12222 * The data pointer can be casted to a RedisModuleFlushInfo
12223 * structure with the following fields:
12224 *
12225 * int32_t async; // True if the flush is done in a thread.
12226 * // See for instance FLUSHALL ASYNC.
12227 * // In this case the END callback is invoked
12228 * // immediately after the database is put
12229 * // in the free list of the thread.
12230 * int32_t dbnum; // Flushed database number, -1 for all the DBs
12231 * // in the case of the FLUSHALL operation.
12232 *
12233 * The start event is called *before* the operation is initiated, thus
12234 * allowing the callback to call DBSIZE or other operation on the
12235 * yet-to-free keyspace.
12236 *
12237 * * RedisModuleEvent_Loading
12238 *
12239 * Called on loading operations: at startup when the server is
12240 * started, but also after a first synchronization when the
12241 * replica is loading the RDB file from the master.
12242 * The following sub events are available:
12243 *
12244 * * `REDISMODULE_SUBEVENT_LOADING_RDB_START`
12245 * * `REDISMODULE_SUBEVENT_LOADING_AOF_START`
12246 * * `REDISMODULE_SUBEVENT_LOADING_REPL_START`
12247 * * `REDISMODULE_SUBEVENT_LOADING_ENDED`
12248 * * `REDISMODULE_SUBEVENT_LOADING_FAILED`
12249 *
12250 * Note that AOF loading may start with an RDB data in case of
12251 * rdb-preamble, in which case you'll only receive an AOF_START event.
12252 *
12253 * * RedisModuleEvent_ClientChange
12254 *
12255 * Called when a client connects or disconnects.
12256 * The data pointer can be casted to a RedisModuleClientInfo
12257 * structure, documented in RedisModule_GetClientInfoById().
12258 * The following sub events are available:
12259 *
12260 * * `REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED`
12261 * * `REDISMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED`
12262 *
12263 * * RedisModuleEvent_Shutdown
12264 *
12265 * The server is shutting down. No subevents are available.
12266 *
12267 * * RedisModuleEvent_ReplicaChange
12268 *
12269 * This event is called when the instance (that can be both a
12270 * master or a replica) get a new online replica, or lose a
12271 * replica since it gets disconnected.
12272 * The following sub events are available:
12273 *
12274 * * `REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE`
12275 * * `REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE`
12276 *
12277 * No additional information is available so far: future versions
12278 * of Redis will have an API in order to enumerate the replicas
12279 * connected and their state.
12280 *
12281 * * RedisModuleEvent_CronLoop
12282 *
12283 * This event is called every time Redis calls the serverCron()
12284 * function in order to do certain bookkeeping. Modules that are
12285 * required to do operations from time to time may use this callback.
12286 * Normally Redis calls this function 10 times per second, but
12287 * this changes depending on the "hz" configuration.
12288 * No sub events are available.
12289 *
12290 * The data pointer can be casted to a RedisModuleCronLoop
12291 * structure with the following fields:
12292 *
12293 * int32_t hz; // Approximate number of events per second.
12294 *
12295 * * RedisModuleEvent_MasterLinkChange
12296 *
12297 * This is called for replicas in order to notify when the
12298 * replication link becomes functional (up) with our master,
12299 * or when it goes down. Note that the link is not considered
12300 * up when we just connected to the master, but only if the
12301 * replication is happening correctly.
12302 * The following sub events are available:
12303 *
12304 * * `REDISMODULE_SUBEVENT_MASTER_LINK_UP`
12305 * * `REDISMODULE_SUBEVENT_MASTER_LINK_DOWN`
12306 *
12307 * * RedisModuleEvent_ModuleChange
12308 *
12309 * This event is called when a new module is loaded or one is unloaded.
12310 * The following sub events are available:
12311 *
12312 * * `REDISMODULE_SUBEVENT_MODULE_LOADED`
12313 * * `REDISMODULE_SUBEVENT_MODULE_UNLOADED`
12314 *
12315 * The data pointer can be casted to a RedisModuleModuleChange
12316 * structure with the following fields:
12317 *
12318 * const char* module_name; // Name of module loaded or unloaded.
12319 * int32_t module_version; // Module version.
12320 *
12321 * * RedisModuleEvent_LoadingProgress
12322 *
12323 * This event is called repeatedly called while an RDB or AOF file
12324 * is being loaded.
12325 * The following sub events are available:
12326 *
12327 * * `REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB`
12328 * * `REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF`
12329 *
12330 * The data pointer can be casted to a RedisModuleLoadingProgress
12331 * structure with the following fields:
12332 *
12333 * int32_t hz; // Approximate number of events per second.
12334 * int32_t progress; // Approximate progress between 0 and 1024,
12335 * // or -1 if unknown.
12336 *
12337 * * RedisModuleEvent_SwapDB
12338 *
12339 * This event is called when a SWAPDB command has been successfully
12340 * Executed.
12341 * For this event call currently there is no subevents available.
12342 *
12343 * The data pointer can be casted to a RedisModuleSwapDbInfo
12344 * structure with the following fields:
12345 *
12346 * int32_t dbnum_first; // Swap Db first dbnum
12347 * int32_t dbnum_second; // Swap Db second dbnum
12348 *
12349 * * RedisModuleEvent_ReplBackup
12350 *
12351 * WARNING: Replication Backup events are deprecated since Redis 7.0 and are never fired.
12352 * See RedisModuleEvent_ReplAsyncLoad for understanding how Async Replication Loading events
12353 * are now triggered when repl-diskless-load is set to swapdb.
12354 *
12355 * Called when repl-diskless-load config is set to swapdb,
12356 * And redis needs to backup the current database for the
12357 * possibility to be restored later. A module with global data and
12358 * maybe with aux_load and aux_save callbacks may need to use this
12359 * notification to backup / restore / discard its globals.
12360 * The following sub events are available:
12361 *
12362 * * `REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE`
12363 * * `REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE`
12364 * * `REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD`
12365 *
12366 * * RedisModuleEvent_ReplAsyncLoad
12367 *
12368 * Called when repl-diskless-load config is set to swapdb and a replication with a master of same
12369 * data set history (matching replication ID) occurs.
12370 * In which case redis serves current data set while loading new database in memory from socket.
12371 * Modules must have declared they support this mechanism in order to activate it, through
12372 * REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD flag.
12373 * The following sub events are available:
12374 *
12375 * * `REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED`
12376 * * `REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED`
12377 * * `REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_COMPLETED`
12378 *
12379 * * RedisModuleEvent_ForkChild
12380 *
12381 * Called when a fork child (AOFRW, RDBSAVE, module fork...) is born/dies
12382 * The following sub events are available:
12383 *
12384 * * `REDISMODULE_SUBEVENT_FORK_CHILD_BORN`
12385 * * `REDISMODULE_SUBEVENT_FORK_CHILD_DIED`
12386 *
12387 * * RedisModuleEvent_EventLoop
12388 *
12389 * Called on each event loop iteration, once just before the event loop goes
12390 * to sleep or just after it wakes up.
12391 * The following sub events are available:
12392 *
12393 * * `REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP`
12394 * * `REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP`
12395 *
12396 * * RedisModule_Event_Config
12397 *
12398 * Called when a configuration event happens
12399 * The following sub events are available:
12400 *
12401 * * `REDISMODULE_SUBEVENT_CONFIG_CHANGE`
12402 *
12403 * The data pointer can be casted to a RedisModuleConfigChange
12404 * structure with the following fields:
12405 *
12406 * const char **config_names; // An array of C string pointers containing the
12407 * // name of each modified configuration item
12408 * uint32_t num_changes; // The number of elements in the config_names array
12409 *
12410 * * RedisModule_Event_Key
12411 *
12412 * Called when a key is removed from the keyspace. We can't modify any key in
12413 * the event.
12414 * The following sub events are available:
12415 *
12416 * * `REDISMODULE_SUBEVENT_KEY_DELETED`
12417 * * `REDISMODULE_SUBEVENT_KEY_EXPIRED`
12418 * * `REDISMODULE_SUBEVENT_KEY_EVICTED`
12419 * * `REDISMODULE_SUBEVENT_KEY_OVERWRITTEN`
12420 *
12421 * The data pointer can be casted to a RedisModuleKeyInfo
12422 * structure with the following fields:
12423 *
12424 * RedisModuleKey *key; // Key name
12425 *
12426 * * RedisModuleEvent_ClusterSlotMigration
12427 *
12428 * Called when an atomic slot migration (ASM) event happens.
12429 * IMPORT events are triggered on the destination side of a slot migration
12430 * operation. These notifications let modules prepare for the upcoming
12431 * ownership change, observe successful completion once the cluster config
12432 * reflects the new owner, or detect a failure in which case slot ownership
12433 * remains with the source.
12434 *
12435 * Similarly, MIGRATE events triggered on the source side of a slot
12436 * migration operation to let modules prepare for the ownership change and
12437 * observe the completion of the slot migration. MIGRATE_MODULE_PROPAGATE
12438 * event is triggered in the fork just before snapshot delivery; modules may
12439 * use it to enqueue commands that will be delivered first. See
12440 * RedisModule_ClusterPropagateForSlotMigration() for details.
12441 *
12442 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_IMPORT_STARTED`
12443 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_IMPORT_FAILED`
12444 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_IMPORT_COMPLETED`
12445 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_STARTED`
12446 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_FAILED`
12447 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_COMPLETED`
12448 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_MODULE_PROPAGATE`
12449 *
12450 * The data pointer can be casted to a RedisModuleClusterSlotMigrationInfo
12451 * structure with the following fields:
12452 *
12453 * char source_node_id[REDISMODULE_NODE_ID_LEN + 1];
12454 * char destination_node_id[REDISMODULE_NODE_ID_LEN + 1];
12455 * const char *task_id; // Task ID
12456 * RedisModuleSlotRangeArray *slots; // Slot ranges
12457 *
12458 * * RedisModuleEvent_ClusterSlotMigrationTrim
12459 *
12460 * Called when trimming keys after a slot migration. Fires on the source
12461 * after a successful migration to clean up migrated keys, or on the
12462 * destination after a failed import to discard partial imports. Two methods
12463 * are supported. In the first method, keys are deleted in a background
12464 * thread; this is reported via the TRIM_BACKGROUND event. In the second
12465 * method, Redis performs incremental deletions on the main thread via the
12466 * cron loop to avoid stalls; this is reported via the TRIM_STARTED and
12467 * TRIM_COMPLETED events. Each deletion emits REDISMODULE_NOTIFY_KEY_TRIMMED
12468 * so modules can react to individual key deletions. Redis selects the
12469 * method automatically: background by default; switches to main thread
12470 * trimming when a module subscribes to REDISMODULE_NOTIFY_KEY_TRIMMED.
12471 *
12472 * The following sub events are available:
12473 *
12474 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_TRIM_STARTED`
12475 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_TRIM_COMPLETED`
12476 * * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_TRIM_BACKGROUND`
12477 *
12478 * The data pointer can be casted to a RedisModuleClusterSlotMigrationTrimInfo
12479 * structure with the following fields:
12480 *
12481 * RedisModuleSlotRangeArray *slots; // Slot ranges
12482 *
12483 * The function returns REDISMODULE_OK if the module was successfully subscribed
12484 * for the specified event. If the API is called from a wrong context or unsupported event
12485 * is given then REDISMODULE_ERR is returned. */
12486int RM_SubscribeToServerEvent(RedisModuleCtx *ctx, RedisModuleEvent event, RedisModuleEventCallback callback) {
12487 RedisModuleEventListener *el;
12488
12489 /* Protect in case of calls from contexts without a module reference. */
12490 if (ctx->module == NULL) return REDISMODULE_ERR;
12491 if (event.id >= _REDISMODULE_EVENT_NEXT) return REDISMODULE_ERR;
12492 if (event.dataver > moduleEventVersions[event.id]) return REDISMODULE_ERR; /* Module compiled with a newer redismodule.h than we support */
12493
12494 /* Search an event matching this module and event ID. */
12495 listIter li;
12496 listNode *ln;
12497 listRewind(RedisModule_EventListeners,&li);
12498 while((ln = listNext(&li))) {
12499 el = ln->value;
12500 if (el->module == ctx->module && el->event.id == event.id)
12501 break; /* Matching event found. */
12502 }
12503
12504 /* Modify or remove the event listener if we already had one. */
12505 if (ln) {
12506 if (callback == NULL) {
12507 listDelNode(RedisModule_EventListeners,ln);
12508 zfree(el);
12509 } else {
12510 el->callback = callback; /* Update the callback with the new one. */
12511 }
12512 return REDISMODULE_OK;
12513 }
12514
12515 /* No event found, we need to add a new one. */
12516 el = zmalloc(sizeof(*el));
12517 el->module = ctx->module;
12518 el->event = event;
12519 el->callback = callback;
12520 listAddNodeTail(RedisModule_EventListeners,el);
12521 return REDISMODULE_OK;
12522}
12523
12524/**
12525 * For a given server event and subevent, return zero if the
12526 * subevent is not supported and non-zero otherwise.
12527 */
12528int RM_IsSubEventSupported(RedisModuleEvent event, int64_t subevent) {
12529 switch (event.id) {
12530 case REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED:
12531 return subevent < _REDISMODULE_EVENT_REPLROLECHANGED_NEXT;
12532 case REDISMODULE_EVENT_PERSISTENCE:
12533 return subevent < _REDISMODULE_SUBEVENT_PERSISTENCE_NEXT;
12534 case REDISMODULE_EVENT_FLUSHDB:
12535 return subevent < _REDISMODULE_SUBEVENT_FLUSHDB_NEXT;
12536 case REDISMODULE_EVENT_LOADING:
12537 return subevent < _REDISMODULE_SUBEVENT_LOADING_NEXT;
12538 case REDISMODULE_EVENT_CLIENT_CHANGE:
12539 return subevent < _REDISMODULE_SUBEVENT_CLIENT_CHANGE_NEXT;
12540 case REDISMODULE_EVENT_SHUTDOWN:
12541 return subevent < _REDISMODULE_SUBEVENT_SHUTDOWN_NEXT;
12542 case REDISMODULE_EVENT_REPLICA_CHANGE:
12543 return subevent < _REDISMODULE_EVENT_REPLROLECHANGED_NEXT;
12544 case REDISMODULE_EVENT_MASTER_LINK_CHANGE:
12545 return subevent < _REDISMODULE_SUBEVENT_MASTER_NEXT;
12546 case REDISMODULE_EVENT_CRON_LOOP:
12547 return subevent < _REDISMODULE_SUBEVENT_CRON_LOOP_NEXT;
12548 case REDISMODULE_EVENT_MODULE_CHANGE:
12549 return subevent < _REDISMODULE_SUBEVENT_MODULE_NEXT;
12550 case REDISMODULE_EVENT_LOADING_PROGRESS:
12551 return subevent < _REDISMODULE_SUBEVENT_LOADING_PROGRESS_NEXT;
12552 case REDISMODULE_EVENT_SWAPDB:
12553 return subevent < _REDISMODULE_SUBEVENT_SWAPDB_NEXT;
12554 case REDISMODULE_EVENT_REPL_ASYNC_LOAD:
12555 return subevent < _REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_NEXT;
12556 case REDISMODULE_EVENT_FORK_CHILD:
12557 return subevent < _REDISMODULE_SUBEVENT_FORK_CHILD_NEXT;
12558 case REDISMODULE_EVENT_EVENTLOOP:
12559 return subevent < _REDISMODULE_SUBEVENT_EVENTLOOP_NEXT;
12560 case REDISMODULE_EVENT_CONFIG:
12561 return subevent < _REDISMODULE_SUBEVENT_CONFIG_NEXT;
12562 case REDISMODULE_EVENT_KEY:
12563 return subevent < _REDISMODULE_SUBEVENT_KEY_NEXT;
12564 case REDISMODULE_EVENT_CLUSTER_SLOT_MIGRATION:
12565 return subevent < _REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_NEXT;
12566 case REDISMODULE_EVENT_CLUSTER_SLOT_MIGRATION_TRIM:
12567 return subevent < _REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_TRIM_NEXT;
12568 default:
12569 break;
12570 }
12571 return 0;
12572}
12573
12574typedef struct KeyInfo {
12575 int32_t dbnum;
12576 RedisModuleString *key;
12577 kvobj *kv; /* key-value object */
12578 int mode;
12579} KeyInfo;
12580
12581/* This is called by the Redis internals every time we want to fire an
12582 * event that can be intercepted by some module. The pointer 'data' is useful
12583 * in order to populate the event-specific structure when needed, in order
12584 * to return the structure with more information to the callback.
12585 *
12586 * 'eid' and 'subid' are just the main event ID and the sub event associated
12587 * with the event, depending on what exactly happened. */
12588void moduleFireServerEvent(uint64_t eid, int subid, void *data) {
12589 /* Fast path to return ASAP if there is nothing to do, avoiding to
12590 * setup the iterator and so forth: we want this call to be extremely
12591 * cheap if there are no registered modules. */
12592 if (listLength(RedisModule_EventListeners) == 0) return;
12593
12594 listIter li;
12595 listNode *ln;
12596 listRewind(RedisModule_EventListeners,&li);
12597 while((ln = listNext(&li))) {
12598 RedisModuleEventListener *el = ln->value;
12599 if (el->event.id == eid) {
12600 RedisModuleCtx ctx;
12601 if (eid == REDISMODULE_EVENT_CLIENT_CHANGE) {
12602 /* In the case of client changes, we're pushing the real client
12603 * so the event handler can mutate it if needed. For example,
12604 * to change its authentication state in a way that does not
12605 * depend on specific commands executed later.
12606 */
12607 moduleCreateContext(&ctx,el->module,REDISMODULE_CTX_NONE);
12608 ctx.client = (client *) data;
12609 } else {
12610 moduleCreateContext(&ctx,el->module,REDISMODULE_CTX_TEMP_CLIENT);
12611 }
12612
12613 void *moduledata = NULL;
12614 RedisModuleClientInfoV1 civ1;
12615 RedisModuleReplicationInfoV1 riv1;
12616 RedisModuleModuleChangeV1 mcv1;
12617 RedisModuleKey key;
12618 RedisModuleKeyInfoV1 ki = {REDISMODULE_KEYINFO_VERSION, &key};
12619
12620 /* Event specific context and data pointer setup. */
12621 if (eid == REDISMODULE_EVENT_CLIENT_CHANGE) {
12622 serverAssert(modulePopulateClientInfoStructure(&civ1,data, el->event.dataver) == REDISMODULE_OK);
12623 moduledata = &civ1;
12624 } else if (eid == REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED) {
12625 serverAssert(modulePopulateReplicationInfoStructure(&riv1,el->event.dataver) == REDISMODULE_OK);
12626 moduledata = &riv1;
12627 } else if (eid == REDISMODULE_EVENT_FLUSHDB) {
12628 moduledata = data;
12629 RedisModuleFlushInfoV1 *fi = data;
12630 if (fi->dbnum != -1)
12631 selectDb(ctx.client, fi->dbnum);
12632 } else if (eid == REDISMODULE_EVENT_MODULE_CHANGE) {
12633 RedisModule *m = data;
12634 if (m == el->module) {
12635 moduleFreeContext(&ctx);
12636 continue;
12637 }
12638 mcv1.version = REDISMODULE_MODULE_CHANGE_VERSION;
12639 mcv1.module_name = m->name;
12640 mcv1.module_version = m->ver;
12641 moduledata = &mcv1;
12642 } else if (eid == REDISMODULE_EVENT_LOADING_PROGRESS) {
12643 moduledata = data;
12644 } else if (eid == REDISMODULE_EVENT_CRON_LOOP) {
12645 moduledata = data;
12646 } else if (eid == REDISMODULE_EVENT_SWAPDB) {
12647 moduledata = data;
12648 } else if (eid == REDISMODULE_EVENT_CONFIG) {
12649 moduledata = data;
12650 } else if (eid == REDISMODULE_EVENT_KEY) {
12651 KeyInfo *info = data;
12652 selectDb(ctx.client, info->dbnum);
12653 moduleInitKey(&key, &ctx, info->key, info->kv, info->mode);
12654 moduledata = &ki;
12655 } else if (eid == REDISMODULE_EVENT_CLUSTER_SLOT_MIGRATION) {
12656 moduledata = data;
12657 } else if (eid == REDISMODULE_EVENT_CLUSTER_SLOT_MIGRATION_TRIM) {
12658 moduledata = data;
12659 }
12660
12661 el->module->in_hook++;
12662 el->callback(&ctx,el->event,subid,moduledata);
12663 el->module->in_hook--;
12664
12665 if (eid == REDISMODULE_EVENT_KEY) {
12666 moduleCloseKey(&key);
12667 }
12668
12669 moduleFreeContext(&ctx);
12670 }
12671 }
12672}
12673
12674/* Remove all the listeners for this module: this is used before unloading
12675 * a module. */
12676void moduleUnsubscribeAllServerEvents(RedisModule *module) {
12677 RedisModuleEventListener *el;
12678 listIter li;
12679 listNode *ln;
12680 listRewind(RedisModule_EventListeners,&li);
12681
12682 while((ln = listNext(&li))) {
12683 el = ln->value;
12684 if (el->module == module) {
12685 listDelNode(RedisModule_EventListeners,ln);
12686 zfree(el);
12687 }
12688 }
12689}
12690
12691void processModuleLoadingProgressEvent(int is_aof) {
12692 long long now = server.ustime;
12693 static long long next_event = 0;
12694 if (now >= next_event) {
12695 /* Fire the loading progress modules end event. */
12696 int progress = -1;
12697 if (server.loading_total_bytes)
12698 progress = (server.loading_loaded_bytes<<10) / server.loading_total_bytes;
12699 RedisModuleLoadingProgressV1 fi = {REDISMODULE_LOADING_PROGRESS_VERSION,
12700 server.hz,
12701 progress};
12702 moduleFireServerEvent(REDISMODULE_EVENT_LOADING_PROGRESS,
12703 is_aof?
12704 REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF:
12705 REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB,
12706 &fi);
12707 /* decide when the next event should fire. */
12708 next_event = now + 1000000 / server.hz;
12709 }
12710}
12711
12712/* When a key is deleted (in dbAsyncDelete/dbSyncDelete/setKey), it
12713* will be called to tell the module which key is about to be released. */
12714void moduleNotifyKeyUnlink(robj *key, kvobj *kv, int dbid, int flags) {
12715 server.allow_access_expired++;
12716 server.allow_access_trimmed++;
12717 int subevent = REDISMODULE_SUBEVENT_KEY_DELETED;
12718 if (flags & DB_FLAG_KEY_EXPIRED) {
12719 subevent = REDISMODULE_SUBEVENT_KEY_EXPIRED;
12720 } else if (flags & DB_FLAG_KEY_EVICTED) {
12721 subevent = REDISMODULE_SUBEVENT_KEY_EVICTED;
12722 } else if (flags & DB_FLAG_KEY_OVERWRITE) {
12723 subevent = REDISMODULE_SUBEVENT_KEY_OVERWRITTEN;
12724 }
12725 KeyInfo info = {dbid, key, kv, REDISMODULE_READ};
12726 moduleFireServerEvent(REDISMODULE_EVENT_KEY, subevent, &info);
12727
12728 if (kv->type == OBJ_MODULE) {
12729 moduleValue *mv = kv->ptr;
12730 moduleType *mt = mv->type;
12731 /* We prefer to use the enhanced version. */
12732 if (mt->unlink2 != NULL) {
12733 RedisModuleKeyOptCtx ctx = {key, NULL, dbid, -1};
12734 mt->unlink2(&ctx,mv->value);
12735 } else if (mt->unlink != NULL) {
12736 mt->unlink(key,mv->value);
12737 }
12738 }
12739 server.allow_access_expired--;
12740 server.allow_access_trimmed--;
12741}
12742
12743/* Return the free_effort of the module, it will automatically choose to call
12744 * `free_effort` or `free_effort2`, and the default return value is 1.
12745 * value of 0 means very high effort (always asynchronous freeing). */
12746size_t moduleGetFreeEffort(robj *key, robj *val, int dbid) {
12747 moduleValue *mv = val->ptr;
12748 moduleType *mt = mv->type;
12749 size_t effort = 1;
12750 /* We prefer to use the enhanced version. */
12751 if (mt->free_effort2 != NULL) {
12752 RedisModuleKeyOptCtx ctx = {key, NULL, dbid, -1};
12753 effort = mt->free_effort2(&ctx,mv->value);
12754 } else if (mt->free_effort != NULL) {
12755 effort = mt->free_effort(key,mv->value);
12756 }
12757
12758 return effort;
12759}
12760
12761/* Return the memory usage of the module, it will automatically choose to call
12762 * `mem_usage` or `mem_usage2`, and the default return value is 0. */
12763size_t moduleGetMemUsage(robj *key, robj *val, size_t sample_size, int dbid) {
12764 moduleValue *mv = val->ptr;
12765 moduleType *mt = mv->type;
12766 size_t size = 0;
12767 /* We prefer to use the enhanced version. */
12768 if (mt->mem_usage2 != NULL) {
12769 RedisModuleKeyOptCtx ctx = {key, NULL, dbid, -1};
12770 size = mt->mem_usage2(&ctx, mv->value, sample_size);
12771 } else if (mt->mem_usage != NULL) {
12772 size = mt->mem_usage(mv->value);
12773 }
12774
12775 return size;
12776}
12777
12778/* --------------------------------------------------------------------------
12779 * Modules API internals
12780 * -------------------------------------------------------------------------- */
12781
12782/* server.moduleapi dictionary type. Only uses plain C strings since
12783 * this gets queries from modules. */
12784
12785uint64_t dictCStringKeyHash(const void *key) {
12786 return dictGenHashFunction((unsigned char*)key, strlen((char*)key));
12787}
12788
12789int dictCStringKeyCompare(dictCmpCache *cache, const void *key1, const void *key2) {
12790 UNUSED(cache);
12791 return strcmp(key1,key2) == 0;
12792}
12793
12794dictType moduleAPIDictType = {
12795 dictCStringKeyHash, /* hash function */
12796 NULL, /* key dup */
12797 NULL, /* val dup */
12798 dictCStringKeyCompare, /* key compare */
12799 NULL, /* key destructor */
12800 NULL, /* val destructor */
12801 NULL /* allow to expand */
12802};
12803
12804int moduleRegisterApi(const char *funcname, void *funcptr) {
12805 return dictAdd(server.moduleapi, (char*)funcname, funcptr);
12806}
12807
12808#define REGISTER_API(name) \
12809 moduleRegisterApi("RedisModule_" #name, (void *)(unsigned long)RM_ ## name)
12810
12811/* Global initialization at Redis startup. */
12812void moduleRegisterCoreAPI(void);
12813
12814/* Currently, this function is just a placeholder for the module system
12815 * initialization steps that need to be run after server initialization.
12816 * A previous issue, selectDb() in createClient() requires that server.db has
12817 * been initialized, see #7323. */
12818void moduleInitModulesSystemLast(void) {
12819}
12820
12821
12822dictType sdsKeyValueHashDictType = {
12823 dictSdsCaseHash, /* hash function */
12824 NULL, /* key dup */
12825 NULL, /* val dup */
12826 dictSdsKeyCaseCompare, /* key compare */
12827 dictSdsDestructor, /* key destructor */
12828 dictSdsDestructor, /* val destructor */
12829 NULL /* allow to expand */
12830};
12831
12832void moduleInitModulesSystem(void) {
12833 moduleUnblockedClients = listCreate();
12834 server.loadmodule_queue = listCreate();
12835 server.module_configs_queue = dictCreate(&sdsKeyValueHashDictType);
12836 server.module_gil_acquring = 0;
12837 modules = dictCreate(&modulesDictType);
12838 moduleAuthCallbacks = listCreate();
12839
12840 /* Set up the keyspace notification subscriber list and static client */
12841 moduleKeyspaceSubscribers = listCreate();
12842
12843 modulePostExecUnitJobs = listCreate();
12844
12845 /* Set up filter list */
12846 moduleCommandFilters = listCreate();
12847
12848 moduleRegisterCoreAPI();
12849
12850 /* Create a pipe for module threads to be able to wake up the redis main thread.
12851 * Make the pipe non blocking. This is just a best effort aware mechanism
12852 * and we do not want to block not in the read nor in the write half.
12853 * Enable close-on-exec flag on pipes in case of the fork-exec system calls in
12854 * sentinels or redis servers. */
12855 if (anetPipe(server.module_pipe, O_CLOEXEC|O_NONBLOCK, O_CLOEXEC|O_NONBLOCK) == -1) {
12856 serverLog(LL_WARNING,
12857 "Can't create the pipe for module threads: %s", strerror(errno));
12858 exit(1);
12859 }
12860
12861 /* Create the timers radix tree. */
12862 Timers = raxNew();
12863
12864 /* Setup the event listeners data structures. */
12865 RedisModule_EventListeners = listCreate();
12866
12867 /* Making sure moduleEventVersions is synced with the number of events. */
12868 serverAssert(sizeof(moduleEventVersions)/sizeof(moduleEventVersions[0]) == _REDISMODULE_EVENT_NEXT);
12869
12870 /* Our thread-safe contexts GIL must start with already locked:
12871 * it is just unlocked when it's safe. */
12872 pthread_mutex_lock(&moduleGIL);
12873}
12874
12875void modulesCron(void) {
12876 /* Check number of temporary clients in the pool and free the unused ones
12877 * since the last cron. moduleTempClientMinCount tracks minimum count of
12878 * clients in the pool since the last cron. This is the number of clients
12879 * that we didn't use for the last cron period. */
12880
12881 /* Limit the max client count to be freed at once to avoid latency spikes.*/
12882 int iteration = 50;
12883 /* We are freeing clients if we have more than 8 unused clients. Keeping
12884 * small amount of clients to avoid client allocation costs if temporary
12885 * clients are required after some idle period. */
12886 const unsigned int min_client = 8;
12887 while (iteration > 0 && moduleTempClientCount > 0 && moduleTempClientMinCount > min_client) {
12888 client *c = moduleTempClients[--moduleTempClientCount];
12889 freeClient(c);
12890 iteration--;
12891 moduleTempClientMinCount--;
12892 }
12893 moduleTempClientMinCount = moduleTempClientCount;
12894
12895 /* Shrink moduleTempClients array itself if it is wasting some space */
12896 if (moduleTempClientCap > 32 && moduleTempClientCap > moduleTempClientCount * 4) {
12897 moduleTempClientCap /= 4;
12898 moduleTempClients = zrealloc(moduleTempClients,sizeof(client*)*moduleTempClientCap);
12899 }
12900}
12901
12902void moduleLoadQueueEntryFree(struct moduleLoadQueueEntry *loadmod) {
12903 if (!loadmod) return;
12904 sdsfree(loadmod->path);
12905 for (int i = 0; i < loadmod->argc; i++) {
12906 decrRefCount(loadmod->argv[i]);
12907 }
12908 zfree(loadmod->argv);
12909 zfree(loadmod);
12910}
12911
12912/* Remove Module Configs from standardConfig array in config.c */
12913void moduleRemoveConfigs(RedisModule *module) {
12914 listIter li;
12915 listNode *ln;
12916 listRewind(module->module_configs, &li);
12917 while ((ln = listNext(&li))) {
12918 ModuleConfig *config = listNodeValue(ln);
12919 removeConfig(config->name);
12920 if (config->alias)
12921 removeConfig(config->alias);
12922 }
12923}
12924
12925/* Remove ACL categories added by the module when it fails to load. */
12926void moduleRemoveCateogires(RedisModule *module) {
12927 if (module->num_acl_categories_added) {
12928 ACLCleanupCategoriesOnFailure(module->num_acl_categories_added);
12929 }
12930}
12931
12932int VectorSets_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
12933/* Load internal data types that bundled as modules */
12934void moduleLoadInternalModules(void) {
12935#ifdef INCLUDE_VEC_SETS
12936 int retval = moduleOnLoad((int (*)(void *, void **, int)) VectorSets_OnLoad, NULL, NULL, NULL, 0, 0);
12937 serverAssert(retval == C_OK);
12938#endif
12939}
12940
12941/* Load all the modules in the server.loadmodule_queue list, which is
12942 * populated by `loadmodule` directives in the configuration file.
12943 * We can't load modules directly when processing the configuration file
12944 * because the server must be fully initialized before loading modules.
12945 *
12946 * The function aborts the server on errors, since to start with missing
12947 * modules is not considered sane: clients may rely on the existence of
12948 * given commands, loading AOF also may need some modules to exist, and
12949 * if this instance is a slave, it must understand commands from master. */
12950void moduleLoadFromQueue(void) {
12951 listIter li;
12952 listNode *ln;
12953
12954 listRewind(server.loadmodule_queue,&li);
12955 while((ln = listNext(&li))) {
12956 struct moduleLoadQueueEntry *loadmod = ln->value;
12957 if (moduleLoad(loadmod->path,(void **)loadmod->argv,loadmod->argc, 0)
12958 == C_ERR)
12959 {
12960 serverLog(LL_WARNING,
12961 "Can't load module from %s: server aborting",
12962 loadmod->path);
12963 exit(1);
12964 }
12965 moduleLoadQueueEntryFree(loadmod);
12966 listDelNode(server.loadmodule_queue, ln);
12967 }
12968 if (dictSize(server.module_configs_queue)) {
12969 serverLog(LL_WARNING, "Unresolved Configuration(s) Detected:");
12970 dictIterator di;
12971 dictEntry *de;
12972 dictInitIterator(&di, server.module_configs_queue);
12973 while ((de = dictNext(&di)) != NULL) {
12974 serverLog(LL_WARNING, ">>> '%s %s'", (char *)dictGetKey(de), (char *)dictGetVal(de));
12975 }
12976 dictResetIterator(&di);
12977 serverLog(LL_WARNING, "Module Configuration detected without loadmodule directive or no ApplyConfig call: aborting");
12978 exit(1);
12979 }
12980}
12981
12982void moduleFreeModuleStructure(struct RedisModule *module) {
12983 listRelease(module->types);
12984 listRelease(module->filters);
12985 listRelease(module->usedby);
12986 listRelease(module->using);
12987 listRelease(module->module_configs);
12988 sdsfree(module->name);
12989 moduleLoadQueueEntryFree(module->loadmod);
12990 zfree(module);
12991}
12992
12993void moduleFreeArgs(struct redisCommandArg *args, int num_args) {
12994 for (int j = 0; j < num_args; j++) {
12995 zfree((char *)args[j].name);
12996 zfree((char *)args[j].token);
12997 zfree((char *)args[j].summary);
12998 zfree((char *)args[j].since);
12999 zfree((char *)args[j].deprecated_since);
13000 zfree((char *)args[j].display_text);
13001
13002 if (args[j].subargs) {
13003 moduleFreeArgs(args[j].subargs, args[j].num_args);
13004 }
13005 }
13006 zfree(args);
13007}
13008
13009/* Free the command registered with the specified module.
13010 * On success C_OK is returned, otherwise C_ERR is returned.
13011 *
13012 * Note that caller needs to handle the deletion of the command table dict,
13013 * and after that needs to free the command->fullname and the command itself.
13014 */
13015int moduleFreeCommand(struct RedisModule *module, struct redisCommand *cmd) {
13016 if (cmd->proc != RedisModuleCommandDispatcher)
13017 return C_ERR;
13018
13019 RedisModuleCommand *cp = cmd->module_cmd;
13020 if (cp->module != module)
13021 return C_ERR;
13022
13023 /* Free everything except cmd->fullname and cmd itself. */
13024 for (int j = 0; j < cmd->key_specs_num; j++) {
13025 if (cmd->key_specs[j].notes)
13026 zfree((char *)cmd->key_specs[j].notes);
13027 if (cmd->key_specs[j].begin_search_type == KSPEC_BS_KEYWORD)
13028 zfree((char *)cmd->key_specs[j].bs.keyword.keyword);
13029 }
13030 zfree(cmd->key_specs);
13031 for (int j = 0; cmd->tips && cmd->tips[j]; j++)
13032 zfree((char *)cmd->tips[j]);
13033 zfree(cmd->tips);
13034 for (int j = 0; cmd->history && cmd->history[j].since; j++) {
13035 zfree((char *)cmd->history[j].since);
13036 zfree((char *)cmd->history[j].changes);
13037 }
13038 zfree(cmd->history);
13039 zfree((char *)cmd->summary);
13040 zfree((char *)cmd->since);
13041 zfree((char *)cmd->deprecated_since);
13042 zfree((char *)cmd->complexity);
13043 if (cmd->latency_histogram) {
13044 hdr_close(cmd->latency_histogram);
13045 cmd->latency_histogram = NULL;
13046 }
13047 moduleFreeArgs(cmd->args, cmd->num_args);
13048 zfree(cp);
13049
13050 if (cmd->subcommands_dict) {
13051 dictEntry *de;
13052 dictIterator di;
13053 dictInitSafeIterator(&di, cmd->subcommands_dict);
13054 while ((de = dictNext(&di)) != NULL) {
13055 struct redisCommand *sub = dictGetVal(de);
13056 if (moduleFreeCommand(module, sub) != C_OK) continue;
13057
13058 serverAssert(dictDelete(cmd->subcommands_dict, sub->declared_name) == DICT_OK);
13059 sdsfree((sds)sub->declared_name);
13060 sdsfree(sub->fullname);
13061 zfree(sub);
13062 }
13063 dictResetIterator(&di);
13064 dictRelease(cmd->subcommands_dict);
13065 }
13066
13067 return C_OK;
13068}
13069
13070void moduleUnregisterCommands(struct RedisModule *module) {
13071 pauseAllIOThreads();
13072 /* Unregister all the commands registered by this module. */
13073 dictIterator di;
13074 dictEntry *de;
13075 dictInitSafeIterator(&di, server.commands);
13076 while ((de = dictNext(&di)) != NULL) {
13077 struct redisCommand *cmd = dictGetVal(de);
13078 if (moduleFreeCommand(module, cmd) != C_OK) continue;
13079
13080 serverAssert(dictDelete(server.commands, cmd->fullname) == DICT_OK);
13081 serverAssert(dictDelete(server.orig_commands, cmd->fullname) == DICT_OK);
13082 sdsfree((sds)cmd->declared_name);
13083 sdsfree(cmd->fullname);
13084 zfree(cmd);
13085 }
13086 dictResetIterator(&di);
13087 resumeAllIOThreads();
13088}
13089
13090/* We parse argv to add sds "NAME VALUE" pairs to the server.module_configs_queue list of configs.
13091 * We also increment the module_argv pointer to just after ARGS if there are args, otherwise
13092 * we set it to NULL */
13093int parseLoadexArguments(RedisModuleString ***module_argv, int *module_argc) {
13094 int args_specified = 0;
13095 RedisModuleString **argv = *module_argv;
13096 int argc = *module_argc;
13097 for (int i = 0; i < argc; i++) {
13098 char *arg_val = argv[i]->ptr;
13099 if (!strcasecmp(arg_val, "CONFIG")) {
13100 if (i + 2 >= argc) {
13101 serverLog(LL_NOTICE, "CONFIG specified without name value pair");
13102 return REDISMODULE_ERR;
13103 }
13104 sds name = sdsdup(argv[i + 1]->ptr);
13105 sds value = sdsdup(argv[i + 2]->ptr);
13106 if (!dictReplace(server.module_configs_queue, name, value)) sdsfree(name);
13107 i += 2;
13108 } else if (!strcasecmp(arg_val, "ARGS")) {
13109 args_specified = 1;
13110 i++;
13111 if (i >= argc) {
13112 *module_argv = NULL;
13113 *module_argc = 0;
13114 } else {
13115 *module_argv = argv + i;
13116 *module_argc = argc - i;
13117 }
13118 break;
13119 } else {
13120 serverLog(LL_NOTICE, "Syntax Error from arguments to loadex around %s.", arg_val);
13121 return REDISMODULE_ERR;
13122 }
13123 }
13124 if (!args_specified) {
13125 *module_argv = NULL;
13126 *module_argc = 0;
13127 }
13128 return REDISMODULE_OK;
13129}
13130
13131/* Unregister module-related things, called when moduleLoad fails or moduleUnload. */
13132void moduleUnregisterCleanup(RedisModule *module) {
13133 moduleFreeAuthenticatedClients(module);
13134 moduleUnregisterCommands(module);
13135 moduleUnsubscribeNotifications(module);
13136 moduleUnregisterSharedAPI(module);
13137 moduleUnregisterUsedAPI(module);
13138 moduleUnregisterFilters(module);
13139 moduleUnsubscribeAllServerEvents(module);
13140 moduleRemoveConfigs(module);
13141 moduleUnregisterAuthCBs(module);
13142}
13143
13144/* Load a module by path and initialize it. On success C_OK is returned, otherwise
13145 * C_ERR is returned. */
13146int moduleLoad(const char *path, void **module_argv, int module_argc, int is_loadex) {
13147 int (*onload)(void *, void **, int);
13148 void *handle;
13149
13150 struct stat st;
13151 if (stat(path, &st) == 0) {
13152 /* This check is best effort */
13153 if (!(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
13154 serverLog(LL_WARNING, "Module %s failed to load: It does not have execute permissions.", path);
13155 return C_ERR;
13156 }
13157 }
13158
13159 handle = dlopen(path,RTLD_NOW|RTLD_LOCAL);
13160 if (handle == NULL) {
13161 serverLog(LL_WARNING, "Module %s failed to load: %s", path, dlerror());
13162 return C_ERR;
13163 }
13164 onload = (int (*)(void *, void **, int))(unsigned long) dlsym(handle,"RedisModule_OnLoad");
13165 if (onload == NULL) {
13166 dlclose(handle);
13167 serverLog(LL_WARNING,
13168 "Module %s does not export RedisModule_OnLoad() "
13169 "symbol. Module not loaded.",path);
13170 return C_ERR;
13171 }
13172
13173 return moduleOnLoad(onload, path, handle, module_argv, module_argc, is_loadex);
13174}
13175
13176/* Load a module by its 'onload' callback and initialize it. On success C_OK is returned, otherwise
13177 * C_ERR is returned. */
13178int moduleOnLoad(int (*onload)(void *, void **, int), const char *path, void *handle, void **module_argv, int module_argc, int is_loadex) {
13179 RedisModuleCtx ctx;
13180 moduleCreateContext(&ctx, NULL, REDISMODULE_CTX_TEMP_CLIENT); /* We pass NULL since we don't have a module yet. */
13181 if (onload((void*)&ctx,module_argv,module_argc) == REDISMODULE_ERR) {
13182 serverLog(LL_WARNING,
13183 "Module %s initialization failed. Module not loaded",path);
13184 if (ctx.module) {
13185 moduleUnregisterCleanup(ctx.module);
13186 moduleRemoveCateogires(ctx.module);
13187 moduleFreeModuleStructure(ctx.module);
13188 }
13189 moduleFreeContext(&ctx);
13190 if (handle) dlclose(handle);
13191 return C_ERR;
13192 }
13193
13194 /* Redis module loaded! Register it. */
13195 dictAdd(modules,ctx.module->name,ctx.module);
13196 ctx.module->blocked_clients = 0;
13197 ctx.module->handle = handle;
13198 ctx.module->loadmod = zmalloc(sizeof(struct moduleLoadQueueEntry));
13199 ctx.module->loadmod->path = sdsnew(path);
13200 ctx.module->loadmod->argv = module_argc ? zmalloc(sizeof(robj*)*module_argc) : NULL;
13201 ctx.module->loadmod->argc = module_argc;
13202 for (int i = 0; i < module_argc; i++) {
13203 ctx.module->loadmod->argv[i] = module_argv[i];
13204 incrRefCount(ctx.module->loadmod->argv[i]);
13205 }
13206
13207 /* If module commands have ACL categories, recompute command bits
13208 * for all existing users once the modules has been registered. */
13209 if (ctx.module->num_commands_with_acl_categories) {
13210 ACLRecomputeCommandBitsFromCommandRulesAllUsers();
13211 }
13212 if (path) serverLog(LL_NOTICE,"Module '%s' loaded from %s",ctx.module->name,path);
13213 ctx.module->onload = 0;
13214
13215 int post_load_err = 0;
13216 if (listLength(ctx.module->module_configs) && !(ctx.module->configs_initialized & MODULE_CONFIGS_USER_VALS)) {
13217 serverLogRaw(LL_WARNING, "Module Configurations were not set, missing LoadConfigs call. Unloading the module.");
13218 post_load_err = 1;
13219 }
13220
13221 if (is_loadex && dictSize(server.module_configs_queue)) {
13222 serverLogRaw(LL_WARNING, "Loadex configurations were not applied, likely due to invalid arguments. Unloading the module.");
13223 post_load_err = 1;
13224 }
13225
13226 if (post_load_err) {
13227 serverAssert(moduleUnload(ctx.module->name, NULL, 1) == C_OK);
13228 moduleFreeContext(&ctx);
13229 return C_ERR;
13230 }
13231
13232 /* Fire the loaded modules event. */
13233 moduleFireServerEvent(REDISMODULE_EVENT_MODULE_CHANGE,
13234 REDISMODULE_SUBEVENT_MODULE_LOADED,
13235 ctx.module);
13236
13237 moduleFreeContext(&ctx);
13238 return C_OK;
13239}
13240
13241/* Unload the module registered with the specified name. On success
13242 * C_OK is returned, otherwise C_ERR is returned and errmsg is set
13243 * with an appropriate message.
13244 * Only forcefully unload this module, passing forced_unload != 0,
13245 * if it is certain that it has not yet been in use (e.g., immediate
13246 * unload on failed load). */
13247int moduleUnload(sds name, const char **errmsg, int forced_unload) {
13248 struct RedisModule *module = dictFetchValue(modules,name);
13249
13250 if (module == NULL) {
13251 *errmsg = "no such module with that name";
13252 return C_ERR;
13253 } else if (sdslen(module->loadmod->path) == 0) {
13254 *errmsg = "the module can't be unloaded";
13255 return C_ERR;
13256 } else if (listLength(module->types) && !forced_unload) {
13257 *errmsg = "the module exports one or more module-side data "
13258 "types, can't unload";
13259 return C_ERR;
13260 } else if (listLength(module->usedby)) {
13261 *errmsg = "the module exports APIs used by other modules. "
13262 "Please unload them first and try again";
13263 return C_ERR;
13264 } else if (module->blocked_clients) {
13265 *errmsg = "the module has blocked clients. "
13266 "Please wait for them to be unblocked and try again";
13267 return C_ERR;
13268 } else if (moduleHoldsTimer(module)) {
13269 *errmsg = "the module holds timer that is not fired. "
13270 "Please stop the timer or wait until it fires.";
13271 return C_ERR;
13272 }
13273
13274 /* Give module a chance to clean up. */
13275 int (*onunload)(void *);
13276 onunload = (int (*)(void *))(unsigned long) dlsym(module->handle, "RedisModule_OnUnload");
13277 if (onunload) {
13278 RedisModuleCtx ctx;
13279 moduleCreateContext(&ctx, module, REDISMODULE_CTX_TEMP_CLIENT);
13280 int unload_status = onunload((void*)&ctx);
13281 moduleFreeContext(&ctx);
13282
13283 if (unload_status == REDISMODULE_ERR) {
13284 serverLog(LL_WARNING, "Module %s OnUnload failed. Unload canceled.", name);
13285 errno = ECANCELED;
13286 return C_ERR;
13287 }
13288 }
13289
13290 moduleUnregisterCleanup(module);
13291
13292 /* Unload the dynamic library. */
13293 if (dlclose(module->handle) == -1) {
13294 char *error = dlerror();
13295 if (error == NULL) error = "Unknown error";
13296 serverLog(LL_WARNING,"Error when trying to close the %s module: %s",
13297 module->name, error);
13298 }
13299
13300 /* Fire the unloaded modules event. */
13301 moduleFireServerEvent(REDISMODULE_EVENT_MODULE_CHANGE,
13302 REDISMODULE_SUBEVENT_MODULE_UNLOADED,
13303 module);
13304
13305 /* Remove from list of modules. */
13306 serverLog(LL_NOTICE,"Module %s unloaded",module->name);
13307 dictDelete(modules,module->name);
13308 module->name = NULL; /* The name was already freed by dictDelete(). */
13309 moduleFreeModuleStructure(module);
13310
13311 /* Recompute command bits for all users once the modules has been completely unloaded. */
13312 ACLRecomputeCommandBitsFromCommandRulesAllUsers();
13313 return C_OK;
13314}
13315
13316void modulePipeReadable(aeEventLoop *el, int fd, void *privdata, int mask) {
13317 UNUSED(el);
13318 UNUSED(fd);
13319 UNUSED(mask);
13320 UNUSED(privdata);
13321
13322 char buf[128];
13323 while (read(fd, buf, sizeof(buf)) == sizeof(buf));
13324
13325 /* Handle event loop events if pipe was written from event loop API */
13326 eventLoopHandleOneShotEvents();
13327}
13328
13329/* Helper function for the MODULE and HELLO command: send the list of the
13330 * loaded modules to the client. */
13331void addReplyLoadedModules(client *c) {
13332 const long ln = dictSize(modules);
13333 /* In case no module is load we avoid iterator creation */
13334 addReplyArrayLen(c,ln);
13335 if (ln == 0) {
13336 return;
13337 }
13338 dictIterator di;
13339 dictEntry *de;
13340
13341 dictInitIterator(&di, modules);
13342 while ((de = dictNext(&di)) != NULL) {
13343 sds name = dictGetKey(de);
13344 struct RedisModule *module = dictGetVal(de);
13345 sds path = module->loadmod->path;
13346 addReplyMapLen(c,4);
13347 addReplyBulkCString(c,"name");
13348 addReplyBulkCBuffer(c,name,sdslen(name));
13349 addReplyBulkCString(c,"ver");
13350 addReplyLongLong(c,module->ver);
13351 addReplyBulkCString(c,"path");
13352 addReplyBulkCBuffer(c,path,sdslen(path));
13353 addReplyBulkCString(c,"args");
13354 addReplyArrayLen(c,module->loadmod->argc);
13355 for (int i = 0; i < module->loadmod->argc; i++) {
13356 addReplyBulk(c,module->loadmod->argv[i]);
13357 }
13358 }
13359 dictResetIterator(&di);
13360}
13361
13362/* Helper for genModulesInfoString(): given a list of modules, return
13363 * an SDS string in the form "[modulename|modulename2|...]" */
13364sds genModulesInfoStringRenderModulesList(list *l) {
13365 listIter li;
13366 listNode *ln;
13367 listRewind(l,&li);
13368 sds output = sdsnew("[");
13369 while((ln = listNext(&li))) {
13370 RedisModule *module = ln->value;
13371 output = sdscat(output,module->name);
13372 if (ln != listLast(l))
13373 output = sdscat(output,"|");
13374 }
13375 output = sdscat(output,"]");
13376 return output;
13377}
13378
13379/* Helper for genModulesInfoString(): render module options as an SDS string. */
13380sds genModulesInfoStringRenderModuleOptions(struct RedisModule *module) {
13381 sds output = sdsnew("[");
13382 if (module->options & REDISMODULE_OPTIONS_HANDLE_IO_ERRORS)
13383 output = sdscat(output,"handle-io-errors|");
13384 if (module->options & REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD)
13385 output = sdscat(output,"handle-repl-async-load|");
13386 if (module->options & REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED)
13387 output = sdscat(output,"no-implicit-signal-modified|");
13388 output = sdstrim(output,"|");
13389 output = sdscat(output,"]");
13390 return output;
13391}
13392
13393
13394/* Helper function for the INFO command: adds loaded modules as to info's
13395 * output.
13396 *
13397 * After the call, the passed sds info string is no longer valid and all the
13398 * references must be substituted with the new pointer returned by the call. */
13399sds genModulesInfoString(sds info) {
13400 dictIterator di;
13401 dictEntry *de;
13402
13403 dictInitIterator(&di, modules);
13404 while ((de = dictNext(&di)) != NULL) {
13405 sds name = dictGetKey(de);
13406 struct RedisModule *module = dictGetVal(de);
13407
13408 sds usedby = genModulesInfoStringRenderModulesList(module->usedby);
13409 sds using = genModulesInfoStringRenderModulesList(module->using);
13410 sds options = genModulesInfoStringRenderModuleOptions(module);
13411 info = sdscatfmt(info,
13412 "module:name=%S,ver=%i,api=%i,filters=%i,"
13413 "usedby=%S,using=%S,options=%S\r\n",
13414 name, module->ver, module->apiver,
13415 (int)listLength(module->filters), usedby, using, options);
13416 sdsfree(usedby);
13417 sdsfree(using);
13418 sdsfree(options);
13419 }
13420 dictResetIterator(&di);
13421 return info;
13422}
13423
13424/* --------------------------------------------------------------------------
13425 * Module Configurations API internals
13426 * -------------------------------------------------------------------------- */
13427
13428/* Check if the configuration name is already registered */
13429int isModuleConfigNameRegistered(RedisModule *module, const char *name) {
13430 listNode *match = listSearchKey(module->module_configs, (void *) name);
13431 return match != NULL;
13432}
13433
13434/* Assert that the flags passed into the RM_RegisterConfig Suite are valid */
13435int moduleVerifyConfigFlags(unsigned int flags, configType type) {
13436 if ((flags & ~(REDISMODULE_CONFIG_DEFAULT
13437 | REDISMODULE_CONFIG_IMMUTABLE
13438 | REDISMODULE_CONFIG_SENSITIVE
13439 | REDISMODULE_CONFIG_HIDDEN
13440 | REDISMODULE_CONFIG_PROTECTED
13441 | REDISMODULE_CONFIG_DENY_LOADING
13442 | REDISMODULE_CONFIG_BITFLAGS
13443 | REDISMODULE_CONFIG_MEMORY
13444 | REDISMODULE_CONFIG_UNPREFIXED))) {
13445 serverLogRaw(LL_WARNING, "Invalid flag(s) for configuration");
13446 return REDISMODULE_ERR;
13447 }
13448 if (type != NUMERIC_CONFIG && flags & REDISMODULE_CONFIG_MEMORY) {
13449 serverLogRaw(LL_WARNING, "Numeric flag provided for non-numeric configuration.");
13450 return REDISMODULE_ERR;
13451 }
13452 if (type != ENUM_CONFIG && flags & REDISMODULE_CONFIG_BITFLAGS) {
13453 serverLogRaw(LL_WARNING, "Enum flag provided for non-enum configuration.");
13454 return REDISMODULE_ERR;
13455 }
13456 return REDISMODULE_OK;
13457}
13458
13459/* Verify a module resource or name has only alphanumeric characters, underscores
13460 * or dashes. */
13461int moduleVerifyResourceName(const char *name) {
13462 if (name[0] == '\0') {
13463 return REDISMODULE_ERR;
13464 }
13465
13466 for (size_t i = 0; name[i] != '\0'; i++) {
13467 char curr_char = name[i];
13468 if ((curr_char >= 'a' && curr_char <= 'z') ||
13469 (curr_char >= 'A' && curr_char <= 'Z') ||
13470 (curr_char >= '0' && curr_char <= '9') ||
13471 (curr_char == '_') || (curr_char == '-'))
13472 {
13473 continue;
13474 }
13475 serverLog(LL_WARNING, "Invalid character %c in Module resource name %s.", curr_char, name);
13476 return REDISMODULE_ERR;
13477 }
13478 return REDISMODULE_OK;
13479}
13480
13481/* Verify unprefixed name config might be a single "<name>" or in the form
13482 * "<name>|<alias>". Unlike moduleVerifyResourceName(), unprefixed name config
13483 * allows a single dot in the name or alias.
13484 *
13485 * delim - Updates to point to "|" if it exists, NULL otherwise.
13486 */
13487int moduleVerifyUnprefixedName(const char *nameAlias, const char **delim) {
13488 if (nameAlias[0] == '\0')
13489 return REDISMODULE_ERR;
13490
13491 *delim = NULL;
13492 int dot_count = 0, lname = 0;
13493
13494 for (size_t i = 0; nameAlias[i] != '\0'; i++) {
13495 char ch = nameAlias[i];
13496
13497 if (((*delim) == NULL) && (ch == '|')) {
13498 /* Handle single separator between name and alias */
13499 if (!lname) {
13500 serverLog(LL_WARNING, "Module configuration name is empty: %s", nameAlias);
13501 return REDISMODULE_ERR;
13502 }
13503 *delim = &nameAlias[i];
13504 dot_count = lname = 0;
13505 } else if ( (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
13506 (ch >= '0' && ch <= '9') || (ch == '_') || (ch == '-') )
13507 {
13508 ++lname;
13509 } else if (ch == '.') {
13510 /* Allow only one dot per section (name or alias) */
13511 if (++dot_count > 1) {
13512 serverLog(LL_WARNING, "Invalid character sequence in Module configuration name or alias: %s", nameAlias);
13513 return REDISMODULE_ERR;
13514 }
13515 } else {
13516 serverLog(LL_WARNING, "Invalid character %c in Module configuration name or alias %s.", ch, nameAlias);
13517 return REDISMODULE_ERR;
13518 }
13519 }
13520
13521 if (!lname) {
13522 serverLog(LL_WARNING, "Module configuration name or alias is empty : %s", nameAlias);
13523 return REDISMODULE_ERR;
13524 }
13525
13526 return REDISMODULE_OK;
13527}
13528
13529/* This is a series of set functions for each type that act as dispatchers for
13530 * config.c to call module set callbacks. */
13531#define CONFIG_ERR_SIZE 256
13532static char configerr[CONFIG_ERR_SIZE];
13533static void propagateErrorString(RedisModuleString *err_in, const char **err) {
13534 if (err_in) {
13535 redis_strlcpy(configerr, err_in->ptr, CONFIG_ERR_SIZE);
13536 decrRefCount(err_in);
13537 *err = configerr;
13538 }
13539}
13540
13541/* If configuration was originally registered with indication to prefix the name,
13542 * return the name without the prefix by skipping prefix "<MODULE-NAME>.".
13543 * Otherwise, return the stored name as is. */
13544static char *getRegisteredConfigName(ModuleConfig *config) {
13545 if (config->unprefixedFlag)
13546 return config->name;
13547
13548 /* For prefixed configuration, find the '.' indicating the end of the prefix */
13549 char *endOfPrefix = strchr(config->name, '.');
13550 serverAssert(endOfPrefix != NULL);
13551 return endOfPrefix + 1;
13552}
13553
13554int setModuleBoolConfig(ModuleConfig *config, int val, const char **err) {
13555 RedisModuleString *error = NULL;
13556
13557 char *rname = getRegisteredConfigName(config);
13558 int return_code = config->set_fn.set_bool(rname, val, config->privdata, &error);
13559 propagateErrorString(error, err);
13560 return return_code == REDISMODULE_OK ? 1 : 0;
13561}
13562
13563int setModuleStringConfig(ModuleConfig *config, sds strval, const char **err) {
13564 RedisModuleString *error = NULL;
13565 RedisModuleString *new = createStringObject(strval, sdslen(strval));
13566
13567 char *rname = getRegisteredConfigName(config);
13568 int return_code = config->set_fn.set_string(rname, new, config->privdata, &error);
13569 propagateErrorString(error, err);
13570 decrRefCount(new);
13571 return return_code == REDISMODULE_OK ? 1 : 0;
13572}
13573
13574int setModuleEnumConfig(ModuleConfig *config, int val, const char **err) {
13575 RedisModuleString *error = NULL;
13576 int return_code = config->set_fn.set_enum(config->name, val, config->privdata, &error);
13577 propagateErrorString(error, err);
13578 return return_code == REDISMODULE_OK ? 1 : 0;
13579}
13580
13581int setModuleNumericConfig(ModuleConfig *config, long long val, const char **err) {
13582 RedisModuleString *error = NULL;
13583 char *rname = getRegisteredConfigName(config);
13584 int return_code = config->set_fn.set_numeric(rname, val, config->privdata, &error);
13585 propagateErrorString(error, err);
13586 return return_code == REDISMODULE_OK ? 1 : 0;
13587}
13588
13589/* This is a series of get functions for each type that act as dispatchers for
13590 * config.c to call module set callbacks. */
13591int getModuleBoolConfig(ModuleConfig *module_config) {
13592 char *rname = getRegisteredConfigName(module_config);
13593 return module_config->get_fn.get_bool(rname, module_config->privdata);
13594}
13595
13596sds getModuleStringConfig(ModuleConfig *module_config) {
13597 char *rname = getRegisteredConfigName(module_config);
13598 RedisModuleString *val = module_config->get_fn.get_string(rname, module_config->privdata);
13599 return val ? sdsdup(val->ptr) : NULL;
13600}
13601
13602int getModuleEnumConfig(ModuleConfig *module_config) {
13603 char *rname = getRegisteredConfigName(module_config);
13604 return module_config->get_fn.get_enum(rname, module_config->privdata);
13605}
13606
13607long long getModuleNumericConfig(ModuleConfig *module_config) {
13608 char *rname = getRegisteredConfigName(module_config);
13609 return module_config->get_fn.get_numeric(rname, module_config->privdata);
13610}
13611
13612int loadModuleDefaultConfigs(RedisModule *module) {
13613 listIter li;
13614 listNode *ln;
13615 const char *err = NULL;
13616 listRewind(module->module_configs, &li);
13617 while ((ln = listNext(&li))) {
13618 ModuleConfig *module_config = listNodeValue(ln);
13619 if (!performModuleConfigSetDefaultFromName(module_config->name, &err)) {
13620 serverLog(LL_WARNING, "Issue attempting to set default value of configuration %s : %s", module_config->name, err);
13621 return REDISMODULE_ERR;
13622 }
13623 }
13624 module->configs_initialized |= MODULE_CONFIGS_DEFAULTS;
13625 return REDISMODULE_OK;
13626}
13627
13628/* This function takes a module and a list of configs stored as sds NAME VALUE pairs.
13629 * It attempts to call set on each of these configs. */
13630int loadModuleConfigs(RedisModule *module) {
13631 listIter li;
13632 listNode *ln;
13633 const char *err = NULL;
13634 listRewind(module->module_configs, &li);
13635 const int set_default_if_missing = !(module->configs_initialized & MODULE_CONFIGS_DEFAULTS);
13636 while ((ln = listNext(&li))) {
13637 ModuleConfig *module_config = listNodeValue(ln);
13638 dictEntry *de = dictUnlink(server.module_configs_queue, module_config->name);
13639 if ((!de) && (module_config->alias))
13640 de = dictUnlink(server.module_configs_queue, module_config->alias);
13641
13642 /* If found in the queue, set the value. Otherwise, set the default value. */
13643 if (de) {
13644 if (!performModuleConfigSetFromName(dictGetKey(de), dictGetVal(de), &err)) {
13645 serverLog(LL_WARNING, "Issue during loading of configuration %s : %s", (sds) dictGetKey(de), err);
13646 dictFreeUnlinkedEntry(server.module_configs_queue, de);
13647 dictEmpty(server.module_configs_queue, NULL);
13648 return REDISMODULE_ERR;
13649 }
13650 dictFreeUnlinkedEntry(server.module_configs_queue, de);
13651 } else if (set_default_if_missing) {
13652 if (!performModuleConfigSetDefaultFromName(module_config->name, &err)) {
13653 serverLog(LL_WARNING, "Issue attempting to set default value of configuration %s : %s", module_config->name, err);
13654 dictEmpty(server.module_configs_queue, NULL);
13655 return REDISMODULE_ERR;
13656 }
13657 }
13658 }
13659 module->configs_initialized = MODULE_CONFIGS_ALL_APPLIED;
13660 return REDISMODULE_OK;
13661}
13662
13663/* Add module_config to the list if the apply and privdata do not match one already in it. */
13664void addModuleConfigApply(list *module_configs, ModuleConfig *module_config) {
13665 if (!module_config->apply_fn) return;
13666 listIter li;
13667 listNode *ln;
13668 ModuleConfig *pending_apply;
13669 listRewind(module_configs, &li);
13670 while ((ln = listNext(&li))) {
13671 pending_apply = listNodeValue(ln);
13672 if (pending_apply->apply_fn == module_config->apply_fn && pending_apply->privdata == module_config->privdata) {
13673 return;
13674 }
13675 }
13676 listAddNodeTail(module_configs, module_config);
13677}
13678
13679/* Call apply on a module config. Assumes module_config->apply_fn != NULL! */
13680int moduleConfigApplyInternal(ModuleConfig *module_config, const char **err) {
13681 RedisModuleCtx ctx;
13682 RedisModuleString *error = NULL;
13683
13684 moduleCreateContext(&ctx, module_config->module, REDISMODULE_CTX_NONE);
13685 if (module_config->apply_fn(&ctx, module_config->privdata, &error)) {
13686 propagateErrorString(error, err);
13687 moduleFreeContext(&ctx);
13688 return 0;
13689 }
13690 moduleFreeContext(&ctx);
13691 return 1;
13692}
13693
13694/* Call apply on a single module config. */
13695int moduleConfigApply(ModuleConfig *module_config, const char **err) {
13696 if (module_config->apply_fn == NULL) return 1;
13697 return moduleConfigApplyInternal(module_config, err);
13698}
13699
13700int moduleConfigNeedsApply(ModuleConfig *config) {
13701 return config->apply_fn != NULL;
13702}
13703
13704/* Call apply on all module configs specified in set, if an apply function was specified at registration time. */
13705int moduleConfigApplyConfig(list *module_configs, const char **err, const char **err_arg_name) {
13706 if (!listLength(module_configs)) return 1;
13707 listIter li;
13708 listNode *ln;
13709 ModuleConfig *module_config;
13710
13711 listRewind(module_configs, &li);
13712 while ((ln = listNext(&li))) {
13713 module_config = listNodeValue(ln);
13714 /* We know apply_fn is not NULL so skip the check */
13715 if (!moduleConfigApplyInternal(module_config, err)) {
13716 if (err_arg_name) *err_arg_name = module_config->name;
13717 return 0;
13718 }
13719 }
13720 return 1;
13721}
13722
13723/* --------------------------------------------------------------------------
13724 * ## Module Configurations API
13725 * -------------------------------------------------------------------------- */
13726
13727/* Resolve config name and create a module config object */
13728ModuleConfig *createModuleConfig(const char *name, RedisModuleConfigApplyFunc apply_fn,
13729 void *privdata, RedisModule *module, unsigned int flags)
13730{
13731 sds cname, alias = NULL;
13732
13733 /* Determine the configuration name:
13734 * - If the unprefixed flag is set, the "<MODULE-NAME>." prefix is omitted.
13735 * - An optional alias can be specified using "<NAME>|<ALIAS>".
13736 *
13737 * Examples:
13738 * - Unprefixed: "bf.initial_size" or "bf-initial-size|bf.initial_size".
13739 * - Prefixed: "initial_size" becomes "<MODULE-NAME>.initial_size".
13740 */
13741 if (flags & REDISMODULE_CONFIG_UNPREFIXED) {
13742 const char *delim = strchr(name, '|');
13743 cname = sdsnew(name);
13744 if (delim) { /* Handle "<NAME>|<ALIAS>" format */
13745 sdssubstr(cname, 0, delim - name);
13746 alias = sdsnew(delim + 1);
13747 }
13748 } else {
13749 /* Add the module name prefix */
13750 cname = sdscatfmt(sdsempty(), "%s.%s", module->name, name);
13751 }
13752
13753 ModuleConfig *new_config = zmalloc(sizeof(ModuleConfig));
13754 new_config->unprefixedFlag = flags & REDISMODULE_CONFIG_UNPREFIXED;
13755 new_config->name = cname;
13756 new_config->alias = alias;
13757 new_config->apply_fn = apply_fn;
13758 new_config->privdata = privdata;
13759 new_config->module = module;
13760 return new_config;
13761}
13762
13763/* Verify the configuration name and check for duplicates.
13764 *
13765 * - If the configuration is flagged as unprefixed, it checks for duplicate
13766 * names and optional aliases in the format <NAME>|<ALIAS>.
13767 * - If the configuration is prefixed, it ensures the name is unique with
13768 * the module name prepended (<MODULE_NAME>.<NAME>).
13769 */
13770int moduleConfigValidityCheck(RedisModule *module, const char *name, unsigned int flags, configType type) {
13771 if (!module->onload) {
13772 errno = EBUSY;
13773 return REDISMODULE_ERR;
13774 }
13775 if (moduleVerifyConfigFlags(flags, type)) {
13776 errno = EINVAL;
13777 return REDISMODULE_ERR;
13778 }
13779
13780 int isdup = 0;
13781 if (flags & REDISMODULE_CONFIG_UNPREFIXED) {
13782 const char *delim = NULL; /* Pointer to the '|' delimiter in <NAME>|<ALIAS> */
13783 if (moduleVerifyUnprefixedName(name, &delim)){
13784 errno = EINVAL;
13785 return REDISMODULE_ERR;
13786 }
13787
13788 if (delim) {
13789 /* Temporary split the "<NAME>|<ALIAS>" for the check */
13790 int count;
13791 sds *ar = sdssplitlen(name, strlen(name), "|", 1, &count);
13792 serverAssert(count == 2); /* Already validated */
13793 isdup = configExists(ar[0]) ||
13794 configExists(ar[1]) ||
13795 (sdscmp(ar[0], ar[1]) == 0);
13796 sdsfreesplitres(ar, count);
13797 } else {
13798 sds _name = sdsnew(name);
13799 isdup = configExists(_name);
13800 sdsfree(_name);
13801 }
13802 } else {
13803 if (moduleVerifyResourceName(name)) {
13804 errno = EINVAL;
13805 return REDISMODULE_ERR;
13806 }
13807
13808 sds fullname = sdscatfmt(sdsempty(), "%s.%s", module->name, name);
13809 isdup = configExists(fullname);
13810 sdsfree(fullname);
13811 }
13812
13813 if (isdup) {
13814 serverLog(LL_WARNING, "Configuration by the name: %s already registered", name);
13815 errno = EALREADY;
13816 return REDISMODULE_ERR;
13817 }
13818 return REDISMODULE_OK;
13819}
13820
13821unsigned int maskModuleConfigFlags(unsigned int flags) {
13822 unsigned int new_flags = 0;
13823 if (flags & REDISMODULE_CONFIG_DEFAULT) new_flags |= MODIFIABLE_CONFIG;
13824 if (flags & REDISMODULE_CONFIG_IMMUTABLE) new_flags |= IMMUTABLE_CONFIG;
13825 if (flags & REDISMODULE_CONFIG_HIDDEN) new_flags |= HIDDEN_CONFIG;
13826 if (flags & REDISMODULE_CONFIG_PROTECTED) new_flags |= PROTECTED_CONFIG;
13827 if (flags & REDISMODULE_CONFIG_DENY_LOADING) new_flags |= DENY_LOADING_CONFIG;
13828 return new_flags;
13829}
13830
13831unsigned int maskModuleNumericConfigFlags(unsigned int flags) {
13832 unsigned int new_flags = 0;
13833 if (flags & REDISMODULE_CONFIG_MEMORY) new_flags |= MEMORY_CONFIG;
13834 return new_flags;
13835}
13836
13837unsigned int maskModuleEnumConfigFlags(unsigned int flags) {
13838 unsigned int new_flags = 0;
13839 if (flags & REDISMODULE_CONFIG_BITFLAGS) new_flags |= MULTI_ARG_CONFIG;
13840 return new_flags;
13841}
13842
13843/* Create a string config that Redis users can interact with via the Redis config file,
13844 * `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands.
13845 *
13846 * The actual config value is owned by the module, and the `getfn`, `setfn` and optional
13847 * `applyfn` callbacks that are provided to Redis in order to access or manipulate the
13848 * value. The `getfn` callback retrieves the value from the module, while the `setfn`
13849 * callback provides a value to be stored into the module config.
13850 * The optional `applyfn` callback is called after a `CONFIG SET` command modified one or
13851 * more configs using the `setfn` callback and can be used to atomically apply a config
13852 * after several configs were changed together.
13853 * If there are multiple configs with `applyfn` callbacks set by a single `CONFIG SET`
13854 * command, they will be deduplicated if their `applyfn` function and `privdata` pointers
13855 * are identical, and the callback will only be run once.
13856 * Both the `setfn` and `applyfn` can return an error if the provided value is invalid or
13857 * cannot be used.
13858 * The config also declares a type for the value that is validated by Redis and
13859 * provided to the module. The config system provides the following types:
13860 *
13861 * * Redis String: Binary safe string data.
13862 * * Enum: One of a finite number of string tokens, provided during registration.
13863 * * Numeric: 64 bit signed integer, which also supports min and max values.
13864 * * Bool: Yes or no value.
13865 *
13866 * The `setfn` callback is expected to return REDISMODULE_OK when the value is successfully
13867 * applied. It can also return REDISMODULE_ERR if the value can't be applied, and the
13868 * *err pointer can be set with a RedisModuleString error message to provide to the client.
13869 * This RedisModuleString will be freed by redis after returning from the set callback.
13870 *
13871 * All configs are registered with a name, a type, a default value, private data that is made
13872 * available in the callbacks, as well as several flags that modify the behavior of the config.
13873 * The name must only contain alphanumeric characters or dashes. The supported flags are:
13874 *
13875 * * REDISMODULE_CONFIG_DEFAULT: The default flags for a config. This creates a config that can be modified after startup.
13876 * * REDISMODULE_CONFIG_IMMUTABLE: This config can only be provided loading time.
13877 * * REDISMODULE_CONFIG_SENSITIVE: The value stored in this config is redacted from all logging.
13878 * * REDISMODULE_CONFIG_HIDDEN: The name is hidden from `CONFIG GET` with pattern matching.
13879 * * REDISMODULE_CONFIG_PROTECTED: This config will be only be modifiable based off the value of enable-protected-configs.
13880 * * REDISMODULE_CONFIG_DENY_LOADING: This config is not modifiable while the server is loading data.
13881 * * REDISMODULE_CONFIG_MEMORY: For numeric configs, this config will convert data unit notations into their byte equivalent.
13882 * * REDISMODULE_CONFIG_BITFLAGS: For enum configs, this config will allow multiple entries to be combined as bit flags.
13883 *
13884 * Default values are used on startup to set the value if it is not provided via the config file
13885 * or command line. Default values are also used to compare to on a config rewrite.
13886 *
13887 * Notes:
13888 *
13889 * 1. On string config sets that the string passed to the set callback will be freed after execution and the module must retain it.
13890 * 2. On string config gets the string will not be consumed and will be valid after execution.
13891 *
13892 * Example implementation:
13893 *
13894 * RedisModuleString *strval;
13895 * int adjustable = 1;
13896 * RedisModuleString *getStringConfigCommand(const char *name, void *privdata) {
13897 * return strval;
13898 * }
13899 *
13900 * int setStringConfigCommand(const char *name, RedisModuleString *new, void *privdata, RedisModuleString **err) {
13901 * if (adjustable) {
13902 * RedisModule_Free(strval);
13903 * RedisModule_RetainString(NULL, new);
13904 * strval = new;
13905 * return REDISMODULE_OK;
13906 * }
13907 * *err = RedisModule_CreateString(NULL, "Not adjustable.", 15);
13908 * return REDISMODULE_ERR;
13909 * }
13910 * ...
13911 * RedisModule_RegisterStringConfig(ctx, "string", NULL, REDISMODULE_CONFIG_DEFAULT, getStringConfigCommand, setStringConfigCommand, NULL, NULL);
13912 *
13913 * If the registration fails, REDISMODULE_ERR is returned and one of the following
13914 * errno is set:
13915 * * EBUSY: Registering the Config outside of RedisModule_OnLoad.
13916 * * EINVAL: The provided flags are invalid for the registration or the name of the config contains invalid characters.
13917 * * EALREADY: The provided configuration name is already used. */
13918int RM_RegisterStringConfig(RedisModuleCtx *ctx, const char *name, const char *default_val, unsigned int flags, RedisModuleConfigGetStringFunc getfn, RedisModuleConfigSetStringFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) {
13919 RedisModule *module = ctx->module;
13920 if (moduleConfigValidityCheck(module, name, flags, NUMERIC_CONFIG)) {
13921 return REDISMODULE_ERR;
13922 }
13923
13924 ModuleConfig *mc = createModuleConfig(name, applyfn, privdata, module, flags);
13925 mc->get_fn.get_string = getfn;
13926 mc->set_fn.set_string = setfn;
13927 listAddNodeTail(module->module_configs, mc);
13928 unsigned int cflags = maskModuleConfigFlags(flags);
13929 addModuleStringConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
13930 cflags, mc, default_val ? sdsnew(default_val) : NULL);
13931 return REDISMODULE_OK;
13932}
13933
13934/* Create a bool config that server clients can interact with via the
13935 * `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. See
13936 * RedisModule_RegisterStringConfig for detailed information about configs. */
13937int RM_RegisterBoolConfig(RedisModuleCtx *ctx, const char *name, int default_val, unsigned int flags, RedisModuleConfigGetBoolFunc getfn, RedisModuleConfigSetBoolFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) {
13938 RedisModule *module = ctx->module;
13939 if (moduleConfigValidityCheck(module, name, flags, BOOL_CONFIG)) {
13940 return REDISMODULE_ERR;
13941 }
13942 ModuleConfig *mc = createModuleConfig(name, applyfn, privdata, module, flags);
13943 mc->get_fn.get_bool = getfn;
13944 mc->set_fn.set_bool = setfn;
13945 listAddNodeTail(module->module_configs, mc);
13946 unsigned int cflags = maskModuleConfigFlags(flags);
13947 addModuleBoolConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
13948 cflags, mc, default_val);
13949 return REDISMODULE_OK;
13950}
13951
13952/*
13953 * Create an enum config that server clients can interact with via the
13954 * `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands.
13955 * Enum configs are a set of string tokens to corresponding integer values, where
13956 * the string value is exposed to Redis clients but the value passed Redis and the
13957 * module is the integer value. These values are defined in enum_values, an array
13958 * of null-terminated c strings, and int_vals, an array of enum values who has an
13959 * index partner in enum_values.
13960 * Example Implementation:
13961 * const char *enum_vals[3] = {"first", "second", "third"};
13962 * const int int_vals[3] = {0, 2, 4};
13963 * int enum_val = 0;
13964 *
13965 * int getEnumConfigCommand(const char *name, void *privdata) {
13966 * return enum_val;
13967 * }
13968 *
13969 * int setEnumConfigCommand(const char *name, int val, void *privdata, const char **err) {
13970 * enum_val = val;
13971 * return REDISMODULE_OK;
13972 * }
13973 * ...
13974 * RedisModule_RegisterEnumConfig(ctx, "enum", 0, REDISMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 3, getEnumConfigCommand, setEnumConfigCommand, NULL, NULL);
13975 *
13976 * Note that you can use REDISMODULE_CONFIG_BITFLAGS so that multiple enum string
13977 * can be combined into one integer as bit flags, in which case you may want to
13978 * sort your enums so that the preferred combinations are present first.
13979 *
13980 * See RedisModule_RegisterStringConfig for detailed general information about configs. */
13981int RM_RegisterEnumConfig(RedisModuleCtx *ctx, const char *name, int default_val, unsigned int flags, const char **enum_values, const int *int_values, int num_enum_vals, RedisModuleConfigGetEnumFunc getfn, RedisModuleConfigSetEnumFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) {
13982 RedisModule *module = ctx->module;
13983 if (moduleConfigValidityCheck(module, name, flags, ENUM_CONFIG)) {
13984 return REDISMODULE_ERR;
13985 }
13986 ModuleConfig *mc = createModuleConfig(name, applyfn, privdata, module, flags);
13987 mc->get_fn.get_enum = getfn;
13988 mc->set_fn.set_enum = setfn;
13989 configEnum *enum_vals = zmalloc((num_enum_vals + 1) * sizeof(configEnum));
13990 for (int i = 0; i < num_enum_vals; i++) {
13991 enum_vals[i].name = zstrdup(enum_values[i]);
13992 enum_vals[i].val = int_values[i];
13993 }
13994 enum_vals[num_enum_vals].name = NULL;
13995 enum_vals[num_enum_vals].val = 0;
13996 listAddNodeTail(module->module_configs, mc);
13997
13998 unsigned int cflags = maskModuleConfigFlags(flags) | maskModuleEnumConfigFlags(flags);
13999 addModuleEnumConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
14000 cflags, mc, default_val, enum_vals, num_enum_vals);
14001 return REDISMODULE_OK;
14002}
14003
14004/*
14005 * Create an integer config that server clients can interact with via the
14006 * `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. See
14007 * RedisModule_RegisterStringConfig for detailed information about configs. */
14008int RM_RegisterNumericConfig(RedisModuleCtx *ctx, const char *name, long long default_val, unsigned int flags, long long min, long long max, RedisModuleConfigGetNumericFunc getfn, RedisModuleConfigSetNumericFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) {
14009 RedisModule *module = ctx->module;
14010 if (moduleConfigValidityCheck(module, name, flags, NUMERIC_CONFIG)) {
14011 return REDISMODULE_ERR;
14012 }
14013 ModuleConfig *mc = createModuleConfig(name, applyfn, privdata, module, flags);
14014 mc->get_fn.get_numeric = getfn;
14015 mc->set_fn.set_numeric = setfn;
14016 listAddNodeTail(module->module_configs, mc);
14017 unsigned int numeric_flags = maskModuleNumericConfigFlags(flags);
14018
14019 unsigned int cflags = maskModuleConfigFlags(flags);
14020 addModuleNumericConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
14021 cflags, mc, default_val, numeric_flags, min, max);
14022 return REDISMODULE_OK;
14023}
14024
14025/* Applies all default configurations for the parameters the module registered.
14026 * Only call this function if the module would like to make changes to the
14027 * configuration values before the actual values are applied by RedisModule_LoadConfigs.
14028 * Otherwise it's sufficient to call RedisModule_LoadConfigs, it should already set the default values if needed.
14029 * This makes it possible to distinguish between default values and user provided values and apply other changes between setting the defaults and the user values.
14030 * This will return REDISMODULE_ERR if it is called:
14031 * 1. outside RedisModule_OnLoad
14032 * 2. more than once
14033 * 3. after the RedisModule_LoadConfigs call */
14034int RM_LoadDefaultConfigs(RedisModuleCtx *ctx) {
14035 if (!ctx || !ctx->module || !ctx->module->onload || ctx->module->configs_initialized) {
14036 return REDISMODULE_ERR;
14037 }
14038 RedisModule *module = ctx->module;
14039 /* Load default configs of the module */
14040 return loadModuleDefaultConfigs(module);
14041}
14042
14043/* Applies all pending configurations on the module load. This should be called
14044 * after all of the configurations have been registered for the module inside of RedisModule_OnLoad.
14045 * This will return REDISMODULE_ERR if it is called outside RedisModule_OnLoad.
14046 * This API needs to be called when configurations are provided in either `MODULE LOADEX`
14047 * or provided as startup arguments. */
14048int RM_LoadConfigs(RedisModuleCtx *ctx) {
14049 if (!ctx || !ctx->module || !ctx->module->onload) {
14050 return REDISMODULE_ERR;
14051 }
14052 RedisModule *module = ctx->module;
14053 /* Load configs from conf file or arguments from loadex */
14054 return loadModuleConfigs(module);
14055}
14056
14057/* --------------------------------------------------------------------------
14058 * ## RDB load/save API
14059 * -------------------------------------------------------------------------- */
14060
14061#define REDISMODULE_RDB_STREAM_FILE 1
14062
14063typedef struct RedisModuleRdbStream {
14064 int type;
14065
14066 union {
14067 char *filename;
14068 } data;
14069} RedisModuleRdbStream;
14070
14071/* Create a stream object to save/load RDB to/from a file.
14072 *
14073 * This function returns a pointer to RedisModuleRdbStream which is owned
14074 * by the caller. It requires a call to RM_RdbStreamFree() to free
14075 * the object. */
14076RedisModuleRdbStream *RM_RdbStreamCreateFromFile(const char *filename) {
14077 RedisModuleRdbStream *stream = zmalloc(sizeof(*stream));
14078 stream->type = REDISMODULE_RDB_STREAM_FILE;
14079 stream->data.filename = zstrdup(filename);
14080 return stream;
14081}
14082
14083/* Release an RDB stream object. */
14084void RM_RdbStreamFree(RedisModuleRdbStream *stream) {
14085 switch (stream->type) {
14086 case REDISMODULE_RDB_STREAM_FILE:
14087 zfree(stream->data.filename);
14088 break;
14089 default:
14090 serverAssert(0);
14091 break;
14092 }
14093 zfree(stream);
14094}
14095
14096/* Load RDB file from the `stream`. Dataset will be cleared first and then RDB
14097 * file will be loaded.
14098 *
14099 * `flags` must be zero. This parameter is for future use.
14100 *
14101 * On success REDISMODULE_OK is returned, otherwise REDISMODULE_ERR is returned
14102 * and errno is set accordingly.
14103 *
14104 * Example:
14105 *
14106 * RedisModuleRdbStream *s = RedisModule_RdbStreamCreateFromFile("exp.rdb");
14107 * RedisModule_RdbLoad(ctx, s, 0);
14108 * RedisModule_RdbStreamFree(s);
14109 */
14110int RM_RdbLoad(RedisModuleCtx *ctx, RedisModuleRdbStream *stream, int flags) {
14111 UNUSED(ctx);
14112
14113 if (!stream || flags != 0) {
14114 errno = EINVAL;
14115 return REDISMODULE_ERR;
14116 }
14117
14118 /* Not allowed on replicas. */
14119 if (server.masterhost != NULL) {
14120 errno = ENOTSUP;
14121 return REDISMODULE_ERR;
14122 }
14123
14124 /* Drop replicas if exist. */
14125 disconnectSlaves();
14126 freeReplicationBacklog();
14127
14128 if (server.aof_state != AOF_OFF) stopAppendOnly();
14129
14130 /* Kill existing RDB fork as it is saving outdated data. Also killing it
14131 * will prevent COW memory issue. */
14132 if (server.child_type == CHILD_TYPE_RDB) killRDBChild();
14133
14134 emptyData(-1,EMPTYDB_NO_FLAGS,NULL);
14135
14136 /* rdbLoad() can go back to the networking and process network events. If
14137 * RM_RdbLoad() is called inside a command callback, we don't want to
14138 * process the current client. Otherwise, we may free the client or try to
14139 * process next message while we are already in the command callback. */
14140 if (server.current_client) protectClient(server.current_client);
14141
14142 serverAssert(stream->type == REDISMODULE_RDB_STREAM_FILE);
14143 int ret = rdbLoad(stream->data.filename,NULL,RDBFLAGS_NONE);
14144
14145 if (server.current_client) unprotectClient(server.current_client);
14146 if (server.aof_enabled) startAppendOnlyWithRetry();
14147
14148 if (ret != RDB_OK) {
14149 errno = (ret == RDB_NOT_EXIST) ? ENOENT : EIO;
14150 return REDISMODULE_ERR;
14151 }
14152
14153 errno = 0;
14154 return REDISMODULE_OK;
14155}
14156
14157/* Save dataset to the RDB stream.
14158 *
14159 * `flags` must be zero. This parameter is for future use.
14160 *
14161 * On success REDISMODULE_OK is returned, otherwise REDISMODULE_ERR is returned
14162 * and errno is set accordingly.
14163 *
14164 * Example:
14165 *
14166 * RedisModuleRdbStream *s = RedisModule_RdbStreamCreateFromFile("exp.rdb");
14167 * RedisModule_RdbSave(ctx, s, 0);
14168 * RedisModule_RdbStreamFree(s);
14169 */
14170int RM_RdbSave(RedisModuleCtx *ctx, RedisModuleRdbStream *stream, int flags) {
14171 UNUSED(ctx);
14172
14173 if (!stream || flags != 0) {
14174 errno = EINVAL;
14175 return REDISMODULE_ERR;
14176 }
14177
14178 serverAssert(stream->type == REDISMODULE_RDB_STREAM_FILE);
14179
14180 if (rdbSaveToFile(stream->data.filename) != C_OK) {
14181 return REDISMODULE_ERR;
14182 }
14183
14184 errno = 0;
14185 return REDISMODULE_OK;
14186}
14187
14188/* Returns the internal secret of the cluster.
14189 * Should be used to authenticate as an internal connection to a node in the
14190 * cluster, and by that gain the permissions to execute internal commands.
14191 */
14192const char* RM_GetInternalSecret(RedisModuleCtx *ctx, size_t *len) {
14193 UNUSED(ctx);
14194 serverAssert(len != NULL);
14195 const char *secret = clusterGetSecret(len);
14196 return secret;
14197}
14198
14199
14200/* --------------------------------------------------------------------------
14201 * ## Config access API
14202 * -------------------------------------------------------------------------- */
14203
14204/* Get an iterator to all configs.
14205 * Optional `ctx` can be provided if use of auto-memory is desired.
14206 * Optional `pattern` can be provided to filter configs by name. If `pattern` is
14207 * NULL all configs will be returned.
14208 *
14209 * The returned iterator can be used to iterate over all configs using
14210 * RedisModule_ConfigIteratorNext().
14211 *
14212 * Example usage:
14213 * ```
14214 * // Below is same as RedisModule_ConfigIteratorCreate(ctx, NULL)
14215 * RedisModuleConfigIterator *iter = RedisModule_ConfigIteratorCreate(ctx, "*");
14216 * const char *config_name = NULL;
14217 * while ((config_name = RedisModule_ConfigIteratorNext(iter)) != NULL) {
14218 * RedisModuleString *value = NULL;
14219 * if (RedisModule_ConfigGet(ctx, config_name, &value) == REDISMODULE_OK) {
14220 * // Do something with `value`...
14221 * RedisModule_FreeString(ctx, value);
14222 * }
14223 * }
14224 * RedisModule_ConfigIteratorRelease(ctx, iter);
14225 *
14226 * // Or optionally one can check the type to get the config value directly
14227 * // via the appropriate API in case performance is of consideration
14228 * iter = RedisModule_ConfigIteratorCreate(ctx, "*");
14229 * while ((config_name = RedisModule_ConfigIteratorNext(iter)) != NULL) {
14230 * RedisModuleConfigType type = RedisModule_ConfigGetType(config_name);
14231 * if (type == REDISMODULE_CONFIG_TYPE_STRING) {
14232 * RedisModuleString *value;
14233 * RedisModule_ConfigGet(ctx, config_name, &value);
14234 * // Do something with `value`...
14235 * RedisModule_FreeString(ctx, value);
14236 * } if (type == REDISMODULE_CONFIG_TYPE_NUMERIC) {
14237 * long long value;
14238 * RedisModule_ConfigGetNumeric(ctx, config_name, &value);
14239 * // Do something with `value`...
14240 * } else if (type == REDISMODULE_CONFIG_TYPE_BOOL) {
14241 * int value;
14242 * RedisModule_ConfigGetBool(ctx, config_name, &value);
14243 * // Do something with `value`...
14244 * } else if (type == REDISMODULE_CONFIG_TYPE_ENUM) {
14245 * RedisModuleString *value;
14246 * RedisModule_ConfigGetEnum(ctx, config_name, &value);
14247 * // Do something with `value`...
14248 * RedisModule_Free(value);
14249 * }
14250 * }
14251 * RedisModule_ConfigIteratorRelease(ctx, iter);
14252 * ```
14253 *
14254 * Returns a pointer to RedisModuleConfigIterator. Unless auto-memory is enabled
14255 * the caller is responsible for freeing the iterator using
14256 * RedisModule_ConfigIteratorRelease(). */
14257RedisModuleConfigIterator *RM_ConfigIteratorCreate(RedisModuleCtx *ctx, const char *pattern) {
14258 RedisModuleConfigIterator *iter = RM_Alloc(sizeof(*iter));
14259
14260 iter->di = moduleGetConfigIterator();
14261 if (pattern != NULL) {
14262 iter->pattern = sdsnew(pattern);
14263 iter->is_glob = (strpbrk(pattern, "*?[") != NULL);
14264 } else {
14265 iter->pattern = NULL;
14266 iter->is_glob = false;
14267 }
14268
14269 if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_CONFIG, iter);
14270 return iter;
14271}
14272
14273/* Release the iterator returned by RedisModule_ConfigIteratorCreate(). If auto-memory
14274 * is enabled and manual release is needed one must pass the same RedisModuleCtx
14275 * that was used to create the iterator. */
14276void RM_ConfigIteratorRelease(RedisModuleCtx *ctx, RedisModuleConfigIterator *iter) {
14277 if (ctx != NULL) autoMemoryFreed(ctx,REDISMODULE_AM_CONFIG,iter);
14278 if (iter->di) dictReleaseIterator(iter->di);
14279 sdsfree(iter->pattern);
14280 RM_Free(iter);
14281}
14282
14283static RedisModuleConfigType convertToRedisModuleConfigType(configType type) {
14284 switch (type) {
14285 case BOOL_CONFIG:
14286 return REDISMODULE_CONFIG_TYPE_BOOL;
14287 case NUMERIC_CONFIG:
14288 return REDISMODULE_CONFIG_TYPE_NUMERIC;
14289 case STRING_CONFIG:
14290 case SDS_CONFIG:
14291 case SPECIAL_CONFIG:
14292 return REDISMODULE_CONFIG_TYPE_STRING;
14293 case ENUM_CONFIG:
14294 return REDISMODULE_CONFIG_TYPE_ENUM;
14295 default:
14296 serverAssert(0);
14297 break;
14298 }
14299}
14300
14301/* Get the type of a config as RedisModuleConfigType. One may use this in order
14302 * to get or set the values of the config with the appropriate function if the
14303 * generic RedisModule_ConfigGet and RedisModule_ConfigSet APIs are performing
14304 * poorly.
14305 *
14306 * Intended usage of this function is when iteration over the configs is
14307 * performed. See RedisModule_ConfigIteratorNext() for example usage. If setting
14308 * or getting individual configs one can check the config type by hand in
14309 * redis.conf (or via other sources if config is added by a module) and use the
14310 * appropriate function without the need to call this function.
14311 *
14312 * Explanation of config types:
14313 * - REDISMODULE_CONFIG_TYPE_BOOL: Config is a boolean. One can use RedisModule_Config(Get/Set)Bool
14314 * - REDISMODULE_CONFIG_TYPE_NUMERIC: Config is a numeric value. One can use RedisModule_Config(Get/Set)Numeric
14315 * - REDISMODULE_CONFIG_TYPE_STRING: Config is a string. One can use the generic RedisModule_Config(Get/Set)
14316 * - REDISMODULE_CONFIG_TYPE_ENUM: Config is an enum. One can use RedisModule_Config(Get/Set)Enum
14317 *
14318 * If a config with the given name exists `res` is populated with its type, else
14319 * REDISMODULE_ERR is returned. */
14320int RM_ConfigGetType(const char *name, RedisModuleConfigType *res) {
14321 sds config_name = sdsnew(name);
14322 configType type;
14323 int ret = moduleGetConfigType(config_name, &type);
14324 sdsfree(config_name);
14325
14326 if (!ret)
14327 return REDISMODULE_ERR;
14328
14329 *res = convertToRedisModuleConfigType(type);
14330 return REDISMODULE_OK;
14331}
14332
14333/* Go to the next element of the config iterator.
14334 *
14335 * Returns the name of the next config, or NULL if there are no more configs.
14336 * Returned string is non-owning and thus should not be freed.
14337 * If a pattern was provided when creating the iterator, only configs matching
14338 * the pattern will be returned.
14339 *
14340 * See RedisModule_ConfigIteratorCreate() for example usage. */
14341const char *RM_ConfigIteratorNext(RedisModuleConfigIterator *iter) {
14342 return moduleConfigIteratorNext(&iter->di, iter->pattern, iter->is_glob, NULL);
14343}
14344
14345/* Get the value of a config as a string. This function can be used to get the
14346 * value of any config, regardless of its type.
14347 *
14348 * The string is allocated by the module and must be freed by the caller unless
14349 * auto memory is enabled.
14350 *
14351 * If the config does not exist, REDISMODULE_ERR is returned, else REDISMODULE_OK
14352 * is returned and `res` is populated with the value. */
14353int RM_ConfigGet(RedisModuleCtx *ctx, const char *name, RedisModuleString **res) {
14354 sds config_name = sdsnew(name);
14355 sds res_sds = NULL;
14356 int ret = moduleGetStringConfig(config_name, &res_sds);
14357 sdsfree(config_name);
14358 if (ret)
14359 *res = RM_CreateString(ctx, res_sds, sdslen(res_sds));
14360 sdsfree(res_sds);
14361 return ret ? REDISMODULE_OK : REDISMODULE_ERR;
14362}
14363
14364/* Get the value of a bool config.
14365 *
14366 * If the config does not exist or is not a bool config, REDISMODULE_ERR is
14367 * returned, else REDISMODULE_OK is returned and `res` is populated with the
14368 * value. */
14369int RM_ConfigGetBool(RedisModuleCtx *ctx, const char *name, int *res) {
14370 UNUSED(ctx);
14371 sds config_name = sdsnew(name);
14372 int ret = moduleGetBoolConfig(config_name, res);
14373 sdsfree(config_name);
14374 return ret ? REDISMODULE_OK : REDISMODULE_ERR;
14375}
14376
14377/* Get the value of an enum config.
14378 *
14379 * If the config does not exist or is not an enum config, REDISMODULE_ERR is
14380 * returned, else REDISMODULE_OK is returned and `res` is populated with the value.
14381 * If the config has multiple arguments they are returned as a space-separated
14382 * string. */
14383int RM_ConfigGetEnum(RedisModuleCtx *ctx, const char *name, RedisModuleString **res) {
14384 sds config_name = sdsnew(name);
14385 sds res_sds = NULL;
14386 int ret = moduleGetEnumConfig(config_name, &res_sds);
14387 sdsfree(config_name);
14388 if (ret)
14389 *res = RM_CreateString(ctx, res_sds, sdslen(res_sds));
14390 sdsfree(res_sds);
14391 return ret ? REDISMODULE_OK : REDISMODULE_ERR;
14392}
14393
14394/* Get the value of a numeric config.
14395 *
14396 * If the config does not exist or is not a numeric config, REDISMODULE_ERR is
14397 * returned, else REDISMODULE_OK is returned and `res` is populated with the
14398 * value. */
14399int RM_ConfigGetNumeric(RedisModuleCtx *ctx, const char *name, long long *res) {
14400 UNUSED(ctx);
14401 sds config_name = sdsnew(name);
14402 int ret = moduleGetNumericConfig(config_name, res);
14403 sdsfree(config_name);
14404 return ret ? REDISMODULE_OK : REDISMODULE_ERR;
14405}
14406
14407/* Set the value of a config.
14408 *
14409 * This function can be used to set the value of any config, regardless of its
14410 * type. If the config is multi-argument, the value must be a space-separated
14411 * string.
14412 *
14413 * If the value failed to be set REDISMODULE_ERR will be returned and if `err`
14414 * is not NULL, it will be populated with an error message. */
14415int RM_ConfigSet(RedisModuleCtx *ctx, const char *name, RedisModuleString *value, RedisModuleString **err) {
14416 sds config_name = sdsnew(name);
14417 const char *cerr = NULL;
14418 const char *val = RM_StringPtrLen(value, NULL);
14419 int res = moduleSetStringConfig(ctx->client, config_name, val, &cerr);
14420 sdsfree(config_name);
14421 if (err && cerr)
14422 *err = RM_CreateString(ctx, cerr, strlen(cerr));
14423 return (res == 0 ? REDISMODULE_ERR : REDISMODULE_OK);
14424}
14425
14426/* Set the value of a bool config.
14427 *
14428 * See RedisModule_ConfigSet for return value. */
14429int RM_ConfigSetBool(RedisModuleCtx *ctx, const char *name, int value, RedisModuleString **err) {
14430 const char *cerr = NULL;
14431 sds config_name = sdsnew(name);
14432 int res = moduleSetBoolConfig(ctx->client, config_name, value, &cerr);
14433 sdsfree(config_name);
14434 if (err && cerr)
14435 *err = RM_CreateString(ctx, cerr, strlen(cerr));
14436 return (res == 0 ? REDISMODULE_ERR : REDISMODULE_OK);
14437}
14438
14439/* Set the value of an enum config.
14440 *
14441 * If the config is multi-argument the value parameter must be a space-separated
14442 * string.
14443 *
14444 * See RedisModule_ConfigSet for return value. */
14445int RM_ConfigSetEnum(RedisModuleCtx *ctx, const char *name, RedisModuleString *value, RedisModuleString **err) {
14446 sds config_name = sdsnew(name);
14447 const char *cerr = NULL;
14448
14449 size_t len;
14450 const char *val = RM_StringPtrLen(value, &len);
14451 sds sds_val = sdsnewlen(val, len);
14452
14453 int vals_cnt = 0;
14454 sds *vals = sdssplitlen(val, sdslen(sds_val), " ", 1, &vals_cnt);
14455
14456 int res = moduleSetEnumConfig(ctx->client, config_name, vals, vals_cnt, &cerr);
14457
14458 sdsfreesplitres(vals, vals_cnt);
14459 sdsfree(sds_val);
14460 sdsfree(config_name);
14461 if (err && cerr)
14462 *err = RM_CreateString(ctx, cerr, strlen(cerr));
14463 return (res == 0 ? REDISMODULE_ERR : REDISMODULE_OK);
14464}
14465
14466/* Set the value of a numeric config.
14467 * If the value passed is meant to be a percentage, it should be passed as a
14468 * negative value.
14469 * For unsigned configs pass the value and cast to (long long) - internal type
14470 * checks will handle it.
14471 *
14472 * See RedisModule_ConfigSet for return value. */
14473int RM_ConfigSetNumeric(RedisModuleCtx *ctx, const char *name, long long value, RedisModuleString **err) {
14474 sds config_name = sdsnew(name);
14475 const char *cerr = NULL;
14476 int res = moduleSetNumericConfig(ctx->client, config_name, value, &cerr);
14477 sdsfree(config_name);
14478 if (err && cerr)
14479 *err = RM_CreateString(ctx, cerr, strlen(cerr));
14480 return (res == 0 ? REDISMODULE_ERR : REDISMODULE_OK);
14481}
14482
14483/* Redis MODULE command.
14484 *
14485 * MODULE LIST
14486 * MODULE LOAD <path> [args...]
14487 * MODULE LOADEX <path> [[CONFIG NAME VALUE] [CONFIG NAME VALUE]] [ARGS ...]
14488 * MODULE UNLOAD <name>
14489 */
14490void moduleCommand(client *c) {
14491 char *subcmd = c->argv[1]->ptr;
14492
14493 if (c->argc == 2 && !strcasecmp(subcmd,"help")) {
14494 const char *help[] = {
14495"LIST",
14496" Return a list of loaded modules.",
14497"LOAD <path> [<arg> ...]",
14498" Load a module library from <path>, passing to it any optional arguments.",
14499"LOADEX <path> [[CONFIG NAME VALUE] [CONFIG NAME VALUE]] [ARGS ...]",
14500" Load a module library from <path>, while passing it module configurations and optional arguments.",
14501"UNLOAD <name>",
14502" Unload a module.",
14503NULL
14504 };
14505 addReplyHelp(c, help);
14506 } else if (!strcasecmp(subcmd,"load") && c->argc >= 3) {
14507 robj **argv = NULL;
14508 int argc = 0;
14509
14510 if (c->argc > 3) {
14511 argc = c->argc - 3;
14512 argv = &c->argv[3];
14513 }
14514
14515 if (moduleLoad(c->argv[2]->ptr,(void **)argv,argc, 0) == C_OK)
14516 addReply(c,shared.ok);
14517 else
14518 addReplyError(c,
14519 "Error loading the extension. Please check the server logs.");
14520 } else if (!strcasecmp(subcmd,"loadex") && c->argc >= 3) {
14521 robj **argv = NULL;
14522 int argc = 0;
14523
14524 if (c->argc > 3) {
14525 argc = c->argc - 3;
14526 argv = &c->argv[3];
14527 }
14528 /* If this is a loadex command we want to populate server.module_configs_queue with
14529 * sds NAME VALUE pairs. We also want to increment argv to just after ARGS, if supplied. */
14530 if (parseLoadexArguments((RedisModuleString ***) &argv, &argc) == REDISMODULE_OK &&
14531 moduleLoad(c->argv[2]->ptr, (void **)argv, argc, 1) == C_OK)
14532 addReply(c,shared.ok);
14533 else {
14534 dictEmpty(server.module_configs_queue, NULL);
14535 addReplyError(c,
14536 "Error loading the extension. Please check the server logs.");
14537 }
14538
14539 } else if (!strcasecmp(subcmd,"unload") && c->argc == 3) {
14540 const char *errmsg = NULL;
14541 if (moduleUnload(c->argv[2]->ptr, &errmsg, 0) == C_OK)
14542 addReply(c,shared.ok);
14543 else {
14544 if (errmsg == NULL) errmsg = "operation not possible.";
14545 addReplyErrorFormat(c, "Error unloading module: %s", errmsg);
14546 serverLog(LL_WARNING, "Error unloading module %s: %s", (sds) c->argv[2]->ptr, errmsg);
14547 }
14548 } else if (!strcasecmp(subcmd,"list") && c->argc == 2) {
14549 addReplyLoadedModules(c);
14550 } else {
14551 addReplySubcommandSyntaxError(c);
14552 return;
14553 }
14554}
14555
14556/* Return the number of registered modules. */
14557size_t moduleCount(void) {
14558 return dictSize(modules);
14559}
14560
14561/* --------------------------------------------------------------------------
14562 * ## Key eviction API
14563 * -------------------------------------------------------------------------- */
14564
14565/* Set the key last access time for LRU based eviction. not relevant if the
14566 * servers's maxmemory policy is LFU based. Value is idle time in milliseconds.
14567 * returns REDISMODULE_OK if the LRU was updated, REDISMODULE_ERR otherwise. */
14568int RM_SetLRU(RedisModuleKey *key, mstime_t lru_idle) {
14569 if (!key->kv)
14570 return REDISMODULE_ERR;
14571 if (objectSetLRUOrLFU(key->kv, -1, lru_idle, lru_idle>=0 ? LRU_CLOCK() : 0, 1))
14572 return REDISMODULE_OK;
14573 return REDISMODULE_ERR;
14574}
14575
14576/* Gets the key last access time.
14577 * Value is idletime in milliseconds or -1 if the server's eviction policy is
14578 * LFU based.
14579 * returns REDISMODULE_OK if when key is valid. */
14580int RM_GetLRU(RedisModuleKey *key, mstime_t *lru_idle) {
14581 *lru_idle = -1;
14582 if (!key->kv)
14583 return REDISMODULE_ERR;
14584 if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU)
14585 return REDISMODULE_OK;
14586 *lru_idle = estimateObjectIdleTime(key->kv);
14587 return REDISMODULE_OK;
14588}
14589
14590/* Set the key access frequency. only relevant if the server's maxmemory policy
14591 * is LFU based.
14592 * The frequency is a logarithmic counter that provides an indication of
14593 * the access frequencyonly (must be <= 255).
14594 * returns REDISMODULE_OK if the LFU was updated, REDISMODULE_ERR otherwise. */
14595int RM_SetLFU(RedisModuleKey *key, long long lfu_freq) {
14596 if (!key->kv)
14597 return REDISMODULE_ERR;
14598 if (objectSetLRUOrLFU(key->kv, lfu_freq, -1, 0, 1))
14599 return REDISMODULE_OK;
14600 return REDISMODULE_ERR;
14601}
14602
14603/* Gets the key access frequency or -1 if the server's eviction policy is not
14604 * LFU based.
14605 * returns REDISMODULE_OK if when key is valid. */
14606int RM_GetLFU(RedisModuleKey *key, long long *lfu_freq) {
14607 *lfu_freq = -1;
14608 if (!key->kv)
14609 return REDISMODULE_ERR;
14610 if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU)
14611 *lfu_freq = LFUDecrAndReturn(key->kv);
14612 return REDISMODULE_OK;
14613}
14614
14615/* --------------------------------------------------------------------------
14616 * ## Miscellaneous APIs
14617 * -------------------------------------------------------------------------- */
14618
14619/**
14620 * Returns the full module options flags mask, using the return value
14621 * the module can check if a certain set of module options are supported
14622 * by the redis server version in use.
14623 * Example:
14624 *
14625 * int supportedFlags = RM_GetModuleOptionsAll();
14626 * if (supportedFlags & REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS) {
14627 * // REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is supported
14628 * } else{
14629 * // REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is not supported
14630 * }
14631 */
14632int RM_GetModuleOptionsAll(void) {
14633 return _REDISMODULE_OPTIONS_FLAGS_NEXT - 1;
14634}
14635
14636/**
14637 * Returns the full ContextFlags mask, using the return value
14638 * the module can check if a certain set of flags are supported
14639 * by the redis server version in use.
14640 * Example:
14641 *
14642 * int supportedFlags = RM_GetContextFlagsAll();
14643 * if (supportedFlags & REDISMODULE_CTX_FLAGS_MULTI) {
14644 * // REDISMODULE_CTX_FLAGS_MULTI is supported
14645 * } else{
14646 * // REDISMODULE_CTX_FLAGS_MULTI is not supported
14647 * }
14648 */
14649int RM_GetContextFlagsAll(void) {
14650 return _REDISMODULE_CTX_FLAGS_NEXT - 1;
14651}
14652
14653/**
14654 * Returns the full KeyspaceNotification mask, using the return value
14655 * the module can check if a certain set of flags are supported
14656 * by the redis server version in use.
14657 * Example:
14658 *
14659 * int supportedFlags = RM_GetKeyspaceNotificationFlagsAll();
14660 * if (supportedFlags & REDISMODULE_NOTIFY_LOADED) {
14661 * // REDISMODULE_NOTIFY_LOADED is supported
14662 * } else{
14663 * // REDISMODULE_NOTIFY_LOADED is not supported
14664 * }
14665 */
14666int RM_GetKeyspaceNotificationFlagsAll(void) {
14667 return _REDISMODULE_NOTIFY_NEXT - 1;
14668}
14669
14670/**
14671 * Return the redis version in format of 0x00MMmmpp.
14672 * Example for 6.0.7 the return value will be 0x00060007.
14673 */
14674int RM_GetServerVersion(void) {
14675 return REDIS_VERSION_NUM;
14676}
14677
14678/**
14679 * Return the current redis-server runtime value of REDISMODULE_TYPE_METHOD_VERSION.
14680 * You can use that when calling RM_CreateDataType to know which fields of
14681 * RedisModuleTypeMethods are gonna be supported and which will be ignored.
14682 */
14683int RM_GetTypeMethodVersion(void) {
14684 return REDISMODULE_TYPE_METHOD_VERSION;
14685}
14686
14687/* Replace the value assigned to a module type.
14688 *
14689 * The key must be open for writing, have an existing value, and have a moduleType
14690 * that matches the one specified by the caller.
14691 *
14692 * Unlike RM_ModuleTypeSetValue() which will free the old value, this function
14693 * simply swaps the old value with the new value.
14694 *
14695 * The function returns REDISMODULE_OK on success, REDISMODULE_ERR on errors
14696 * such as:
14697 *
14698 * 1. Key is not opened for writing.
14699 * 2. Key is not a module data type key.
14700 * 3. Key is a module datatype other than 'mt'.
14701 *
14702 * If old_value is non-NULL, the old value is returned by reference.
14703 */
14704int RM_ModuleTypeReplaceValue(RedisModuleKey *key, moduleType *mt, void *new_value, void **old_value) {
14705 if (!(key->mode & REDISMODULE_WRITE) || key->iter)
14706 return REDISMODULE_ERR;
14707 if (!key->kv || key->kv->type != OBJ_MODULE)
14708 return REDISMODULE_ERR;
14709
14710 moduleValue *mv = key->kv->ptr;
14711 if (mv->type != mt)
14712 return REDISMODULE_ERR;
14713
14714 if (old_value)
14715 *old_value = mv->value;
14716 mv->value = new_value;
14717
14718 return REDISMODULE_OK;
14719}
14720
14721/* For a specified command, parse its arguments and return an array that
14722 * contains the indexes of all key name arguments. This function is
14723 * essentially a more efficient way to do `COMMAND GETKEYS`.
14724 *
14725 * The out_flags argument is optional, and can be set to NULL.
14726 * When provided it is filled with REDISMODULE_CMD_KEY_ flags in matching
14727 * indexes with the key indexes of the returned array.
14728 *
14729 * A NULL return value indicates the specified command has no keys, or
14730 * an error condition. Error conditions are indicated by setting errno
14731 * as follows:
14732 *
14733 * * ENOENT: Specified command does not exist.
14734 * * EINVAL: Invalid command arity specified.
14735 *
14736 * NOTE: The returned array is not a Redis Module object so it does not
14737 * get automatically freed even when auto-memory is used. The caller
14738 * must explicitly call RM_Free() to free it, same as the out_flags pointer if
14739 * used.
14740 */
14741int *RM_GetCommandKeysWithFlags(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int *num_keys, int **out_flags) {
14742 UNUSED(ctx);
14743 struct redisCommand *cmd;
14744 int *res = NULL;
14745
14746 /* Find command */
14747 if ((cmd = lookupCommand(argv,argc)) == NULL) {
14748 errno = ENOENT;
14749 return NULL;
14750 }
14751
14752 /* Bail out if command has no keys */
14753 if (!doesCommandHaveKeys(cmd)) {
14754 errno = 0;
14755 return NULL;
14756 }
14757
14758 if ((cmd->arity > 0 && cmd->arity != argc) || (argc < -cmd->arity)) {
14759 errno = EINVAL;
14760 return NULL;
14761 }
14762
14763 getKeysResult result = GETKEYS_RESULT_INIT;
14764 getKeysFromCommand(cmd, argv, argc, &result);
14765
14766 *num_keys = result.numkeys;
14767 if (!result.numkeys) {
14768 errno = 0;
14769 getKeysFreeResult(&result);
14770 return NULL;
14771 }
14772
14773 /* The return value here expects an array of key positions */
14774 unsigned long int size = sizeof(int) * result.numkeys;
14775 res = zmalloc(size);
14776 if (out_flags)
14777 *out_flags = zmalloc(size);
14778 for (int i = 0; i < result.numkeys; i++) {
14779 res[i] = result.keys[i].pos;
14780 if (out_flags)
14781 (*out_flags)[i] = moduleConvertKeySpecsFlags(result.keys[i].flags, 0);
14782 }
14783
14784 getKeysFreeResult(&result);
14785 return res;
14786}
14787
14788/* Identical to RM_GetCommandKeysWithFlags when flags are not needed. */
14789int *RM_GetCommandKeys(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int *num_keys) {
14790 return RM_GetCommandKeysWithFlags(ctx, argv, argc, num_keys, NULL);
14791}
14792
14793/* Return the name of the command currently running */
14794const char *RM_GetCurrentCommandName(RedisModuleCtx *ctx) {
14795 if (!ctx || !ctx->client || !ctx->client->cmd)
14796 return NULL;
14797
14798 return (const char*)ctx->client->cmd->fullname;
14799}
14800
14801/* --------------------------------------------------------------------------
14802 * ## Defrag API
14803 * -------------------------------------------------------------------------- */
14804
14805/* Register a defrag callback for global data, i.e. anything that the module
14806 * may allocate that is not tied to a specific data type.
14807 */
14808int RM_RegisterDefragFunc(RedisModuleCtx *ctx, RedisModuleDefragFunc cb) {
14809 ctx->module->defrag_cb = cb;
14810 return REDISMODULE_OK;
14811}
14812
14813/* Register a defrag callback for global data, i.e. anything that the module
14814 * may allocate that is not tied to a specific data type.
14815 * This is a more advanced version of RM_RegisterDefragFunc, in that it takes
14816 * a callbacks that has a return value, and can use RM_DefragShouldStop
14817 * in and indicate that it should be called again later, or is it done (returned 0).
14818 */
14819int RM_RegisterDefragFunc2(RedisModuleCtx *ctx, RedisModuleDefragFunc2 cb) {
14820 ctx->module->defrag_cb_2 = cb;
14821 return REDISMODULE_OK;
14822}
14823
14824/* Register a defrag callbacks that will be called when defrag operation starts and ends.
14825 *
14826 * The callbacks are the same as `RM_RegisterDefragFunc` but the user
14827 * can also assume the callbacks are called when the defrag operation starts and ends. */
14828int RM_RegisterDefragCallbacks(RedisModuleCtx *ctx, RedisModuleDefragFunc start, RedisModuleDefragFunc end) {
14829 ctx->module->defrag_start_cb = start;
14830 ctx->module->defrag_end_cb = end;
14831 return REDISMODULE_OK;
14832}
14833
14834/* When the data type defrag callback iterates complex structures, this
14835 * function should be called periodically. A zero (false) return
14836 * indicates the callback may continue its work. A non-zero value (true)
14837 * indicates it should stop.
14838 *
14839 * When stopped, the callback may use RM_DefragCursorSet() to store its
14840 * position so it can later use RM_DefragCursorGet() to resume defragging.
14841 *
14842 * When stopped and more work is left to be done, the callback should
14843 * return 1. Otherwise, it should return 0.
14844 */
14845int RM_DefragShouldStop(RedisModuleDefragCtx *ctx) {
14846 if (ctx->stopping) /* Return immediately if already stopping */
14847 return 1;
14848 if (!ctx->endtime) /* Return if no time limit set */
14849 return 0;
14850
14851 /* We use certain thresholds to avoid excessive system calls.
14852 * Time checks are only performed when any threshold is reached,
14853 * which means we might slightly exceed the expected end time. */
14854 if (server.stat_active_defrag_hits - ctx->last_stop_check_hits >= 512 ||
14855 server.stat_active_defrag_misses - ctx->last_stop_check_misses >= 1024)
14856 {
14857 if (ctx->endtime <= getMonotonicUs()) {
14858 ctx->stopping = 1;
14859 return 1;
14860 }
14861 ctx->last_stop_check_hits = server.stat_active_defrag_hits;
14862 ctx->last_stop_check_misses = server.stat_active_defrag_misses;
14863 }
14864 return 0;
14865}
14866
14867/* Store an arbitrary cursor value for future re-use.
14868 *
14869 * This should only be called if RM_DefragShouldStop() has returned a non-zero
14870 * value and the defrag callback is about to exit without fully iterating its
14871 * data type.
14872 *
14873 * This behavior is reserved to cases where late defrag is performed. Late
14874 * defrag is selected for keys that implement the `free_effort` callback and
14875 * return a `free_effort` value that is larger than the defrag
14876 * 'active-defrag-max-scan-fields' configuration directive.
14877 *
14878 * Smaller keys, keys that do not implement `free_effort` or the global
14879 * defrag callback are not called in late-defrag mode. In those cases, a
14880 * call to this function will return REDISMODULE_ERR.
14881 *
14882 * The cursor may be used by the module to represent some progress into the
14883 * module's data type. Modules may also store additional cursor-related
14884 * information locally and use the cursor as a flag that indicates when
14885 * traversal of a new key begins. This is possible because the API makes
14886 * a guarantee that concurrent defragmentation of multiple keys will
14887 * not be performed.
14888 */
14889int RM_DefragCursorSet(RedisModuleDefragCtx *ctx, unsigned long cursor) {
14890 if (!ctx->cursor)
14891 return REDISMODULE_ERR;
14892
14893 *ctx->cursor = cursor;
14894 return REDISMODULE_OK;
14895}
14896
14897/* Fetch a cursor value that has been previously stored using RM_DefragCursorSet().
14898 *
14899 * If not called for a late defrag operation, REDISMODULE_ERR will be returned and
14900 * the cursor should be ignored. See RM_DefragCursorSet() for more details on
14901 * defrag cursors.
14902 */
14903int RM_DefragCursorGet(RedisModuleDefragCtx *ctx, unsigned long *cursor) {
14904 if (!ctx->cursor)
14905 return REDISMODULE_ERR;
14906
14907 *cursor = *ctx->cursor;
14908 return REDISMODULE_OK;
14909}
14910
14911/* Defrag a memory allocation previously allocated by RM_Alloc, RM_Calloc, etc.
14912 * The defragmentation process involves allocating a new memory block and copying
14913 * the contents to it, like realloc().
14914 *
14915 * If defragmentation was not necessary, NULL is returned and the operation has
14916 * no other effect.
14917 *
14918 * If a non-NULL value is returned, the caller should use the new pointer instead
14919 * of the old one and update any reference to the old pointer, which must not
14920 * be used again.
14921 */
14922void *RM_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr) {
14923 UNUSED(ctx);
14924 return activeDefragAlloc(ptr);
14925}
14926
14927/* Allocate memory for defrag purposes
14928 *
14929 * On the common cases user simply want to reallocate a pointer with a single
14930 * owner. For such usecase RM_DefragAlloc is enough. But on some usecases the user
14931 * might want to replace a pointer with multiple owners in different keys.
14932 * In such case, an in place replacement can not work because the other key still
14933 * keep a pointer to the old value.
14934 *
14935 * RM_DefragAllocRaw and RM_DefragFreeRaw allows to control when the memory
14936 * for defrag purposes will be allocated and when it will be freed,
14937 * allow to support more complex defrag usecases. */
14938void *RM_DefragAllocRaw(RedisModuleDefragCtx *ctx, size_t size) {
14939 UNUSED(ctx);
14940 return activeDefragAllocRaw(size);
14941}
14942
14943/* Free memory for defrag purposes
14944 *
14945 * See RM_DefragAllocRaw for more information. */
14946void RM_DefragFreeRaw(RedisModuleDefragCtx *ctx, void *ptr) {
14947 UNUSED(ctx);
14948 activeDefragFreeRaw(ptr);
14949}
14950
14951/* Defrag a RedisModuleString previously allocated by RM_Alloc, RM_Calloc, etc.
14952 * See RM_DefragAlloc() for more information on how the defragmentation process
14953 * works.
14954 *
14955 * NOTE: It is only possible to defrag strings that have a single reference.
14956 * Typically this means strings retained with RM_RetainString or RM_HoldString
14957 * may not be defragmentable. One exception is command argvs which, if retained
14958 * by the module, will end up with a single reference (because the reference
14959 * on the Redis side is dropped as soon as the command callback returns).
14960 */
14961RedisModuleString *RM_DefragRedisModuleString(RedisModuleDefragCtx *ctx, RedisModuleString *str) {
14962 UNUSED(ctx);
14963 return activeDefragStringOb(str);
14964}
14965
14966/* Defrag callback for radix tree iterator, called for each node,
14967 * used in order to defrag the nodes allocations. */
14968int moduleDefragRaxNode(raxNode **noderef, void *privdata) {
14969 UNUSED(privdata);
14970 raxNode *newnode = activeDefragAlloc(*noderef);
14971 if (newnode) {
14972 *noderef = newnode;
14973 return 1;
14974 }
14975 return 0;
14976}
14977
14978/* Defragment a Redis Module Dictionary by scanning its contents and calling a value
14979 * callback for each value.
14980 *
14981 * The callback gets the current value in the dict, and should update newptr to the new pointer,
14982 * if the value was re-allocated to a different address. The callback also gets the key name just as a reference.
14983 * The callback returns 0 when defrag is complete for this node, 1 when node needs more work.
14984 *
14985 * The API can work incrementally by accepting a seek position to continue from, and
14986 * returning the next position to seek to on the next call (or return NULL when the iteration is completed).
14987 *
14988 * This API returns a new dict if it was re-allocated to a new address (will only
14989 * be attempted when *seekTo is NULL on entry).
14990 */
14991RedisModuleDict *RM_DefragRedisModuleDict(RedisModuleDefragCtx *ctx, RedisModuleDict *dict, RedisModuleDefragDictValueCallback valueCB, RedisModuleString **seekTo) {
14992 RedisModuleDict *newdict = NULL;
14993 raxIterator ri;
14994
14995 if (*seekTo == NULL) {
14996 /* if last seek is NULL, we start new iteration */
14997 rax* newrax = NULL;
14998 if ((newdict = activeDefragAlloc(dict)))
14999 dict = newdict;
15000 if ((newrax = activeDefragAlloc(dict->rax)))
15001 dict->rax = newrax;
15002 }
15003
15004 raxStart(&ri,dict->rax);
15005 if (*seekTo == NULL) {
15006 /* if last seek is NULL, we start new iteration */
15007 moduleDefragRaxNode(&dict->rax->head, NULL);
15008 /* assign the iterator node callback before the seek, so that the
15009 * initial nodes that are processed till the first item are covered */
15010 ri.node_cb = moduleDefragRaxNode;
15011 raxSeek(&ri,"^",NULL,0);
15012 } else {
15013 /* Seek to the static 'seekTo'. */
15014 if (!raxSeek(&ri,">=", (*seekTo)->ptr, sdslen((*seekTo)->ptr))) {
15015 goto cleanup;
15016 }
15017 /* assign the iterator node callback after the seek, so that the
15018 * initial nodes that are processed till now aren't covered */
15019 ri.node_cb = moduleDefragRaxNode;
15020 }
15021
15022 while (raxNext(&ri)) {
15023 int ret = 0;
15024 void *newdata = NULL;
15025
15026 if (valueCB) {
15027 ret = valueCB(ctx, ri.data, ri.key, ri.key_len, &newdata);
15028 if (newdata)
15029 raxSetData(ri.node, ri.data=newdata);
15030 }
15031
15032 /* Check if we need to interrupt defragmentation.
15033 * - For explicit interruption, use current position
15034 * - For timeout interruption, try to advance to next node if possible */
15035 if (ret == 1 || RM_DefragShouldStop(ctx)) {
15036 if (ret == 0 && !raxNext(&ri)) goto cleanup; /* Last node and no more work needed. */
15037 if (*seekTo) RM_FreeString(NULL, *seekTo);
15038 *seekTo = RM_CreateString(NULL, (const char *)ri.key, ri.key_len);
15039 raxStop(&ri);
15040 return newdict;
15041 }
15042 }
15043cleanup:
15044 if (*seekTo) RM_FreeString(NULL, *seekTo);
15045 *seekTo = NULL;
15046 raxStop(&ri);
15047 return newdict;
15048}
15049
15050/* Perform a late defrag of a module datatype key.
15051 *
15052 * Returns a zero value (and initializes the cursor) if no more needs to be done,
15053 * or a non-zero value otherwise.
15054 */
15055int moduleLateDefrag(robj *key, robj *value, unsigned long *cursor, monotime endtime, int dbid) {
15056 moduleValue *mv = value->ptr;
15057 moduleType *mt = mv->type;
15058
15059 /* Interval shouldn't exceed 1 hour. */
15060 serverAssert(!endtime || llabs((long long)endtime - (long long)getMonotonicUs()) < 60*60*1000*1000LL);
15061
15062 RedisModuleDefragCtx defrag_ctx = INIT_MODULE_DEFRAG_CTX(endtime, cursor, key, dbid);
15063
15064 /* Invoke callback. Note that the callback may be missing if the key has been
15065 * replaced with a different type since our last visit.
15066 */
15067 int ret = 0;
15068 if (mt->defrag)
15069 ret = mt->defrag(&defrag_ctx, key, &mv->value);
15070
15071 if (!ret) {
15072 *cursor = 0; /* No more work to do */
15073 return 0;
15074 }
15075
15076 return 1;
15077}
15078
15079/* Attempt to defrag a module data type value. Depending on complexity,
15080 * the operation may happen immediately or be scheduled for later.
15081 *
15082 * Returns 1 if the operation has been completed or 0 if it needs to
15083 * be scheduled for late defrag.
15084 */
15085int moduleDefragValue(robj *key, robj *value, int dbid) {
15086 moduleValue *mv = value->ptr;
15087 moduleType *mt = mv->type;
15088
15089 /* Try to defrag moduleValue itself regardless of whether or not
15090 * defrag callbacks are provided.
15091 */
15092 moduleValue *newmv = activeDefragAlloc(mv);
15093 if (newmv) {
15094 value->ptr = mv = newmv;
15095 }
15096
15097 if (!mt->defrag)
15098 return 1;
15099
15100 /* Use free_effort to determine complexity of module value, and if
15101 * necessary schedule it for defragLater instead of quick immediate
15102 * defrag.
15103 */
15104 size_t effort = moduleGetFreeEffort(key, value, dbid);
15105 if (!effort)
15106 effort = SIZE_MAX;
15107 if (effort > server.active_defrag_max_scan_fields) {
15108 return 0; /* Defrag later */
15109 }
15110
15111 RedisModuleDefragCtx defrag_ctx = INIT_MODULE_DEFRAG_CTX(0, NULL, key, dbid);
15112 mt->defrag(&defrag_ctx, key, &mv->value);
15113 return 1;
15114}
15115
15116/* Call registered module API defrag start functions */
15117void moduleDefragStart(void) {
15118 dictForEach(modules, struct RedisModule, module,
15119 if (module->defrag_start_cb) {
15120 RedisModuleDefragCtx defrag_ctx = INIT_MODULE_DEFRAG_CTX(0, NULL, NULL, -1);
15121 module->defrag_start_cb(&defrag_ctx);
15122 }
15123 );
15124}
15125
15126/* Call registered module API defrag end functions */
15127void moduleDefragEnd(void) {
15128 dictForEach(modules, struct RedisModule, module,
15129 if (module->defrag_end_cb) {
15130 RedisModuleDefragCtx defrag_ctx = INIT_MODULE_DEFRAG_CTX(0, NULL, NULL, -1);
15131 module->defrag_end_cb(&defrag_ctx);
15132 }
15133 );
15134}
15135
15136/* Returns the name of the key currently being processed.
15137 * There is no guarantee that the key name is always available, so this may return NULL.
15138 */
15139const RedisModuleString *RM_GetKeyNameFromDefragCtx(RedisModuleDefragCtx *ctx) {
15140 return ctx->key;
15141}
15142
15143/* Returns the database id of the key currently being processed.
15144 * There is no guarantee that this info is always available, so this may return -1.
15145 */
15146int RM_GetDbIdFromDefragCtx(RedisModuleDefragCtx *ctx) {
15147 return ctx->dbid;
15148}
15149
15150/* Register all the APIs we export. Keep this function at the end of the
15151 * file so that's easy to seek it to add new entries. */
15152void moduleRegisterCoreAPI(void) {
15153 server.moduleapi = dictCreate(&moduleAPIDictType);
15154 server.sharedapi = dictCreate(&moduleAPIDictType);
15155 REGISTER_API(Alloc);
15156 REGISTER_API(TryAlloc);
15157 REGISTER_API(Calloc);
15158 REGISTER_API(TryCalloc);
15159 REGISTER_API(Realloc);
15160 REGISTER_API(TryRealloc);
15161 REGISTER_API(Free);
15162 REGISTER_API(Strdup);
15163 REGISTER_API(CreateCommand);
15164 REGISTER_API(GetCommand);
15165 REGISTER_API(CreateSubcommand);
15166 REGISTER_API(SetCommandInfo);
15167 REGISTER_API(SetCommandACLCategories);
15168 REGISTER_API(AddACLCategory);
15169 REGISTER_API(SetModuleAttribs);
15170 REGISTER_API(IsModuleNameBusy);
15171 REGISTER_API(WrongArity);
15172 REGISTER_API(ReplyWithLongLong);
15173 REGISTER_API(ReplyWithError);
15174 REGISTER_API(ReplyWithErrorFormat);
15175 REGISTER_API(ReplyWithSimpleString);
15176 REGISTER_API(ReplyWithArray);
15177 REGISTER_API(ReplyWithMap);
15178 REGISTER_API(ReplyWithSet);
15179 REGISTER_API(ReplyWithAttribute);
15180 REGISTER_API(ReplyWithNullArray);
15181 REGISTER_API(ReplyWithEmptyArray);
15182 REGISTER_API(ReplySetArrayLength);
15183 REGISTER_API(ReplySetMapLength);
15184 REGISTER_API(ReplySetSetLength);
15185 REGISTER_API(ReleaseKeyMetaClass);
15186 REGISTER_API(ReplySetAttributeLength);
15187 REGISTER_API(ReplyWithString);
15188 REGISTER_API(ReplyWithEmptyString);
15189 REGISTER_API(ReplyWithVerbatimString);
15190 REGISTER_API(ReplyWithVerbatimStringType);
15191 REGISTER_API(ReplyWithStringBuffer);
15192 REGISTER_API(CreateKeyMetaClass);
15193 REGISTER_API(SetKeyMeta);
15194 REGISTER_API(GetKeyMeta);
15195 REGISTER_API(ReplyWithCString);
15196 REGISTER_API(ReplyWithNull);
15197 REGISTER_API(ReplyWithBool);
15198 REGISTER_API(ReplyWithCallReply);
15199 REGISTER_API(ReplyWithDouble);
15200 REGISTER_API(ReplyWithBigNumber);
15201 REGISTER_API(ReplyWithLongDouble);
15202 REGISTER_API(GetSelectedDb);
15203 REGISTER_API(SelectDb);
15204 REGISTER_API(KeyExists);
15205 REGISTER_API(OpenKey);
15206 REGISTER_API(GetOpenKeyModesAll);
15207 REGISTER_API(CloseKey);
15208 REGISTER_API(KeyType);
15209 REGISTER_API(ValueLength);
15210 REGISTER_API(ListPush);
15211 REGISTER_API(ListPop);
15212 REGISTER_API(ListGet);
15213 REGISTER_API(ListSet);
15214 REGISTER_API(ListInsert);
15215 REGISTER_API(ListDelete);
15216 REGISTER_API(StringToLongLong);
15217 REGISTER_API(StringToULongLong);
15218 REGISTER_API(StringToDouble);
15219 REGISTER_API(StringToLongDouble);
15220 REGISTER_API(StringToStreamID);
15221 REGISTER_API(Call);
15222 REGISTER_API(CallReplyProto);
15223 REGISTER_API(FreeCallReply);
15224 REGISTER_API(CallReplyInteger);
15225 REGISTER_API(CallReplyDouble);
15226 REGISTER_API(CallReplyBigNumber);
15227 REGISTER_API(CallReplyVerbatim);
15228 REGISTER_API(CallReplyBool);
15229 REGISTER_API(CallReplySetElement);
15230 REGISTER_API(CallReplyMapElement);
15231 REGISTER_API(CallReplyAttributeElement);
15232 REGISTER_API(CallReplyPromiseSetUnblockHandler);
15233 REGISTER_API(CallReplyPromiseAbort);
15234 REGISTER_API(CallReplyAttribute);
15235 REGISTER_API(CallReplyType);
15236 REGISTER_API(CallReplyLength);
15237 REGISTER_API(CallReplyArrayElement);
15238 REGISTER_API(CallReplyStringPtr);
15239 REGISTER_API(CreateStringFromCallReply);
15240 REGISTER_API(CreateString);
15241 REGISTER_API(CreateStringFromLongLong);
15242 REGISTER_API(CreateStringFromULongLong);
15243 REGISTER_API(CreateStringFromDouble);
15244 REGISTER_API(CreateStringFromLongDouble);
15245 REGISTER_API(CreateStringFromString);
15246 REGISTER_API(CreateStringFromStreamID);
15247 REGISTER_API(CreateStringPrintf);
15248 REGISTER_API(FreeString);
15249 REGISTER_API(StringPtrLen);
15250 REGISTER_API(AutoMemory);
15251 REGISTER_API(Replicate);
15252 REGISTER_API(ReplicateVerbatim);
15253 REGISTER_API(DeleteKey);
15254 REGISTER_API(UnlinkKey);
15255 REGISTER_API(StringSet);
15256 REGISTER_API(StringDMA);
15257 REGISTER_API(StringTruncate);
15258 REGISTER_API(SetExpire);
15259 REGISTER_API(GetExpire);
15260 REGISTER_API(SetAbsExpire);
15261 REGISTER_API(GetAbsExpire);
15262 REGISTER_API(ResetDataset);
15263 REGISTER_API(DbSize);
15264 REGISTER_API(RandomKey);
15265 REGISTER_API(ZsetAdd);
15266 REGISTER_API(ZsetIncrby);
15267 REGISTER_API(ZsetScore);
15268 REGISTER_API(ZsetRem);
15269 REGISTER_API(ZsetRangeStop);
15270 REGISTER_API(ZsetFirstInScoreRange);
15271 REGISTER_API(ZsetLastInScoreRange);
15272 REGISTER_API(ZsetFirstInLexRange);
15273 REGISTER_API(ZsetLastInLexRange);
15274 REGISTER_API(ZsetRangeCurrentElement);
15275 REGISTER_API(ZsetRangeNext);
15276 REGISTER_API(ZsetRangePrev);
15277 REGISTER_API(ZsetRangeEndReached);
15278 REGISTER_API(HashSet);
15279 REGISTER_API(HashGet);
15280 REGISTER_API(HashFieldMinExpire);
15281 REGISTER_API(StreamAdd);
15282 REGISTER_API(StreamDelete);
15283 REGISTER_API(StreamIteratorStart);
15284 REGISTER_API(StreamIteratorStop);
15285 REGISTER_API(StreamIteratorNextID);
15286 REGISTER_API(StreamIteratorNextField);
15287 REGISTER_API(StreamIteratorDelete);
15288 REGISTER_API(StreamTrimByLength);
15289 REGISTER_API(StreamTrimByID);
15290 REGISTER_API(IsKeysPositionRequest);
15291 REGISTER_API(KeyAtPos);
15292 REGISTER_API(KeyAtPosWithFlags);
15293 REGISTER_API(IsChannelsPositionRequest);
15294 REGISTER_API(ChannelAtPosWithFlags);
15295 REGISTER_API(GetClientId);
15296 REGISTER_API(GetClientUserNameById);
15297 REGISTER_API(GetContextFlags);
15298 REGISTER_API(AvoidReplicaTraffic);
15299 REGISTER_API(PoolAlloc);
15300 REGISTER_API(CreateDataType);
15301 REGISTER_API(ModuleTypeSetValue);
15302 REGISTER_API(ModuleTypeReplaceValue);
15303 REGISTER_API(ModuleTypeGetType);
15304 REGISTER_API(ModuleTypeGetValue);
15305 REGISTER_API(IsIOError);
15306 REGISTER_API(SetModuleOptions);
15307 REGISTER_API(SignalModifiedKey);
15308 REGISTER_API(SaveUnsigned);
15309 REGISTER_API(LoadUnsigned);
15310 REGISTER_API(SaveSigned);
15311 REGISTER_API(LoadSigned);
15312 REGISTER_API(SaveString);
15313 REGISTER_API(SaveStringBuffer);
15314 REGISTER_API(LoadString);
15315 REGISTER_API(LoadStringBuffer);
15316 REGISTER_API(SaveDouble);
15317 REGISTER_API(LoadDouble);
15318 REGISTER_API(SaveFloat);
15319 REGISTER_API(LoadFloat);
15320 REGISTER_API(SaveLongDouble);
15321 REGISTER_API(LoadLongDouble);
15322 REGISTER_API(SaveDataTypeToString);
15323 REGISTER_API(LoadDataTypeFromString);
15324 REGISTER_API(LoadDataTypeFromStringEncver);
15325 REGISTER_API(EmitAOF);
15326 REGISTER_API(Log);
15327 REGISTER_API(LogIOError);
15328 REGISTER_API(_Assert);
15329 REGISTER_API(LatencyAddSample);
15330 REGISTER_API(StringAppendBuffer);
15331 REGISTER_API(TrimStringAllocation);
15332 REGISTER_API(RetainString);
15333 REGISTER_API(HoldString);
15334 REGISTER_API(StringCompare);
15335 REGISTER_API(GetContextFromIO);
15336 REGISTER_API(GetKeyNameFromIO);
15337 REGISTER_API(GetKeyNameFromModuleKey);
15338 REGISTER_API(GetDbIdFromModuleKey);
15339 REGISTER_API(GetDbIdFromIO);
15340 REGISTER_API(GetKeyNameFromOptCtx);
15341 REGISTER_API(GetToKeyNameFromOptCtx);
15342 REGISTER_API(GetDbIdFromOptCtx);
15343 REGISTER_API(GetToDbIdFromOptCtx);
15344 REGISTER_API(GetKeyNameFromDefragCtx);
15345 REGISTER_API(GetDbIdFromDefragCtx);
15346 REGISTER_API(GetKeyNameFromDigest);
15347 REGISTER_API(GetDbIdFromDigest);
15348 REGISTER_API(BlockClient);
15349 REGISTER_API(BlockClientGetPrivateData);
15350 REGISTER_API(BlockClientSetPrivateData);
15351 REGISTER_API(BlockClientOnAuth);
15352 REGISTER_API(UnblockClient);
15353 REGISTER_API(IsBlockedReplyRequest);
15354 REGISTER_API(IsBlockedTimeoutRequest);
15355 REGISTER_API(GetBlockedClientPrivateData);
15356 REGISTER_API(AbortBlock);
15357 REGISTER_API(Milliseconds);
15358 REGISTER_API(MonotonicMicroseconds);
15359 REGISTER_API(Microseconds);
15360 REGISTER_API(CachedMicroseconds);
15361 REGISTER_API(BlockedClientMeasureTimeStart);
15362 REGISTER_API(BlockedClientMeasureTimeEnd);
15363 REGISTER_API(GetThreadSafeContext);
15364 REGISTER_API(GetDetachedThreadSafeContext);
15365 REGISTER_API(FreeThreadSafeContext);
15366 REGISTER_API(ThreadSafeContextLock);
15367 REGISTER_API(ThreadSafeContextTryLock);
15368 REGISTER_API(ThreadSafeContextUnlock);
15369 REGISTER_API(DigestAddStringBuffer);
15370 REGISTER_API(DigestAddLongLong);
15371 REGISTER_API(DigestEndSequence);
15372 REGISTER_API(NotifyKeyspaceEvent);
15373 REGISTER_API(GetNotifyKeyspaceEvents);
15374 REGISTER_API(SubscribeToKeyspaceEvents);
15375 REGISTER_API(UnsubscribeFromKeyspaceEvents);
15376 REGISTER_API(AddPostNotificationJob);
15377 REGISTER_API(RegisterClusterMessageReceiver);
15378 REGISTER_API(SendClusterMessage);
15379 REGISTER_API(GetClusterNodeInfo);
15380 REGISTER_API(GetClusterNodesList);
15381 REGISTER_API(FreeClusterNodesList);
15382 REGISTER_API(CreateTimer);
15383 REGISTER_API(StopTimer);
15384 REGISTER_API(GetTimerInfo);
15385 REGISTER_API(GetMyClusterID);
15386 REGISTER_API(GetClusterSize);
15387 REGISTER_API(GetRandomBytes);
15388 REGISTER_API(GetRandomHexChars);
15389 REGISTER_API(BlockedClientDisconnected);
15390 REGISTER_API(SetDisconnectCallback);
15391 REGISTER_API(GetBlockedClientHandle);
15392 REGISTER_API(SetClusterFlags);
15393 REGISTER_API(ClusterDisableTrim);
15394 REGISTER_API(ClusterEnableTrim);
15395 REGISTER_API(ClusterKeySlot);
15396 REGISTER_API(ClusterKeySlotC);
15397 REGISTER_API(ClusterCanonicalKeyNameInSlot);
15398 REGISTER_API(ClusterCanAccessKeysInSlot);
15399 REGISTER_API(ClusterPropagateForSlotMigration);
15400 REGISTER_API(ClusterGetLocalSlotRanges);
15401 REGISTER_API(ClusterFreeSlotRanges);
15402 REGISTER_API(CreateDict);
15403 REGISTER_API(FreeDict);
15404 REGISTER_API(DictSize);
15405 REGISTER_API(DictSetC);
15406 REGISTER_API(DictReplaceC);
15407 REGISTER_API(DictSet);
15408 REGISTER_API(DictReplace);
15409 REGISTER_API(DictGetC);
15410 REGISTER_API(DictGet);
15411 REGISTER_API(DictDelC);
15412 REGISTER_API(DictDel);
15413 REGISTER_API(DictIteratorStartC);
15414 REGISTER_API(DictIteratorStart);
15415 REGISTER_API(DictIteratorStop);
15416 REGISTER_API(DictIteratorReseekC);
15417 REGISTER_API(DictIteratorReseek);
15418 REGISTER_API(DictNextC);
15419 REGISTER_API(DictPrevC);
15420 REGISTER_API(DictNext);
15421 REGISTER_API(DictPrev);
15422 REGISTER_API(DictCompareC);
15423 REGISTER_API(DictCompare);
15424 REGISTER_API(ExportSharedAPI);
15425 REGISTER_API(GetSharedAPI);
15426 REGISTER_API(RegisterCommandFilter);
15427 REGISTER_API(UnregisterCommandFilter);
15428 REGISTER_API(CommandFilterArgsCount);
15429 REGISTER_API(CommandFilterArgGet);
15430 REGISTER_API(CommandFilterArgInsert);
15431 REGISTER_API(CommandFilterArgReplace);
15432 REGISTER_API(CommandFilterArgDelete);
15433 REGISTER_API(CommandFilterGetClientId);
15434 REGISTER_API(Fork);
15435 REGISTER_API(SendChildHeartbeat);
15436 REGISTER_API(ExitFromChild);
15437 REGISTER_API(KillForkChild);
15438 REGISTER_API(RegisterInfoFunc);
15439 REGISTER_API(InfoAddSection);
15440 REGISTER_API(InfoBeginDictField);
15441 REGISTER_API(InfoEndDictField);
15442 REGISTER_API(InfoAddFieldString);
15443 REGISTER_API(InfoAddFieldCString);
15444 REGISTER_API(InfoAddFieldDouble);
15445 REGISTER_API(InfoAddFieldLongLong);
15446 REGISTER_API(InfoAddFieldULongLong);
15447 REGISTER_API(GetServerInfo);
15448 REGISTER_API(FreeServerInfo);
15449 REGISTER_API(ServerInfoGetField);
15450 REGISTER_API(ServerInfoGetFieldC);
15451 REGISTER_API(ServerInfoGetFieldSigned);
15452 REGISTER_API(ServerInfoGetFieldUnsigned);
15453 REGISTER_API(ServerInfoGetFieldDouble);
15454 REGISTER_API(GetClientInfoById);
15455 REGISTER_API(GetClientNameById);
15456 REGISTER_API(SetClientNameById);
15457 REGISTER_API(PublishMessage);
15458 REGISTER_API(PublishMessageShard);
15459 REGISTER_API(SubscribeToServerEvent);
15460 REGISTER_API(SetLRU);
15461 REGISTER_API(GetLRU);
15462 REGISTER_API(SetLFU);
15463 REGISTER_API(GetLFU);
15464 REGISTER_API(BlockClientOnKeys);
15465 REGISTER_API(BlockClientOnKeysWithFlags);
15466 REGISTER_API(SignalKeyAsReady);
15467 REGISTER_API(GetBlockedClientReadyKey);
15468 REGISTER_API(GetUsedMemoryRatio);
15469 REGISTER_API(MallocSize);
15470 REGISTER_API(MallocUsableSize);
15471 REGISTER_API(MallocSizeString);
15472 REGISTER_API(MallocSizeDict);
15473 REGISTER_API(ScanCursorCreate);
15474 REGISTER_API(ScanCursorDestroy);
15475 REGISTER_API(ScanCursorRestart);
15476 REGISTER_API(Scan);
15477 REGISTER_API(ScanKey);
15478 REGISTER_API(CreateModuleUser);
15479 REGISTER_API(SetContextUser);
15480 REGISTER_API(SetModuleUserACL);
15481 REGISTER_API(SetModuleUserACLString);
15482 REGISTER_API(GetModuleUserACLString);
15483 REGISTER_API(GetCurrentUserName);
15484 REGISTER_API(GetModuleUserFromUserName);
15485 REGISTER_API(ACLCheckCommandPermissions);
15486 REGISTER_API(ACLCheckKeyPermissions);
15487 REGISTER_API(ACLCheckKeyPrefixPermissions);
15488 REGISTER_API(ACLCheckChannelPermissions);
15489 REGISTER_API(ACLAddLogEntry);
15490 REGISTER_API(ACLAddLogEntryByUserName);
15491 REGISTER_API(FreeModuleUser);
15492 REGISTER_API(DeauthenticateAndCloseClient);
15493 REGISTER_API(AuthenticateClientWithACLUser);
15494 REGISTER_API(AuthenticateClientWithUser);
15495 REGISTER_API(GetContextFlagsAll);
15496 REGISTER_API(GetModuleOptionsAll);
15497 REGISTER_API(GetKeyspaceNotificationFlagsAll);
15498 REGISTER_API(IsSubEventSupported);
15499 REGISTER_API(GetServerVersion);
15500 REGISTER_API(GetClientCertificate);
15501 REGISTER_API(RedactClientCommandArgument);
15502 REGISTER_API(GetCommandKeys);
15503 REGISTER_API(GetCommandKeysWithFlags);
15504 REGISTER_API(GetCurrentCommandName);
15505 REGISTER_API(GetTypeMethodVersion);
15506 REGISTER_API(RegisterDefragFunc);
15507 REGISTER_API(RegisterDefragFunc2);
15508 REGISTER_API(RegisterDefragCallbacks);
15509 REGISTER_API(DefragAlloc);
15510 REGISTER_API(DefragAllocRaw);
15511 REGISTER_API(DefragFreeRaw);
15512 REGISTER_API(DefragRedisModuleString);
15513 REGISTER_API(DefragRedisModuleDict);
15514 REGISTER_API(DefragShouldStop);
15515 REGISTER_API(DefragCursorSet);
15516 REGISTER_API(DefragCursorGet);
15517 REGISTER_API(EventLoopAdd);
15518 REGISTER_API(EventLoopDel);
15519 REGISTER_API(EventLoopAddOneShot);
15520 REGISTER_API(Yield);
15521 REGISTER_API(RegisterBoolConfig);
15522 REGISTER_API(RegisterNumericConfig);
15523 REGISTER_API(RegisterStringConfig);
15524 REGISTER_API(RegisterEnumConfig);
15525 REGISTER_API(LoadDefaultConfigs);
15526 REGISTER_API(LoadConfigs);
15527 REGISTER_API(RegisterAuthCallback);
15528 REGISTER_API(RdbStreamCreateFromFile);
15529 REGISTER_API(RdbStreamFree);
15530 REGISTER_API(RdbLoad);
15531 REGISTER_API(RdbSave);
15532 REGISTER_API(GetInternalSecret);
15533 REGISTER_API(ConfigIteratorCreate);
15534 REGISTER_API(ConfigIteratorRelease);
15535 REGISTER_API(ConfigIteratorNext);
15536 REGISTER_API(ConfigGetType);
15537 REGISTER_API(ConfigGet);
15538 REGISTER_API(ConfigGetBool);
15539 REGISTER_API(ConfigGetEnum);
15540 REGISTER_API(ConfigGetNumeric);
15541 REGISTER_API(ConfigSet);
15542 REGISTER_API(ConfigSetBool);
15543 REGISTER_API(ConfigSetEnum);
15544 REGISTER_API(ConfigSetNumeric);
15545}