xref: /f-stack/app/redis-5.0.5/src/module.c (revision 572c4311)
1*572c4311Sfengbojiang /*
2*572c4311Sfengbojiang  * Copyright (c) 2016, Salvatore Sanfilippo <antirez at gmail dot com>
3*572c4311Sfengbojiang  * All rights reserved.
4*572c4311Sfengbojiang  *
5*572c4311Sfengbojiang  * Redistribution and use in source and binary forms, with or without
6*572c4311Sfengbojiang  * modification, are permitted provided that the following conditions are met:
7*572c4311Sfengbojiang  *
8*572c4311Sfengbojiang  *   * Redistributions of source code must retain the above copyright notice,
9*572c4311Sfengbojiang  *     this list of conditions and the following disclaimer.
10*572c4311Sfengbojiang  *   * Redistributions in binary form must reproduce the above copyright
11*572c4311Sfengbojiang  *     notice, this list of conditions and the following disclaimer in the
12*572c4311Sfengbojiang  *     documentation and/or other materials provided with the distribution.
13*572c4311Sfengbojiang  *   * Neither the name of Redis nor the names of its contributors may be used
14*572c4311Sfengbojiang  *     to endorse or promote products derived from this software without
15*572c4311Sfengbojiang  *     specific prior written permission.
16*572c4311Sfengbojiang  *
17*572c4311Sfengbojiang  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18*572c4311Sfengbojiang  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*572c4311Sfengbojiang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*572c4311Sfengbojiang  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21*572c4311Sfengbojiang  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*572c4311Sfengbojiang  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*572c4311Sfengbojiang  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*572c4311Sfengbojiang  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*572c4311Sfengbojiang  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*572c4311Sfengbojiang  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*572c4311Sfengbojiang  * POSSIBILITY OF SUCH DAMAGE.
28*572c4311Sfengbojiang  */
29*572c4311Sfengbojiang 
30*572c4311Sfengbojiang #include "server.h"
31*572c4311Sfengbojiang #include "cluster.h"
32*572c4311Sfengbojiang #include <dlfcn.h>
33*572c4311Sfengbojiang 
34*572c4311Sfengbojiang #define REDISMODULE_CORE 1
35*572c4311Sfengbojiang #include "redismodule.h"
36*572c4311Sfengbojiang 
37*572c4311Sfengbojiang /* --------------------------------------------------------------------------
38*572c4311Sfengbojiang  * Private data structures used by the modules system. Those are data
39*572c4311Sfengbojiang  * structures that are never exposed to Redis Modules, if not as void
40*572c4311Sfengbojiang  * pointers that have an API the module can call with them)
41*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
42*572c4311Sfengbojiang 
43*572c4311Sfengbojiang /* This structure represents a module inside the system. */
44*572c4311Sfengbojiang struct RedisModule {
45*572c4311Sfengbojiang     void *handle;   /* Module dlopen() handle. */
46*572c4311Sfengbojiang     char *name;     /* Module name. */
47*572c4311Sfengbojiang     int ver;        /* Module version. We use just progressive integers. */
48*572c4311Sfengbojiang     int apiver;     /* Module API version as requested during initialization.*/
49*572c4311Sfengbojiang     list *types;    /* Module data types. */
50*572c4311Sfengbojiang     list *usedby;   /* List of modules using APIs from this one. */
51*572c4311Sfengbojiang     list *using;    /* List of modules we use some APIs of. */
52*572c4311Sfengbojiang     list *filters;  /* List of filters the module has registered. */
53*572c4311Sfengbojiang     int in_call;    /* RM_Call() nesting level */
54*572c4311Sfengbojiang };
55*572c4311Sfengbojiang typedef struct RedisModule RedisModule;
56*572c4311Sfengbojiang 
57*572c4311Sfengbojiang /* This represents a shared API. Shared APIs will be used to populate
58*572c4311Sfengbojiang  * the server.sharedapi dictionary, mapping names of APIs exported by
59*572c4311Sfengbojiang  * modules for other modules to use, to their structure specifying the
60*572c4311Sfengbojiang  * function pointer that can be called. */
61*572c4311Sfengbojiang struct RedisModuleSharedAPI {
62*572c4311Sfengbojiang     void *func;
63*572c4311Sfengbojiang     RedisModule *module;
64*572c4311Sfengbojiang };
65*572c4311Sfengbojiang typedef struct RedisModuleSharedAPI RedisModuleSharedAPI;
66*572c4311Sfengbojiang 
67*572c4311Sfengbojiang static dict *modules; /* Hash table of modules. SDS -> RedisModule ptr.*/
68*572c4311Sfengbojiang 
69*572c4311Sfengbojiang /* Entries in the context->amqueue array, representing objects to free
70*572c4311Sfengbojiang  * when the callback returns. */
71*572c4311Sfengbojiang struct AutoMemEntry {
72*572c4311Sfengbojiang     void *ptr;
73*572c4311Sfengbojiang     int type;
74*572c4311Sfengbojiang };
75*572c4311Sfengbojiang 
76*572c4311Sfengbojiang /* AutMemEntry type field values. */
77*572c4311Sfengbojiang #define REDISMODULE_AM_KEY 0
78*572c4311Sfengbojiang #define REDISMODULE_AM_STRING 1
79*572c4311Sfengbojiang #define REDISMODULE_AM_REPLY 2
80*572c4311Sfengbojiang #define REDISMODULE_AM_FREED 3 /* Explicitly freed by user already. */
81*572c4311Sfengbojiang #define REDISMODULE_AM_DICT 4
82*572c4311Sfengbojiang 
83*572c4311Sfengbojiang /* The pool allocator block. Redis Modules can allocate memory via this special
84*572c4311Sfengbojiang  * allocator that will automatically release it all once the callback returns.
85*572c4311Sfengbojiang  * This means that it can only be used for ephemeral allocations. However
86*572c4311Sfengbojiang  * there are two advantages for modules to use this API:
87*572c4311Sfengbojiang  *
88*572c4311Sfengbojiang  * 1) The memory is automatically released when the callback returns.
89*572c4311Sfengbojiang  * 2) This allocator is faster for many small allocations since whole blocks
90*572c4311Sfengbojiang  *    are allocated, and small pieces returned to the caller just advancing
91*572c4311Sfengbojiang  *    the index of the allocation.
92*572c4311Sfengbojiang  *
93*572c4311Sfengbojiang  * Allocations are always rounded to the size of the void pointer in order
94*572c4311Sfengbojiang  * to always return aligned memory chunks. */
95*572c4311Sfengbojiang 
96*572c4311Sfengbojiang #define REDISMODULE_POOL_ALLOC_MIN_SIZE (1024*8)
97*572c4311Sfengbojiang #define REDISMODULE_POOL_ALLOC_ALIGN (sizeof(void*))
98*572c4311Sfengbojiang 
99*572c4311Sfengbojiang typedef struct RedisModulePoolAllocBlock {
100*572c4311Sfengbojiang     uint32_t size;
101*572c4311Sfengbojiang     uint32_t used;
102*572c4311Sfengbojiang     struct RedisModulePoolAllocBlock *next;
103*572c4311Sfengbojiang     char memory[];
104*572c4311Sfengbojiang } RedisModulePoolAllocBlock;
105*572c4311Sfengbojiang 
106*572c4311Sfengbojiang /* This structure represents the context in which Redis modules operate.
107*572c4311Sfengbojiang  * Most APIs module can access, get a pointer to the context, so that the API
108*572c4311Sfengbojiang  * implementation can hold state across calls, or remember what to free after
109*572c4311Sfengbojiang  * the call and so forth.
110*572c4311Sfengbojiang  *
111*572c4311Sfengbojiang  * Note that not all the context structure is always filled with actual values
112*572c4311Sfengbojiang  * but only the fields needed in a given context. */
113*572c4311Sfengbojiang 
114*572c4311Sfengbojiang struct RedisModuleBlockedClient;
115*572c4311Sfengbojiang 
116*572c4311Sfengbojiang struct RedisModuleCtx {
117*572c4311Sfengbojiang     void *getapifuncptr;            /* NOTE: Must be the first field. */
118*572c4311Sfengbojiang     struct RedisModule *module;     /* Module reference. */
119*572c4311Sfengbojiang     client *client;                 /* Client calling a command. */
120*572c4311Sfengbojiang     struct RedisModuleBlockedClient *blocked_client; /* Blocked client for
121*572c4311Sfengbojiang                                                         thread safe context. */
122*572c4311Sfengbojiang     struct AutoMemEntry *amqueue;   /* Auto memory queue of objects to free. */
123*572c4311Sfengbojiang     int amqueue_len;                /* Number of slots in amqueue. */
124*572c4311Sfengbojiang     int amqueue_used;               /* Number of used slots in amqueue. */
125*572c4311Sfengbojiang     int flags;                      /* REDISMODULE_CTX_... flags. */
126*572c4311Sfengbojiang     void **postponed_arrays;        /* To set with RM_ReplySetArrayLength(). */
127*572c4311Sfengbojiang     int postponed_arrays_count;     /* Number of entries in postponed_arrays. */
128*572c4311Sfengbojiang     void *blocked_privdata;         /* Privdata set when unblocking a client. */
129*572c4311Sfengbojiang 
130*572c4311Sfengbojiang     /* Used if there is the REDISMODULE_CTX_KEYS_POS_REQUEST flag set. */
131*572c4311Sfengbojiang     int *keys_pos;
132*572c4311Sfengbojiang     int keys_count;
133*572c4311Sfengbojiang 
134*572c4311Sfengbojiang     struct RedisModulePoolAllocBlock *pa_head;
135*572c4311Sfengbojiang };
136*572c4311Sfengbojiang typedef struct RedisModuleCtx RedisModuleCtx;
137*572c4311Sfengbojiang 
138*572c4311Sfengbojiang #define REDISMODULE_CTX_INIT {(void*)(unsigned long)&RM_GetApi, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0, NULL, NULL, 0, NULL}
139*572c4311Sfengbojiang #define REDISMODULE_CTX_MULTI_EMITTED (1<<0)
140*572c4311Sfengbojiang #define REDISMODULE_CTX_AUTO_MEMORY (1<<1)
141*572c4311Sfengbojiang #define REDISMODULE_CTX_KEYS_POS_REQUEST (1<<2)
142*572c4311Sfengbojiang #define REDISMODULE_CTX_BLOCKED_REPLY (1<<3)
143*572c4311Sfengbojiang #define REDISMODULE_CTX_BLOCKED_TIMEOUT (1<<4)
144*572c4311Sfengbojiang #define REDISMODULE_CTX_THREAD_SAFE (1<<5)
145*572c4311Sfengbojiang #define REDISMODULE_CTX_BLOCKED_DISCONNECTED (1<<6)
146*572c4311Sfengbojiang 
147*572c4311Sfengbojiang /* This represents a Redis key opened with RM_OpenKey(). */
148*572c4311Sfengbojiang struct RedisModuleKey {
149*572c4311Sfengbojiang     RedisModuleCtx *ctx;
150*572c4311Sfengbojiang     redisDb *db;
151*572c4311Sfengbojiang     robj *key;      /* Key name object. */
152*572c4311Sfengbojiang     robj *value;    /* Value object, or NULL if the key was not found. */
153*572c4311Sfengbojiang     void *iter;     /* Iterator. */
154*572c4311Sfengbojiang     int mode;       /* Opening mode. */
155*572c4311Sfengbojiang 
156*572c4311Sfengbojiang     /* Zset iterator. */
157*572c4311Sfengbojiang     uint32_t ztype;         /* REDISMODULE_ZSET_RANGE_* */
158*572c4311Sfengbojiang     zrangespec zrs;         /* Score range. */
159*572c4311Sfengbojiang     zlexrangespec zlrs;     /* Lex range. */
160*572c4311Sfengbojiang     uint32_t zstart;        /* Start pos for positional ranges. */
161*572c4311Sfengbojiang     uint32_t zend;          /* End pos for positional ranges. */
162*572c4311Sfengbojiang     void *zcurrent;         /* Zset iterator current node. */
163*572c4311Sfengbojiang     int zer;                /* Zset iterator end reached flag
164*572c4311Sfengbojiang                                (true if end was reached). */
165*572c4311Sfengbojiang };
166*572c4311Sfengbojiang typedef struct RedisModuleKey RedisModuleKey;
167*572c4311Sfengbojiang 
168*572c4311Sfengbojiang /* RedisModuleKey 'ztype' values. */
169*572c4311Sfengbojiang #define REDISMODULE_ZSET_RANGE_NONE 0       /* This must always be 0. */
170*572c4311Sfengbojiang #define REDISMODULE_ZSET_RANGE_LEX 1
171*572c4311Sfengbojiang #define REDISMODULE_ZSET_RANGE_SCORE 2
172*572c4311Sfengbojiang #define REDISMODULE_ZSET_RANGE_POS 3
173*572c4311Sfengbojiang 
174*572c4311Sfengbojiang /* Function pointer type of a function representing a command inside
175*572c4311Sfengbojiang  * a Redis module. */
176*572c4311Sfengbojiang struct RedisModuleBlockedClient;
177*572c4311Sfengbojiang typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, void **argv, int argc);
178*572c4311Sfengbojiang typedef void (*RedisModuleDisconnectFunc) (RedisModuleCtx *ctx, struct RedisModuleBlockedClient *bc);
179*572c4311Sfengbojiang 
180*572c4311Sfengbojiang /* This struct holds the information about a command registered by a module.*/
181*572c4311Sfengbojiang struct RedisModuleCommandProxy {
182*572c4311Sfengbojiang     struct RedisModule *module;
183*572c4311Sfengbojiang     RedisModuleCmdFunc func;
184*572c4311Sfengbojiang     struct redisCommand *rediscmd;
185*572c4311Sfengbojiang };
186*572c4311Sfengbojiang typedef struct RedisModuleCommandProxy RedisModuleCommandProxy;
187*572c4311Sfengbojiang 
188*572c4311Sfengbojiang #define REDISMODULE_REPLYFLAG_NONE 0
189*572c4311Sfengbojiang #define REDISMODULE_REPLYFLAG_TOPARSE (1<<0) /* Protocol must be parsed. */
190*572c4311Sfengbojiang #define REDISMODULE_REPLYFLAG_NESTED (1<<1)  /* Nested reply object. No proto
191*572c4311Sfengbojiang                                                 or struct free. */
192*572c4311Sfengbojiang 
193*572c4311Sfengbojiang /* Reply of RM_Call() function. The function is filled in a lazy
194*572c4311Sfengbojiang  * way depending on the function called on the reply structure. By default
195*572c4311Sfengbojiang  * only the type, proto and protolen are filled. */
196*572c4311Sfengbojiang typedef struct RedisModuleCallReply {
197*572c4311Sfengbojiang     RedisModuleCtx *ctx;
198*572c4311Sfengbojiang     int type;       /* REDISMODULE_REPLY_... */
199*572c4311Sfengbojiang     int flags;      /* REDISMODULE_REPLYFLAG_...  */
200*572c4311Sfengbojiang     size_t len;     /* Len of strings or num of elements of arrays. */
201*572c4311Sfengbojiang     char *proto;    /* Raw reply protocol. An SDS string at top-level object. */
202*572c4311Sfengbojiang     size_t protolen;/* Length of protocol. */
203*572c4311Sfengbojiang     union {
204*572c4311Sfengbojiang         const char *str; /* String pointer for string and error replies. This
205*572c4311Sfengbojiang                             does not need to be freed, always points inside
206*572c4311Sfengbojiang                             a reply->proto buffer of the reply object or, in
207*572c4311Sfengbojiang                             case of array elements, of parent reply objects. */
208*572c4311Sfengbojiang         long long ll;    /* Reply value for integer reply. */
209*572c4311Sfengbojiang         struct RedisModuleCallReply *array; /* Array of sub-reply elements. */
210*572c4311Sfengbojiang     } val;
211*572c4311Sfengbojiang } RedisModuleCallReply;
212*572c4311Sfengbojiang 
213*572c4311Sfengbojiang /* Structure representing a blocked client. We get a pointer to such
214*572c4311Sfengbojiang  * an object when blocking from modules. */
215*572c4311Sfengbojiang typedef struct RedisModuleBlockedClient {
216*572c4311Sfengbojiang     client *client;  /* Pointer to the blocked client. or NULL if the client
217*572c4311Sfengbojiang                         was destroyed during the life of this object. */
218*572c4311Sfengbojiang     RedisModule *module;    /* Module blocking the client. */
219*572c4311Sfengbojiang     RedisModuleCmdFunc reply_callback; /* Reply callback on normal completion.*/
220*572c4311Sfengbojiang     RedisModuleCmdFunc timeout_callback; /* Reply callback on timeout. */
221*572c4311Sfengbojiang     RedisModuleDisconnectFunc disconnect_callback; /* Called on disconnection.*/
222*572c4311Sfengbojiang     void (*free_privdata)(RedisModuleCtx*,void*);/* privdata cleanup callback.*/
223*572c4311Sfengbojiang     void *privdata;     /* Module private data that may be used by the reply
224*572c4311Sfengbojiang                            or timeout callback. It is set via the
225*572c4311Sfengbojiang                            RedisModule_UnblockClient() API. */
226*572c4311Sfengbojiang     client *reply_client;           /* Fake client used to accumulate replies
227*572c4311Sfengbojiang                                        in thread safe contexts. */
228*572c4311Sfengbojiang     int dbid;           /* Database number selected by the original client. */
229*572c4311Sfengbojiang } RedisModuleBlockedClient;
230*572c4311Sfengbojiang 
231*572c4311Sfengbojiang static pthread_mutex_t moduleUnblockedClientsMutex = PTHREAD_MUTEX_INITIALIZER;
232*572c4311Sfengbojiang static list *moduleUnblockedClients;
233*572c4311Sfengbojiang 
234*572c4311Sfengbojiang /* We need a mutex that is unlocked / relocked in beforeSleep() in order to
235*572c4311Sfengbojiang  * allow thread safe contexts to execute commands at a safe moment. */
236*572c4311Sfengbojiang static pthread_mutex_t moduleGIL = PTHREAD_MUTEX_INITIALIZER;
237*572c4311Sfengbojiang 
238*572c4311Sfengbojiang 
239*572c4311Sfengbojiang /* Function pointer type for keyspace event notification subscriptions from modules. */
240*572c4311Sfengbojiang typedef int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key);
241*572c4311Sfengbojiang 
242*572c4311Sfengbojiang /* Keyspace notification subscriber information.
243*572c4311Sfengbojiang  * See RM_SubscribeToKeyspaceEvents() for more information. */
244*572c4311Sfengbojiang typedef struct RedisModuleKeyspaceSubscriber {
245*572c4311Sfengbojiang     /* The module subscribed to the event */
246*572c4311Sfengbojiang     RedisModule *module;
247*572c4311Sfengbojiang     /* Notification callback in the module*/
248*572c4311Sfengbojiang     RedisModuleNotificationFunc notify_callback;
249*572c4311Sfengbojiang     /* A bit mask of the events the module is interested in */
250*572c4311Sfengbojiang     int event_mask;
251*572c4311Sfengbojiang     /* Active flag set on entry, to avoid reentrant subscribers
252*572c4311Sfengbojiang      * calling themselves */
253*572c4311Sfengbojiang     int active;
254*572c4311Sfengbojiang } RedisModuleKeyspaceSubscriber;
255*572c4311Sfengbojiang 
256*572c4311Sfengbojiang /* The module keyspace notification subscribers list */
257*572c4311Sfengbojiang static list *moduleKeyspaceSubscribers;
258*572c4311Sfengbojiang 
259*572c4311Sfengbojiang /* Static client recycled for when we need to provide a context with a client
260*572c4311Sfengbojiang  * in a situation where there is no client to provide. This avoidsallocating
261*572c4311Sfengbojiang  * a new client per round. For instance this is used in the keyspace
262*572c4311Sfengbojiang  * notifications, timers and cluster messages callbacks. */
263*572c4311Sfengbojiang static client *moduleFreeContextReusedClient;
264*572c4311Sfengbojiang 
265*572c4311Sfengbojiang /* Data structures related to the exported dictionary data structure. */
266*572c4311Sfengbojiang typedef struct RedisModuleDict {
267*572c4311Sfengbojiang     rax *rax;                       /* The radix tree. */
268*572c4311Sfengbojiang } RedisModuleDict;
269*572c4311Sfengbojiang 
270*572c4311Sfengbojiang typedef struct RedisModuleDictIter {
271*572c4311Sfengbojiang     RedisModuleDict *dict;
272*572c4311Sfengbojiang     raxIterator ri;
273*572c4311Sfengbojiang } RedisModuleDictIter;
274*572c4311Sfengbojiang 
275*572c4311Sfengbojiang typedef struct RedisModuleCommandFilterCtx {
276*572c4311Sfengbojiang     RedisModuleString **argv;
277*572c4311Sfengbojiang     int argc;
278*572c4311Sfengbojiang } RedisModuleCommandFilterCtx;
279*572c4311Sfengbojiang 
280*572c4311Sfengbojiang typedef void (*RedisModuleCommandFilterFunc) (RedisModuleCommandFilterCtx *filter);
281*572c4311Sfengbojiang 
282*572c4311Sfengbojiang typedef struct RedisModuleCommandFilter {
283*572c4311Sfengbojiang     /* The module that registered the filter */
284*572c4311Sfengbojiang     RedisModule *module;
285*572c4311Sfengbojiang     /* Filter callback function */
286*572c4311Sfengbojiang     RedisModuleCommandFilterFunc callback;
287*572c4311Sfengbojiang     /* REDISMODULE_CMDFILTER_* flags */
288*572c4311Sfengbojiang     int flags;
289*572c4311Sfengbojiang } RedisModuleCommandFilter;
290*572c4311Sfengbojiang 
291*572c4311Sfengbojiang /* Registered filters */
292*572c4311Sfengbojiang static list *moduleCommandFilters;
293*572c4311Sfengbojiang 
294*572c4311Sfengbojiang /* --------------------------------------------------------------------------
295*572c4311Sfengbojiang  * Prototypes
296*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
297*572c4311Sfengbojiang 
298*572c4311Sfengbojiang void RM_FreeCallReply(RedisModuleCallReply *reply);
299*572c4311Sfengbojiang void RM_CloseKey(RedisModuleKey *key);
300*572c4311Sfengbojiang void autoMemoryCollect(RedisModuleCtx *ctx);
301*572c4311Sfengbojiang robj **moduleCreateArgvFromUserFormat(const char *cmdname, const char *fmt, int *argcp, int *flags, va_list ap);
302*572c4311Sfengbojiang void moduleReplicateMultiIfNeeded(RedisModuleCtx *ctx);
303*572c4311Sfengbojiang void RM_ZsetRangeStop(RedisModuleKey *kp);
304*572c4311Sfengbojiang static void zsetKeyReset(RedisModuleKey *key);
305*572c4311Sfengbojiang void RM_FreeDict(RedisModuleCtx *ctx, RedisModuleDict *d);
306*572c4311Sfengbojiang 
307*572c4311Sfengbojiang /* --------------------------------------------------------------------------
308*572c4311Sfengbojiang  * Heap allocation raw functions
309*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
310*572c4311Sfengbojiang 
311*572c4311Sfengbojiang /* Use like malloc(). Memory allocated with this function is reported in
312*572c4311Sfengbojiang  * Redis INFO memory, used for keys eviction according to maxmemory settings
313*572c4311Sfengbojiang  * and in general is taken into account as memory allocated by Redis.
314*572c4311Sfengbojiang  * You should avoid using malloc(). */
RM_Alloc(size_t bytes)315*572c4311Sfengbojiang void *RM_Alloc(size_t bytes) {
316*572c4311Sfengbojiang     return zmalloc(bytes);
317*572c4311Sfengbojiang }
318*572c4311Sfengbojiang 
319*572c4311Sfengbojiang /* Use like calloc(). Memory allocated with this function is reported in
320*572c4311Sfengbojiang  * Redis INFO memory, used for keys eviction according to maxmemory settings
321*572c4311Sfengbojiang  * and in general is taken into account as memory allocated by Redis.
322*572c4311Sfengbojiang  * You should avoid using calloc() directly. */
RM_Calloc(size_t nmemb,size_t size)323*572c4311Sfengbojiang void *RM_Calloc(size_t nmemb, size_t size) {
324*572c4311Sfengbojiang     return zcalloc(nmemb*size);
325*572c4311Sfengbojiang }
326*572c4311Sfengbojiang 
327*572c4311Sfengbojiang /* Use like realloc() for memory obtained with RedisModule_Alloc(). */
RM_Realloc(void * ptr,size_t bytes)328*572c4311Sfengbojiang void* RM_Realloc(void *ptr, size_t bytes) {
329*572c4311Sfengbojiang     return zrealloc(ptr,bytes);
330*572c4311Sfengbojiang }
331*572c4311Sfengbojiang 
332*572c4311Sfengbojiang /* Use like free() for memory obtained by RedisModule_Alloc() and
333*572c4311Sfengbojiang  * RedisModule_Realloc(). However you should never try to free with
334*572c4311Sfengbojiang  * RedisModule_Free() memory allocated with malloc() inside your module. */
RM_Free(void * ptr)335*572c4311Sfengbojiang void RM_Free(void *ptr) {
336*572c4311Sfengbojiang     zfree(ptr);
337*572c4311Sfengbojiang }
338*572c4311Sfengbojiang 
339*572c4311Sfengbojiang /* Like strdup() but returns memory allocated with RedisModule_Alloc(). */
RM_Strdup(const char * str)340*572c4311Sfengbojiang char *RM_Strdup(const char *str) {
341*572c4311Sfengbojiang     return zstrdup(str);
342*572c4311Sfengbojiang }
343*572c4311Sfengbojiang 
344*572c4311Sfengbojiang /* --------------------------------------------------------------------------
345*572c4311Sfengbojiang  * Pool allocator
346*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
347*572c4311Sfengbojiang 
348*572c4311Sfengbojiang /* Release the chain of blocks used for pool allocations. */
poolAllocRelease(RedisModuleCtx * ctx)349*572c4311Sfengbojiang void poolAllocRelease(RedisModuleCtx *ctx) {
350*572c4311Sfengbojiang     RedisModulePoolAllocBlock *head = ctx->pa_head, *next;
351*572c4311Sfengbojiang 
352*572c4311Sfengbojiang     while(head != NULL) {
353*572c4311Sfengbojiang         next = head->next;
354*572c4311Sfengbojiang         zfree(head);
355*572c4311Sfengbojiang         head = next;
356*572c4311Sfengbojiang     }
357*572c4311Sfengbojiang     ctx->pa_head = NULL;
358*572c4311Sfengbojiang }
359*572c4311Sfengbojiang 
360*572c4311Sfengbojiang /* Return heap allocated memory that will be freed automatically when the
361*572c4311Sfengbojiang  * module callback function returns. Mostly suitable for small allocations
362*572c4311Sfengbojiang  * that are short living and must be released when the callback returns
363*572c4311Sfengbojiang  * anyway. The returned memory is aligned to the architecture word size
364*572c4311Sfengbojiang  * if at least word size bytes are requested, otherwise it is just
365*572c4311Sfengbojiang  * aligned to the next power of two, so for example a 3 bytes request is
366*572c4311Sfengbojiang  * 4 bytes aligned while a 2 bytes request is 2 bytes aligned.
367*572c4311Sfengbojiang  *
368*572c4311Sfengbojiang  * There is no realloc style function since when this is needed to use the
369*572c4311Sfengbojiang  * pool allocator is not a good idea.
370*572c4311Sfengbojiang  *
371*572c4311Sfengbojiang  * The function returns NULL if `bytes` is 0. */
RM_PoolAlloc(RedisModuleCtx * ctx,size_t bytes)372*572c4311Sfengbojiang void *RM_PoolAlloc(RedisModuleCtx *ctx, size_t bytes) {
373*572c4311Sfengbojiang     if (bytes == 0) return NULL;
374*572c4311Sfengbojiang     RedisModulePoolAllocBlock *b = ctx->pa_head;
375*572c4311Sfengbojiang     size_t left = b ? b->size - b->used : 0;
376*572c4311Sfengbojiang 
377*572c4311Sfengbojiang     /* Fix alignment. */
378*572c4311Sfengbojiang     if (left >= bytes) {
379*572c4311Sfengbojiang         size_t alignment = REDISMODULE_POOL_ALLOC_ALIGN;
380*572c4311Sfengbojiang         while (bytes < alignment && alignment/2 >= bytes) alignment /= 2;
381*572c4311Sfengbojiang         if (b->used % alignment)
382*572c4311Sfengbojiang             b->used += alignment - (b->used % alignment);
383*572c4311Sfengbojiang         left = (b->used > b->size) ? 0 : b->size - b->used;
384*572c4311Sfengbojiang     }
385*572c4311Sfengbojiang 
386*572c4311Sfengbojiang     /* Create a new block if needed. */
387*572c4311Sfengbojiang     if (left < bytes) {
388*572c4311Sfengbojiang         size_t blocksize = REDISMODULE_POOL_ALLOC_MIN_SIZE;
389*572c4311Sfengbojiang         if (blocksize < bytes) blocksize = bytes;
390*572c4311Sfengbojiang         b = zmalloc(sizeof(*b) + blocksize);
391*572c4311Sfengbojiang         b->size = blocksize;
392*572c4311Sfengbojiang         b->used = 0;
393*572c4311Sfengbojiang         b->next = ctx->pa_head;
394*572c4311Sfengbojiang         ctx->pa_head = b;
395*572c4311Sfengbojiang     }
396*572c4311Sfengbojiang 
397*572c4311Sfengbojiang     char *retval = b->memory + b->used;
398*572c4311Sfengbojiang     b->used += bytes;
399*572c4311Sfengbojiang     return retval;
400*572c4311Sfengbojiang }
401*572c4311Sfengbojiang 
402*572c4311Sfengbojiang /* --------------------------------------------------------------------------
403*572c4311Sfengbojiang  * Helpers for modules API implementation
404*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
405*572c4311Sfengbojiang 
406*572c4311Sfengbojiang /* Create an empty key of the specified type. 'kp' must point to a key object
407*572c4311Sfengbojiang  * opened for writing where the .value member is set to NULL because the
408*572c4311Sfengbojiang  * key was found to be non existing.
409*572c4311Sfengbojiang  *
410*572c4311Sfengbojiang  * On success REDISMODULE_OK is returned and the key is populated with
411*572c4311Sfengbojiang  * the value of the specified type. The function fails and returns
412*572c4311Sfengbojiang  * REDISMODULE_ERR if:
413*572c4311Sfengbojiang  *
414*572c4311Sfengbojiang  * 1) The key is not open for writing.
415*572c4311Sfengbojiang  * 2) The key is not empty.
416*572c4311Sfengbojiang  * 3) The specified type is unknown.
417*572c4311Sfengbojiang  */
moduleCreateEmptyKey(RedisModuleKey * key,int type)418*572c4311Sfengbojiang int moduleCreateEmptyKey(RedisModuleKey *key, int type) {
419*572c4311Sfengbojiang     robj *obj;
420*572c4311Sfengbojiang 
421*572c4311Sfengbojiang     /* The key must be open for writing and non existing to proceed. */
422*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE) || key->value)
423*572c4311Sfengbojiang         return REDISMODULE_ERR;
424*572c4311Sfengbojiang 
425*572c4311Sfengbojiang     switch(type) {
426*572c4311Sfengbojiang     case REDISMODULE_KEYTYPE_LIST:
427*572c4311Sfengbojiang         obj = createQuicklistObject();
428*572c4311Sfengbojiang         quicklistSetOptions(obj->ptr, server.list_max_ziplist_size,
429*572c4311Sfengbojiang                             server.list_compress_depth);
430*572c4311Sfengbojiang         break;
431*572c4311Sfengbojiang     case REDISMODULE_KEYTYPE_ZSET:
432*572c4311Sfengbojiang         obj = createZsetZiplistObject();
433*572c4311Sfengbojiang         break;
434*572c4311Sfengbojiang     case REDISMODULE_KEYTYPE_HASH:
435*572c4311Sfengbojiang         obj = createHashObject();
436*572c4311Sfengbojiang         break;
437*572c4311Sfengbojiang     default: return REDISMODULE_ERR;
438*572c4311Sfengbojiang     }
439*572c4311Sfengbojiang     dbAdd(key->db,key->key,obj);
440*572c4311Sfengbojiang     key->value = obj;
441*572c4311Sfengbojiang     return REDISMODULE_OK;
442*572c4311Sfengbojiang }
443*572c4311Sfengbojiang 
444*572c4311Sfengbojiang /* This function is called in low-level API implementation functions in order
445*572c4311Sfengbojiang  * to check if the value associated with the key remained empty after an
446*572c4311Sfengbojiang  * operation that removed elements from an aggregate data type.
447*572c4311Sfengbojiang  *
448*572c4311Sfengbojiang  * If this happens, the key is deleted from the DB and the key object state
449*572c4311Sfengbojiang  * is set to the right one in order to be targeted again by write operations
450*572c4311Sfengbojiang  * possibly recreating the key if needed.
451*572c4311Sfengbojiang  *
452*572c4311Sfengbojiang  * The function returns 1 if the key value object is found empty and is
453*572c4311Sfengbojiang  * deleted, otherwise 0 is returned. */
moduleDelKeyIfEmpty(RedisModuleKey * key)454*572c4311Sfengbojiang int moduleDelKeyIfEmpty(RedisModuleKey *key) {
455*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE) || key->value == NULL) return 0;
456*572c4311Sfengbojiang     int isempty;
457*572c4311Sfengbojiang     robj *o = key->value;
458*572c4311Sfengbojiang 
459*572c4311Sfengbojiang     switch(o->type) {
460*572c4311Sfengbojiang     case OBJ_LIST: isempty = listTypeLength(o) == 0; break;
461*572c4311Sfengbojiang     case OBJ_SET: isempty = setTypeSize(o) == 0; break;
462*572c4311Sfengbojiang     case OBJ_ZSET: isempty = zsetLength(o) == 0; break;
463*572c4311Sfengbojiang     case OBJ_HASH : isempty = hashTypeLength(o) == 0; break;
464*572c4311Sfengbojiang     default: isempty = 0;
465*572c4311Sfengbojiang     }
466*572c4311Sfengbojiang 
467*572c4311Sfengbojiang     if (isempty) {
468*572c4311Sfengbojiang         dbDelete(key->db,key->key);
469*572c4311Sfengbojiang         key->value = NULL;
470*572c4311Sfengbojiang         return 1;
471*572c4311Sfengbojiang     } else {
472*572c4311Sfengbojiang         return 0;
473*572c4311Sfengbojiang     }
474*572c4311Sfengbojiang }
475*572c4311Sfengbojiang 
476*572c4311Sfengbojiang /* --------------------------------------------------------------------------
477*572c4311Sfengbojiang  * Service API exported to modules
478*572c4311Sfengbojiang  *
479*572c4311Sfengbojiang  * Note that all the exported APIs are called RM_<funcname> in the core
480*572c4311Sfengbojiang  * and RedisModule_<funcname> in the module side (defined as function
481*572c4311Sfengbojiang  * pointers in redismodule.h). In this way the dynamic linker does not
482*572c4311Sfengbojiang  * mess with our global function pointers, overriding it with the symbols
483*572c4311Sfengbojiang  * defined in the main executable having the same names.
484*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
485*572c4311Sfengbojiang 
486*572c4311Sfengbojiang /* Lookup the requested module API and store the function pointer into the
487*572c4311Sfengbojiang  * target pointer. The function returns REDISMODULE_ERR if there is no such
488*572c4311Sfengbojiang  * named API, otherwise REDISMODULE_OK.
489*572c4311Sfengbojiang  *
490*572c4311Sfengbojiang  * This function is not meant to be used by modules developer, it is only
491*572c4311Sfengbojiang  * used implicitly by including redismodule.h. */
RM_GetApi(const char * funcname,void ** targetPtrPtr)492*572c4311Sfengbojiang int RM_GetApi(const char *funcname, void **targetPtrPtr) {
493*572c4311Sfengbojiang     dictEntry *he = dictFind(server.moduleapi, funcname);
494*572c4311Sfengbojiang     if (!he) return REDISMODULE_ERR;
495*572c4311Sfengbojiang     *targetPtrPtr = dictGetVal(he);
496*572c4311Sfengbojiang     return REDISMODULE_OK;
497*572c4311Sfengbojiang }
498*572c4311Sfengbojiang 
499*572c4311Sfengbojiang /* Free the context after the user function was called. */
moduleFreeContext(RedisModuleCtx * ctx)500*572c4311Sfengbojiang void moduleFreeContext(RedisModuleCtx *ctx) {
501*572c4311Sfengbojiang     autoMemoryCollect(ctx);
502*572c4311Sfengbojiang     poolAllocRelease(ctx);
503*572c4311Sfengbojiang     if (ctx->postponed_arrays) {
504*572c4311Sfengbojiang         zfree(ctx->postponed_arrays);
505*572c4311Sfengbojiang         ctx->postponed_arrays_count = 0;
506*572c4311Sfengbojiang         serverLog(LL_WARNING,
507*572c4311Sfengbojiang             "API misuse detected in module %s: "
508*572c4311Sfengbojiang             "RedisModule_ReplyWithArray(REDISMODULE_POSTPONED_ARRAY_LEN) "
509*572c4311Sfengbojiang             "not matched by the same number of RedisModule_SetReplyArrayLen() "
510*572c4311Sfengbojiang             "calls.",
511*572c4311Sfengbojiang             ctx->module->name);
512*572c4311Sfengbojiang     }
513*572c4311Sfengbojiang     if (ctx->flags & REDISMODULE_CTX_THREAD_SAFE) freeClient(ctx->client);
514*572c4311Sfengbojiang }
515*572c4311Sfengbojiang 
516*572c4311Sfengbojiang /* Helper function for when a command callback is called, in order to handle
517*572c4311Sfengbojiang  * details needed to correctly replicate commands. */
moduleHandlePropagationAfterCommandCallback(RedisModuleCtx * ctx)518*572c4311Sfengbojiang void moduleHandlePropagationAfterCommandCallback(RedisModuleCtx *ctx) {
519*572c4311Sfengbojiang     client *c = ctx->client;
520*572c4311Sfengbojiang 
521*572c4311Sfengbojiang     if (c->flags & CLIENT_LUA) return;
522*572c4311Sfengbojiang 
523*572c4311Sfengbojiang     /* Handle the replication of the final EXEC, since whatever a command
524*572c4311Sfengbojiang      * emits is always wrapped around MULTI/EXEC. */
525*572c4311Sfengbojiang     if (ctx->flags & REDISMODULE_CTX_MULTI_EMITTED) {
526*572c4311Sfengbojiang         robj *propargv[1];
527*572c4311Sfengbojiang         propargv[0] = createStringObject("EXEC",4);
528*572c4311Sfengbojiang         alsoPropagate(server.execCommand,c->db->id,propargv,1,
529*572c4311Sfengbojiang             PROPAGATE_AOF|PROPAGATE_REPL);
530*572c4311Sfengbojiang         decrRefCount(propargv[0]);
531*572c4311Sfengbojiang     }
532*572c4311Sfengbojiang }
533*572c4311Sfengbojiang 
534*572c4311Sfengbojiang /* This Redis command binds the normal Redis command invocation with commands
535*572c4311Sfengbojiang  * exported by modules. */
RedisModuleCommandDispatcher(client * c)536*572c4311Sfengbojiang void RedisModuleCommandDispatcher(client *c) {
537*572c4311Sfengbojiang     RedisModuleCommandProxy *cp = (void*)(unsigned long)c->cmd->getkeys_proc;
538*572c4311Sfengbojiang     RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
539*572c4311Sfengbojiang 
540*572c4311Sfengbojiang     ctx.module = cp->module;
541*572c4311Sfengbojiang     ctx.client = c;
542*572c4311Sfengbojiang     cp->func(&ctx,(void**)c->argv,c->argc);
543*572c4311Sfengbojiang     moduleHandlePropagationAfterCommandCallback(&ctx);
544*572c4311Sfengbojiang     moduleFreeContext(&ctx);
545*572c4311Sfengbojiang 
546*572c4311Sfengbojiang     /* In some cases processMultibulkBuffer uses sdsMakeRoomFor to
547*572c4311Sfengbojiang      * expand the query buffer, and in order to avoid a big object copy
548*572c4311Sfengbojiang      * the query buffer SDS may be used directly as the SDS string backing
549*572c4311Sfengbojiang      * the client argument vectors: sometimes this will result in the SDS
550*572c4311Sfengbojiang      * string having unused space at the end. Later if a module takes ownership
551*572c4311Sfengbojiang      * of the RedisString, such space will be wasted forever. Inside the
552*572c4311Sfengbojiang      * Redis core this is not a problem because tryObjectEncoding() is called
553*572c4311Sfengbojiang      * before storing strings in the key space. Here we need to do it
554*572c4311Sfengbojiang      * for the module. */
555*572c4311Sfengbojiang     for (int i = 0; i < c->argc; i++) {
556*572c4311Sfengbojiang         /* Only do the work if the module took ownership of the object:
557*572c4311Sfengbojiang          * in that case the refcount is no longer 1. */
558*572c4311Sfengbojiang         if (c->argv[i]->refcount > 1)
559*572c4311Sfengbojiang             trimStringObjectIfNeeded(c->argv[i]);
560*572c4311Sfengbojiang     }
561*572c4311Sfengbojiang }
562*572c4311Sfengbojiang 
563*572c4311Sfengbojiang /* This function returns the list of keys, with the same interface as the
564*572c4311Sfengbojiang  * 'getkeys' function of the native commands, for module commands that exported
565*572c4311Sfengbojiang  * the "getkeys-api" flag during the registration. This is done when the
566*572c4311Sfengbojiang  * list of keys are not at fixed positions, so that first/last/step cannot
567*572c4311Sfengbojiang  * be used.
568*572c4311Sfengbojiang  *
569*572c4311Sfengbojiang  * In order to accomplish its work, the module command is called, flagging
570*572c4311Sfengbojiang  * the context in a way that the command can recognize this is a special
571*572c4311Sfengbojiang  * "get keys" call by calling RedisModule_IsKeysPositionRequest(ctx). */
moduleGetCommandKeysViaAPI(struct redisCommand * cmd,robj ** argv,int argc,int * numkeys)572*572c4311Sfengbojiang int *moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {
573*572c4311Sfengbojiang     RedisModuleCommandProxy *cp = (void*)(unsigned long)cmd->getkeys_proc;
574*572c4311Sfengbojiang     RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
575*572c4311Sfengbojiang 
576*572c4311Sfengbojiang     ctx.module = cp->module;
577*572c4311Sfengbojiang     ctx.client = NULL;
578*572c4311Sfengbojiang     ctx.flags |= REDISMODULE_CTX_KEYS_POS_REQUEST;
579*572c4311Sfengbojiang     cp->func(&ctx,(void**)argv,argc);
580*572c4311Sfengbojiang     int *res = ctx.keys_pos;
581*572c4311Sfengbojiang     if (numkeys) *numkeys = ctx.keys_count;
582*572c4311Sfengbojiang     moduleFreeContext(&ctx);
583*572c4311Sfengbojiang     return res;
584*572c4311Sfengbojiang }
585*572c4311Sfengbojiang 
586*572c4311Sfengbojiang /* Return non-zero if a module command, that was declared with the
587*572c4311Sfengbojiang  * flag "getkeys-api", is called in a special way to get the keys positions
588*572c4311Sfengbojiang  * and not to get executed. Otherwise zero is returned. */
RM_IsKeysPositionRequest(RedisModuleCtx * ctx)589*572c4311Sfengbojiang int RM_IsKeysPositionRequest(RedisModuleCtx *ctx) {
590*572c4311Sfengbojiang     return (ctx->flags & REDISMODULE_CTX_KEYS_POS_REQUEST) != 0;
591*572c4311Sfengbojiang }
592*572c4311Sfengbojiang 
593*572c4311Sfengbojiang /* When a module command is called in order to obtain the position of
594*572c4311Sfengbojiang  * keys, since it was flagged as "getkeys-api" during the registration,
595*572c4311Sfengbojiang  * the command implementation checks for this special call using the
596*572c4311Sfengbojiang  * RedisModule_IsKeysPositionRequest() API and uses this function in
597*572c4311Sfengbojiang  * order to report keys, like in the following example:
598*572c4311Sfengbojiang  *
599*572c4311Sfengbojiang  *     if (RedisModule_IsKeysPositionRequest(ctx)) {
600*572c4311Sfengbojiang  *         RedisModule_KeyAtPos(ctx,1);
601*572c4311Sfengbojiang  *         RedisModule_KeyAtPos(ctx,2);
602*572c4311Sfengbojiang  *     }
603*572c4311Sfengbojiang  *
604*572c4311Sfengbojiang  *  Note: in the example below the get keys API would not be needed since
605*572c4311Sfengbojiang  *  keys are at fixed positions. This interface is only used for commands
606*572c4311Sfengbojiang  *  with a more complex structure. */
RM_KeyAtPos(RedisModuleCtx * ctx,int pos)607*572c4311Sfengbojiang void RM_KeyAtPos(RedisModuleCtx *ctx, int pos) {
608*572c4311Sfengbojiang     if (!(ctx->flags & REDISMODULE_CTX_KEYS_POS_REQUEST)) return;
609*572c4311Sfengbojiang     if (pos <= 0) return;
610*572c4311Sfengbojiang     ctx->keys_pos = zrealloc(ctx->keys_pos,sizeof(int)*(ctx->keys_count+1));
611*572c4311Sfengbojiang     ctx->keys_pos[ctx->keys_count++] = pos;
612*572c4311Sfengbojiang }
613*572c4311Sfengbojiang 
614*572c4311Sfengbojiang /* Helper for RM_CreateCommand(). Turns a string representing command
615*572c4311Sfengbojiang  * flags into the command flags used by the Redis core.
616*572c4311Sfengbojiang  *
617*572c4311Sfengbojiang  * It returns the set of flags, or -1 if unknown flags are found. */
commandFlagsFromString(char * s)618*572c4311Sfengbojiang int commandFlagsFromString(char *s) {
619*572c4311Sfengbojiang     int count, j;
620*572c4311Sfengbojiang     int flags = 0;
621*572c4311Sfengbojiang     sds *tokens = sdssplitlen(s,strlen(s)," ",1,&count);
622*572c4311Sfengbojiang     for (j = 0; j < count; j++) {
623*572c4311Sfengbojiang         char *t = tokens[j];
624*572c4311Sfengbojiang         if (!strcasecmp(t,"write")) flags |= CMD_WRITE;
625*572c4311Sfengbojiang         else if (!strcasecmp(t,"readonly")) flags |= CMD_READONLY;
626*572c4311Sfengbojiang         else if (!strcasecmp(t,"admin")) flags |= CMD_ADMIN;
627*572c4311Sfengbojiang         else if (!strcasecmp(t,"deny-oom")) flags |= CMD_DENYOOM;
628*572c4311Sfengbojiang         else if (!strcasecmp(t,"deny-script")) flags |= CMD_NOSCRIPT;
629*572c4311Sfengbojiang         else if (!strcasecmp(t,"allow-loading")) flags |= CMD_LOADING;
630*572c4311Sfengbojiang         else if (!strcasecmp(t,"pubsub")) flags |= CMD_PUBSUB;
631*572c4311Sfengbojiang         else if (!strcasecmp(t,"random")) flags |= CMD_RANDOM;
632*572c4311Sfengbojiang         else if (!strcasecmp(t,"allow-stale")) flags |= CMD_STALE;
633*572c4311Sfengbojiang         else if (!strcasecmp(t,"no-monitor")) flags |= CMD_SKIP_MONITOR;
634*572c4311Sfengbojiang         else if (!strcasecmp(t,"fast")) flags |= CMD_FAST;
635*572c4311Sfengbojiang         else if (!strcasecmp(t,"getkeys-api")) flags |= CMD_MODULE_GETKEYS;
636*572c4311Sfengbojiang         else if (!strcasecmp(t,"no-cluster")) flags |= CMD_MODULE_NO_CLUSTER;
637*572c4311Sfengbojiang         else break;
638*572c4311Sfengbojiang     }
639*572c4311Sfengbojiang     sdsfreesplitres(tokens,count);
640*572c4311Sfengbojiang     if (j != count) return -1; /* Some token not processed correctly. */
641*572c4311Sfengbojiang     return flags;
642*572c4311Sfengbojiang }
643*572c4311Sfengbojiang 
644*572c4311Sfengbojiang /* Register a new command in the Redis server, that will be handled by
645*572c4311Sfengbojiang  * calling the function pointer 'func' using the RedisModule calling
646*572c4311Sfengbojiang  * convention. The function returns REDISMODULE_ERR if the specified command
647*572c4311Sfengbojiang  * name is already busy or a set of invalid flags were passed, otherwise
648*572c4311Sfengbojiang  * REDISMODULE_OK is returned and the new command is registered.
649*572c4311Sfengbojiang  *
650*572c4311Sfengbojiang  * This function must be called during the initialization of the module
651*572c4311Sfengbojiang  * inside the RedisModule_OnLoad() function. Calling this function outside
652*572c4311Sfengbojiang  * of the initialization function is not defined.
653*572c4311Sfengbojiang  *
654*572c4311Sfengbojiang  * The command function type is the following:
655*572c4311Sfengbojiang  *
656*572c4311Sfengbojiang  *      int MyCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
657*572c4311Sfengbojiang  *
658*572c4311Sfengbojiang  * And is supposed to always return REDISMODULE_OK.
659*572c4311Sfengbojiang  *
660*572c4311Sfengbojiang  * The set of flags 'strflags' specify the behavior of the command, and should
661*572c4311Sfengbojiang  * be passed as a C string composed of space separated words, like for
662*572c4311Sfengbojiang  * example "write deny-oom". The set of flags are:
663*572c4311Sfengbojiang  *
664*572c4311Sfengbojiang  * * **"write"**:     The command may modify the data set (it may also read
665*572c4311Sfengbojiang  *                    from it).
666*572c4311Sfengbojiang  * * **"readonly"**:  The command returns data from keys but never writes.
667*572c4311Sfengbojiang  * * **"admin"**:     The command is an administrative command (may change
668*572c4311Sfengbojiang  *                    replication or perform similar tasks).
669*572c4311Sfengbojiang  * * **"deny-oom"**:  The command may use additional memory and should be
670*572c4311Sfengbojiang  *                    denied during out of memory conditions.
671*572c4311Sfengbojiang  * * **"deny-script"**:   Don't allow this command in Lua scripts.
672*572c4311Sfengbojiang  * * **"allow-loading"**: Allow this command while the server is loading data.
673*572c4311Sfengbojiang  *                        Only commands not interacting with the data set
674*572c4311Sfengbojiang  *                        should be allowed to run in this mode. If not sure
675*572c4311Sfengbojiang  *                        don't use this flag.
676*572c4311Sfengbojiang  * * **"pubsub"**:    The command publishes things on Pub/Sub channels.
677*572c4311Sfengbojiang  * * **"random"**:    The command may have different outputs even starting
678*572c4311Sfengbojiang  *                    from the same input arguments and key values.
679*572c4311Sfengbojiang  * * **"allow-stale"**: The command is allowed to run on slaves that don't
680*572c4311Sfengbojiang  *                      serve stale data. Don't use if you don't know what
681*572c4311Sfengbojiang  *                      this means.
682*572c4311Sfengbojiang  * * **"no-monitor"**: Don't propagate the command on monitor. Use this if
683*572c4311Sfengbojiang  *                     the command has sensible data among the arguments.
684*572c4311Sfengbojiang  * * **"fast"**:      The command time complexity is not greater
685*572c4311Sfengbojiang  *                    than O(log(N)) where N is the size of the collection or
686*572c4311Sfengbojiang  *                    anything else representing the normal scalability
687*572c4311Sfengbojiang  *                    issue with the command.
688*572c4311Sfengbojiang  * * **"getkeys-api"**: The command implements the interface to return
689*572c4311Sfengbojiang  *                      the arguments that are keys. Used when start/stop/step
690*572c4311Sfengbojiang  *                      is not enough because of the command syntax.
691*572c4311Sfengbojiang  * * **"no-cluster"**: The command should not register in Redis Cluster
692*572c4311Sfengbojiang  *                     since is not designed to work with it because, for
693*572c4311Sfengbojiang  *                     example, is unable to report the position of the
694*572c4311Sfengbojiang  *                     keys, programmatically creates key names, or any
695*572c4311Sfengbojiang  *                     other reason.
696*572c4311Sfengbojiang  */
RM_CreateCommand(RedisModuleCtx * ctx,const char * name,RedisModuleCmdFunc cmdfunc,const char * strflags,int firstkey,int lastkey,int keystep)697*572c4311Sfengbojiang int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) {
698*572c4311Sfengbojiang     int flags = strflags ? commandFlagsFromString((char*)strflags) : 0;
699*572c4311Sfengbojiang     if (flags == -1) return REDISMODULE_ERR;
700*572c4311Sfengbojiang     if ((flags & CMD_MODULE_NO_CLUSTER) && server.cluster_enabled)
701*572c4311Sfengbojiang         return REDISMODULE_ERR;
702*572c4311Sfengbojiang 
703*572c4311Sfengbojiang     struct redisCommand *rediscmd;
704*572c4311Sfengbojiang     RedisModuleCommandProxy *cp;
705*572c4311Sfengbojiang     sds cmdname = sdsnew(name);
706*572c4311Sfengbojiang 
707*572c4311Sfengbojiang     /* Check if the command name is busy. */
708*572c4311Sfengbojiang     if (lookupCommand(cmdname) != NULL) {
709*572c4311Sfengbojiang         sdsfree(cmdname);
710*572c4311Sfengbojiang         return REDISMODULE_ERR;
711*572c4311Sfengbojiang     }
712*572c4311Sfengbojiang 
713*572c4311Sfengbojiang     /* Create a command "proxy", which is a structure that is referenced
714*572c4311Sfengbojiang      * in the command table, so that the generic command that works as
715*572c4311Sfengbojiang      * binding between modules and Redis, can know what function to call
716*572c4311Sfengbojiang      * and what the module is.
717*572c4311Sfengbojiang      *
718*572c4311Sfengbojiang      * Note that we use the Redis command table 'getkeys_proc' in order to
719*572c4311Sfengbojiang      * pass a reference to the command proxy structure. */
720*572c4311Sfengbojiang     cp = zmalloc(sizeof(*cp));
721*572c4311Sfengbojiang     cp->module = ctx->module;
722*572c4311Sfengbojiang     cp->func = cmdfunc;
723*572c4311Sfengbojiang     cp->rediscmd = zmalloc(sizeof(*rediscmd));
724*572c4311Sfengbojiang     cp->rediscmd->name = cmdname;
725*572c4311Sfengbojiang     cp->rediscmd->proc = RedisModuleCommandDispatcher;
726*572c4311Sfengbojiang     cp->rediscmd->arity = -1;
727*572c4311Sfengbojiang     cp->rediscmd->flags = flags | CMD_MODULE;
728*572c4311Sfengbojiang     cp->rediscmd->getkeys_proc = (redisGetKeysProc*)(unsigned long)cp;
729*572c4311Sfengbojiang     cp->rediscmd->firstkey = firstkey;
730*572c4311Sfengbojiang     cp->rediscmd->lastkey = lastkey;
731*572c4311Sfengbojiang     cp->rediscmd->keystep = keystep;
732*572c4311Sfengbojiang     cp->rediscmd->microseconds = 0;
733*572c4311Sfengbojiang     cp->rediscmd->calls = 0;
734*572c4311Sfengbojiang     dictAdd(server.commands,sdsdup(cmdname),cp->rediscmd);
735*572c4311Sfengbojiang     dictAdd(server.orig_commands,sdsdup(cmdname),cp->rediscmd);
736*572c4311Sfengbojiang     return REDISMODULE_OK;
737*572c4311Sfengbojiang }
738*572c4311Sfengbojiang 
739*572c4311Sfengbojiang /* Called by RM_Init() to setup the `ctx->module` structure.
740*572c4311Sfengbojiang  *
741*572c4311Sfengbojiang  * This is an internal function, Redis modules developers don't need
742*572c4311Sfengbojiang  * to use it. */
RM_SetModuleAttribs(RedisModuleCtx * ctx,const char * name,int ver,int apiver)743*572c4311Sfengbojiang void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int apiver) {
744*572c4311Sfengbojiang     RedisModule *module;
745*572c4311Sfengbojiang 
746*572c4311Sfengbojiang     if (ctx->module != NULL) return;
747*572c4311Sfengbojiang     module = zmalloc(sizeof(*module));
748*572c4311Sfengbojiang     module->name = sdsnew((char*)name);
749*572c4311Sfengbojiang     module->ver = ver;
750*572c4311Sfengbojiang     module->apiver = apiver;
751*572c4311Sfengbojiang     module->types = listCreate();
752*572c4311Sfengbojiang     module->usedby = listCreate();
753*572c4311Sfengbojiang     module->using = listCreate();
754*572c4311Sfengbojiang     module->filters = listCreate();
755*572c4311Sfengbojiang     module->in_call = 0;
756*572c4311Sfengbojiang     ctx->module = module;
757*572c4311Sfengbojiang }
758*572c4311Sfengbojiang 
759*572c4311Sfengbojiang /* Return non-zero if the module name is busy.
760*572c4311Sfengbojiang  * Otherwise zero is returned. */
RM_IsModuleNameBusy(const char * name)761*572c4311Sfengbojiang int RM_IsModuleNameBusy(const char *name) {
762*572c4311Sfengbojiang     sds modulename = sdsnew(name);
763*572c4311Sfengbojiang     dictEntry *de = dictFind(modules,modulename);
764*572c4311Sfengbojiang     sdsfree(modulename);
765*572c4311Sfengbojiang     return de != NULL;
766*572c4311Sfengbojiang }
767*572c4311Sfengbojiang 
768*572c4311Sfengbojiang /* Return the current UNIX time in milliseconds. */
RM_Milliseconds(void)769*572c4311Sfengbojiang long long RM_Milliseconds(void) {
770*572c4311Sfengbojiang     return mstime();
771*572c4311Sfengbojiang }
772*572c4311Sfengbojiang 
773*572c4311Sfengbojiang /* --------------------------------------------------------------------------
774*572c4311Sfengbojiang  * Automatic memory management for modules
775*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
776*572c4311Sfengbojiang 
777*572c4311Sfengbojiang /* Enable automatic memory management. See API.md for more information.
778*572c4311Sfengbojiang  *
779*572c4311Sfengbojiang  * The function must be called as the first function of a command implementation
780*572c4311Sfengbojiang  * that wants to use automatic memory. */
RM_AutoMemory(RedisModuleCtx * ctx)781*572c4311Sfengbojiang void RM_AutoMemory(RedisModuleCtx *ctx) {
782*572c4311Sfengbojiang     ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
783*572c4311Sfengbojiang }
784*572c4311Sfengbojiang 
785*572c4311Sfengbojiang /* Add a new object to release automatically when the callback returns. */
autoMemoryAdd(RedisModuleCtx * ctx,int type,void * ptr)786*572c4311Sfengbojiang void autoMemoryAdd(RedisModuleCtx *ctx, int type, void *ptr) {
787*572c4311Sfengbojiang     if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
788*572c4311Sfengbojiang     if (ctx->amqueue_used == ctx->amqueue_len) {
789*572c4311Sfengbojiang         ctx->amqueue_len *= 2;
790*572c4311Sfengbojiang         if (ctx->amqueue_len < 16) ctx->amqueue_len = 16;
791*572c4311Sfengbojiang         ctx->amqueue = zrealloc(ctx->amqueue,sizeof(struct AutoMemEntry)*ctx->amqueue_len);
792*572c4311Sfengbojiang     }
793*572c4311Sfengbojiang     ctx->amqueue[ctx->amqueue_used].type = type;
794*572c4311Sfengbojiang     ctx->amqueue[ctx->amqueue_used].ptr = ptr;
795*572c4311Sfengbojiang     ctx->amqueue_used++;
796*572c4311Sfengbojiang }
797*572c4311Sfengbojiang 
798*572c4311Sfengbojiang /* Mark an object as freed in the auto release queue, so that users can still
799*572c4311Sfengbojiang  * free things manually if they want.
800*572c4311Sfengbojiang  *
801*572c4311Sfengbojiang  * The function returns 1 if the object was actually found in the auto memory
802*572c4311Sfengbojiang  * pool, otherwise 0 is returned. */
autoMemoryFreed(RedisModuleCtx * ctx,int type,void * ptr)803*572c4311Sfengbojiang int autoMemoryFreed(RedisModuleCtx *ctx, int type, void *ptr) {
804*572c4311Sfengbojiang     if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return 0;
805*572c4311Sfengbojiang 
806*572c4311Sfengbojiang     int count = (ctx->amqueue_used+1)/2;
807*572c4311Sfengbojiang     for (int j = 0; j < count; j++) {
808*572c4311Sfengbojiang         for (int side = 0; side < 2; side++) {
809*572c4311Sfengbojiang             /* For side = 0 check right side of the array, for
810*572c4311Sfengbojiang              * side = 1 check the left side instead (zig-zag scanning). */
811*572c4311Sfengbojiang             int i = (side == 0) ? (ctx->amqueue_used - 1 - j) : j;
812*572c4311Sfengbojiang             if (ctx->amqueue[i].type == type &&
813*572c4311Sfengbojiang                 ctx->amqueue[i].ptr == ptr)
814*572c4311Sfengbojiang             {
815*572c4311Sfengbojiang                 ctx->amqueue[i].type = REDISMODULE_AM_FREED;
816*572c4311Sfengbojiang 
817*572c4311Sfengbojiang                 /* Switch the freed element and the last element, to avoid growing
818*572c4311Sfengbojiang                  * the queue unnecessarily if we allocate/free in a loop */
819*572c4311Sfengbojiang                 if (i != ctx->amqueue_used-1) {
820*572c4311Sfengbojiang                     ctx->amqueue[i] = ctx->amqueue[ctx->amqueue_used-1];
821*572c4311Sfengbojiang                 }
822*572c4311Sfengbojiang 
823*572c4311Sfengbojiang                 /* Reduce the size of the queue because we either moved the top
824*572c4311Sfengbojiang                  * element elsewhere or freed it */
825*572c4311Sfengbojiang                 ctx->amqueue_used--;
826*572c4311Sfengbojiang                 return 1;
827*572c4311Sfengbojiang             }
828*572c4311Sfengbojiang         }
829*572c4311Sfengbojiang     }
830*572c4311Sfengbojiang     return 0;
831*572c4311Sfengbojiang }
832*572c4311Sfengbojiang 
833*572c4311Sfengbojiang /* Release all the objects in queue. */
autoMemoryCollect(RedisModuleCtx * ctx)834*572c4311Sfengbojiang void autoMemoryCollect(RedisModuleCtx *ctx) {
835*572c4311Sfengbojiang     if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
836*572c4311Sfengbojiang     /* Clear the AUTO_MEMORY flag from the context, otherwise the functions
837*572c4311Sfengbojiang      * we call to free the resources, will try to scan the auto release
838*572c4311Sfengbojiang      * queue to mark the entries as freed. */
839*572c4311Sfengbojiang     ctx->flags &= ~REDISMODULE_CTX_AUTO_MEMORY;
840*572c4311Sfengbojiang     int j;
841*572c4311Sfengbojiang     for (j = 0; j < ctx->amqueue_used; j++) {
842*572c4311Sfengbojiang         void *ptr = ctx->amqueue[j].ptr;
843*572c4311Sfengbojiang         switch(ctx->amqueue[j].type) {
844*572c4311Sfengbojiang         case REDISMODULE_AM_STRING: decrRefCount(ptr); break;
845*572c4311Sfengbojiang         case REDISMODULE_AM_REPLY: RM_FreeCallReply(ptr); break;
846*572c4311Sfengbojiang         case REDISMODULE_AM_KEY: RM_CloseKey(ptr); break;
847*572c4311Sfengbojiang         case REDISMODULE_AM_DICT: RM_FreeDict(NULL,ptr); break;
848*572c4311Sfengbojiang         }
849*572c4311Sfengbojiang     }
850*572c4311Sfengbojiang     ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
851*572c4311Sfengbojiang     zfree(ctx->amqueue);
852*572c4311Sfengbojiang     ctx->amqueue = NULL;
853*572c4311Sfengbojiang     ctx->amqueue_len = 0;
854*572c4311Sfengbojiang     ctx->amqueue_used = 0;
855*572c4311Sfengbojiang }
856*572c4311Sfengbojiang 
857*572c4311Sfengbojiang /* --------------------------------------------------------------------------
858*572c4311Sfengbojiang  * String objects APIs
859*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
860*572c4311Sfengbojiang 
861*572c4311Sfengbojiang /* Create a new module string object. The returned string must be freed
862*572c4311Sfengbojiang  * with RedisModule_FreeString(), unless automatic memory is enabled.
863*572c4311Sfengbojiang  *
864*572c4311Sfengbojiang  * The string is created by copying the `len` bytes starting
865*572c4311Sfengbojiang  * at `ptr`. No reference is retained to the passed buffer.
866*572c4311Sfengbojiang  *
867*572c4311Sfengbojiang  * The module context 'ctx' is optional and may be NULL if you want to create
868*572c4311Sfengbojiang  * a string out of the context scope. However in that case, the automatic
869*572c4311Sfengbojiang  * memory management will not be available, and the string memory must be
870*572c4311Sfengbojiang  * managed manually. */
RM_CreateString(RedisModuleCtx * ctx,const char * ptr,size_t len)871*572c4311Sfengbojiang RedisModuleString *RM_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len) {
872*572c4311Sfengbojiang     RedisModuleString *o = createStringObject(ptr,len);
873*572c4311Sfengbojiang     if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
874*572c4311Sfengbojiang     return o;
875*572c4311Sfengbojiang }
876*572c4311Sfengbojiang 
877*572c4311Sfengbojiang /* Create a new module string object from a printf format and arguments.
878*572c4311Sfengbojiang  * The returned string must be freed with RedisModule_FreeString(), unless
879*572c4311Sfengbojiang  * automatic memory is enabled.
880*572c4311Sfengbojiang  *
881*572c4311Sfengbojiang  * The string is created using the sds formatter function sdscatvprintf().
882*572c4311Sfengbojiang  *
883*572c4311Sfengbojiang  * The passed context 'ctx' may be NULL if necessary, see the
884*572c4311Sfengbojiang  * RedisModule_CreateString() documentation for more info. */
RM_CreateStringPrintf(RedisModuleCtx * ctx,const char * fmt,...)885*572c4311Sfengbojiang RedisModuleString *RM_CreateStringPrintf(RedisModuleCtx *ctx, const char *fmt, ...) {
886*572c4311Sfengbojiang     sds s = sdsempty();
887*572c4311Sfengbojiang 
888*572c4311Sfengbojiang     va_list ap;
889*572c4311Sfengbojiang     va_start(ap, fmt);
890*572c4311Sfengbojiang     s = sdscatvprintf(s, fmt, ap);
891*572c4311Sfengbojiang     va_end(ap);
892*572c4311Sfengbojiang 
893*572c4311Sfengbojiang     RedisModuleString *o = createObject(OBJ_STRING, s);
894*572c4311Sfengbojiang     if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
895*572c4311Sfengbojiang 
896*572c4311Sfengbojiang     return o;
897*572c4311Sfengbojiang }
898*572c4311Sfengbojiang 
899*572c4311Sfengbojiang 
900*572c4311Sfengbojiang /* Like RedisModule_CreatString(), but creates a string starting from a long long
901*572c4311Sfengbojiang  * integer instead of taking a buffer and its length.
902*572c4311Sfengbojiang  *
903*572c4311Sfengbojiang  * The returned string must be released with RedisModule_FreeString() or by
904*572c4311Sfengbojiang  * enabling automatic memory management.
905*572c4311Sfengbojiang  *
906*572c4311Sfengbojiang  * The passed context 'ctx' may be NULL if necessary, see the
907*572c4311Sfengbojiang  * RedisModule_CreateString() documentation for more info. */
RM_CreateStringFromLongLong(RedisModuleCtx * ctx,long long ll)908*572c4311Sfengbojiang RedisModuleString *RM_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll) {
909*572c4311Sfengbojiang     char buf[LONG_STR_SIZE];
910*572c4311Sfengbojiang     size_t len = ll2string(buf,sizeof(buf),ll);
911*572c4311Sfengbojiang     return RM_CreateString(ctx,buf,len);
912*572c4311Sfengbojiang }
913*572c4311Sfengbojiang 
914*572c4311Sfengbojiang /* Like RedisModule_CreatString(), but creates a string starting from another
915*572c4311Sfengbojiang  * RedisModuleString.
916*572c4311Sfengbojiang  *
917*572c4311Sfengbojiang  * The returned string must be released with RedisModule_FreeString() or by
918*572c4311Sfengbojiang  * enabling automatic memory management.
919*572c4311Sfengbojiang  *
920*572c4311Sfengbojiang  * The passed context 'ctx' may be NULL if necessary, see the
921*572c4311Sfengbojiang  * RedisModule_CreateString() documentation for more info. */
RM_CreateStringFromString(RedisModuleCtx * ctx,const RedisModuleString * str)922*572c4311Sfengbojiang RedisModuleString *RM_CreateStringFromString(RedisModuleCtx *ctx, const RedisModuleString *str) {
923*572c4311Sfengbojiang     RedisModuleString *o = dupStringObject(str);
924*572c4311Sfengbojiang     if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
925*572c4311Sfengbojiang     return o;
926*572c4311Sfengbojiang }
927*572c4311Sfengbojiang 
928*572c4311Sfengbojiang /* Free a module string object obtained with one of the Redis modules API calls
929*572c4311Sfengbojiang  * that return new string objects.
930*572c4311Sfengbojiang  *
931*572c4311Sfengbojiang  * It is possible to call this function even when automatic memory management
932*572c4311Sfengbojiang  * is enabled. In that case the string will be released ASAP and removed
933*572c4311Sfengbojiang  * from the pool of string to release at the end.
934*572c4311Sfengbojiang  *
935*572c4311Sfengbojiang  * If the string was created with a NULL context 'ctx', it is also possible to
936*572c4311Sfengbojiang  * pass ctx as NULL when releasing the string (but passing a context will not
937*572c4311Sfengbojiang  * create any issue). Strings created with a context should be freed also passing
938*572c4311Sfengbojiang  * the context, so if you want to free a string out of context later, make sure
939*572c4311Sfengbojiang  * to create it using a NULL context. */
RM_FreeString(RedisModuleCtx * ctx,RedisModuleString * str)940*572c4311Sfengbojiang void RM_FreeString(RedisModuleCtx *ctx, RedisModuleString *str) {
941*572c4311Sfengbojiang     decrRefCount(str);
942*572c4311Sfengbojiang     if (ctx != NULL) autoMemoryFreed(ctx,REDISMODULE_AM_STRING,str);
943*572c4311Sfengbojiang }
944*572c4311Sfengbojiang 
945*572c4311Sfengbojiang /* Every call to this function, will make the string 'str' requiring
946*572c4311Sfengbojiang  * an additional call to RedisModule_FreeString() in order to really
947*572c4311Sfengbojiang  * free the string. Note that the automatic freeing of the string obtained
948*572c4311Sfengbojiang  * enabling modules automatic memory management counts for one
949*572c4311Sfengbojiang  * RedisModule_FreeString() call (it is just executed automatically).
950*572c4311Sfengbojiang  *
951*572c4311Sfengbojiang  * Normally you want to call this function when, at the same time
952*572c4311Sfengbojiang  * the following conditions are true:
953*572c4311Sfengbojiang  *
954*572c4311Sfengbojiang  * 1) You have automatic memory management enabled.
955*572c4311Sfengbojiang  * 2) You want to create string objects.
956*572c4311Sfengbojiang  * 3) Those string objects you create need to live *after* the callback
957*572c4311Sfengbojiang  *    function(for example a command implementation) creating them returns.
958*572c4311Sfengbojiang  *
959*572c4311Sfengbojiang  * Usually you want this in order to store the created string object
960*572c4311Sfengbojiang  * into your own data structure, for example when implementing a new data
961*572c4311Sfengbojiang  * type.
962*572c4311Sfengbojiang  *
963*572c4311Sfengbojiang  * Note that when memory management is turned off, you don't need
964*572c4311Sfengbojiang  * any call to RetainString() since creating a string will always result
965*572c4311Sfengbojiang  * into a string that lives after the callback function returns, if
966*572c4311Sfengbojiang  * no FreeString() call is performed.
967*572c4311Sfengbojiang  *
968*572c4311Sfengbojiang  * It is possible to call this function with a NULL context. */
RM_RetainString(RedisModuleCtx * ctx,RedisModuleString * str)969*572c4311Sfengbojiang void RM_RetainString(RedisModuleCtx *ctx, RedisModuleString *str) {
970*572c4311Sfengbojiang     if (ctx == NULL || !autoMemoryFreed(ctx,REDISMODULE_AM_STRING,str)) {
971*572c4311Sfengbojiang         /* Increment the string reference counting only if we can't
972*572c4311Sfengbojiang          * just remove the object from the list of objects that should
973*572c4311Sfengbojiang          * be reclaimed. Why we do that, instead of just incrementing
974*572c4311Sfengbojiang          * the refcount in any case, and let the automatic FreeString()
975*572c4311Sfengbojiang          * call at the end to bring the refcount back at the desired
976*572c4311Sfengbojiang          * value? Because this way we ensure that the object refcount
977*572c4311Sfengbojiang          * value is 1 (instead of going to 2 to be dropped later to 1)
978*572c4311Sfengbojiang          * after the call to this function. This is needed for functions
979*572c4311Sfengbojiang          * like RedisModule_StringAppendBuffer() to work. */
980*572c4311Sfengbojiang         incrRefCount(str);
981*572c4311Sfengbojiang     }
982*572c4311Sfengbojiang }
983*572c4311Sfengbojiang 
984*572c4311Sfengbojiang /* Given a string module object, this function returns the string pointer
985*572c4311Sfengbojiang  * and length of the string. The returned pointer and length should only
986*572c4311Sfengbojiang  * be used for read only accesses and never modified. */
RM_StringPtrLen(const RedisModuleString * str,size_t * len)987*572c4311Sfengbojiang const char *RM_StringPtrLen(const RedisModuleString *str, size_t *len) {
988*572c4311Sfengbojiang     if (str == NULL) {
989*572c4311Sfengbojiang         const char *errmsg = "(NULL string reply referenced in module)";
990*572c4311Sfengbojiang         if (len) *len = strlen(errmsg);
991*572c4311Sfengbojiang         return errmsg;
992*572c4311Sfengbojiang     }
993*572c4311Sfengbojiang     if (len) *len = sdslen(str->ptr);
994*572c4311Sfengbojiang     return str->ptr;
995*572c4311Sfengbojiang }
996*572c4311Sfengbojiang 
997*572c4311Sfengbojiang /* --------------------------------------------------------------------------
998*572c4311Sfengbojiang  * Higher level string operations
999*572c4311Sfengbojiang  * ------------------------------------------------------------------------- */
1000*572c4311Sfengbojiang 
1001*572c4311Sfengbojiang /* Convert the string into a long long integer, storing it at `*ll`.
1002*572c4311Sfengbojiang  * Returns REDISMODULE_OK on success. If the string can't be parsed
1003*572c4311Sfengbojiang  * as a valid, strict long long (no spaces before/after), REDISMODULE_ERR
1004*572c4311Sfengbojiang  * is returned. */
RM_StringToLongLong(const RedisModuleString * str,long long * ll)1005*572c4311Sfengbojiang int RM_StringToLongLong(const RedisModuleString *str, long long *ll) {
1006*572c4311Sfengbojiang     return string2ll(str->ptr,sdslen(str->ptr),ll) ? REDISMODULE_OK :
1007*572c4311Sfengbojiang                                                      REDISMODULE_ERR;
1008*572c4311Sfengbojiang }
1009*572c4311Sfengbojiang 
1010*572c4311Sfengbojiang /* Convert the string into a double, storing it at `*d`.
1011*572c4311Sfengbojiang  * Returns REDISMODULE_OK on success or REDISMODULE_ERR if the string is
1012*572c4311Sfengbojiang  * not a valid string representation of a double value. */
RM_StringToDouble(const RedisModuleString * str,double * d)1013*572c4311Sfengbojiang int RM_StringToDouble(const RedisModuleString *str, double *d) {
1014*572c4311Sfengbojiang     int retval = getDoubleFromObject(str,d);
1015*572c4311Sfengbojiang     return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
1016*572c4311Sfengbojiang }
1017*572c4311Sfengbojiang 
1018*572c4311Sfengbojiang /* Compare two string objects, returning -1, 0 or 1 respectively if
1019*572c4311Sfengbojiang  * a < b, a == b, a > b. Strings are compared byte by byte as two
1020*572c4311Sfengbojiang  * binary blobs without any encoding care / collation attempt. */
RM_StringCompare(RedisModuleString * a,RedisModuleString * b)1021*572c4311Sfengbojiang int RM_StringCompare(RedisModuleString *a, RedisModuleString *b) {
1022*572c4311Sfengbojiang     return compareStringObjects(a,b);
1023*572c4311Sfengbojiang }
1024*572c4311Sfengbojiang 
1025*572c4311Sfengbojiang /* Return the (possibly modified in encoding) input 'str' object if
1026*572c4311Sfengbojiang  * the string is unshared, otherwise NULL is returned. */
moduleAssertUnsharedString(RedisModuleString * str)1027*572c4311Sfengbojiang RedisModuleString *moduleAssertUnsharedString(RedisModuleString *str) {
1028*572c4311Sfengbojiang     if (str->refcount != 1) {
1029*572c4311Sfengbojiang         serverLog(LL_WARNING,
1030*572c4311Sfengbojiang             "Module attempted to use an in-place string modify operation "
1031*572c4311Sfengbojiang             "with a string referenced multiple times. Please check the code "
1032*572c4311Sfengbojiang             "for API usage correctness.");
1033*572c4311Sfengbojiang         return NULL;
1034*572c4311Sfengbojiang     }
1035*572c4311Sfengbojiang     if (str->encoding == OBJ_ENCODING_EMBSTR) {
1036*572c4311Sfengbojiang         /* Note: here we "leak" the additional allocation that was
1037*572c4311Sfengbojiang          * used in order to store the embedded string in the object. */
1038*572c4311Sfengbojiang         str->ptr = sdsnewlen(str->ptr,sdslen(str->ptr));
1039*572c4311Sfengbojiang         str->encoding = OBJ_ENCODING_RAW;
1040*572c4311Sfengbojiang     } else if (str->encoding == OBJ_ENCODING_INT) {
1041*572c4311Sfengbojiang         /* Convert the string from integer to raw encoding. */
1042*572c4311Sfengbojiang         str->ptr = sdsfromlonglong((long)str->ptr);
1043*572c4311Sfengbojiang         str->encoding = OBJ_ENCODING_RAW;
1044*572c4311Sfengbojiang     }
1045*572c4311Sfengbojiang     return str;
1046*572c4311Sfengbojiang }
1047*572c4311Sfengbojiang 
1048*572c4311Sfengbojiang /* Append the specified buffer to the string 'str'. The string must be a
1049*572c4311Sfengbojiang  * string created by the user that is referenced only a single time, otherwise
1050*572c4311Sfengbojiang  * REDISMODULE_ERR is returned and the operation is not performed. */
RM_StringAppendBuffer(RedisModuleCtx * ctx,RedisModuleString * str,const char * buf,size_t len)1051*572c4311Sfengbojiang int RM_StringAppendBuffer(RedisModuleCtx *ctx, RedisModuleString *str, const char *buf, size_t len) {
1052*572c4311Sfengbojiang     UNUSED(ctx);
1053*572c4311Sfengbojiang     str = moduleAssertUnsharedString(str);
1054*572c4311Sfengbojiang     if (str == NULL) return REDISMODULE_ERR;
1055*572c4311Sfengbojiang     str->ptr = sdscatlen(str->ptr,buf,len);
1056*572c4311Sfengbojiang     return REDISMODULE_OK;
1057*572c4311Sfengbojiang }
1058*572c4311Sfengbojiang 
1059*572c4311Sfengbojiang /* --------------------------------------------------------------------------
1060*572c4311Sfengbojiang  * Reply APIs
1061*572c4311Sfengbojiang  *
1062*572c4311Sfengbojiang  * Most functions always return REDISMODULE_OK so you can use it with
1063*572c4311Sfengbojiang  * 'return' in order to return from the command implementation with:
1064*572c4311Sfengbojiang  *
1065*572c4311Sfengbojiang  *     if (... some condition ...)
1066*572c4311Sfengbojiang  *         return RM_ReplyWithLongLong(ctx,mycount);
1067*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
1068*572c4311Sfengbojiang 
1069*572c4311Sfengbojiang /* Send an error about the number of arguments given to the command,
1070*572c4311Sfengbojiang  * citing the command name in the error message.
1071*572c4311Sfengbojiang  *
1072*572c4311Sfengbojiang  * Example:
1073*572c4311Sfengbojiang  *
1074*572c4311Sfengbojiang  *     if (argc != 3) return RedisModule_WrongArity(ctx);
1075*572c4311Sfengbojiang  */
RM_WrongArity(RedisModuleCtx * ctx)1076*572c4311Sfengbojiang int RM_WrongArity(RedisModuleCtx *ctx) {
1077*572c4311Sfengbojiang     addReplyErrorFormat(ctx->client,
1078*572c4311Sfengbojiang         "wrong number of arguments for '%s' command",
1079*572c4311Sfengbojiang         (char*)ctx->client->argv[0]->ptr);
1080*572c4311Sfengbojiang     return REDISMODULE_OK;
1081*572c4311Sfengbojiang }
1082*572c4311Sfengbojiang 
1083*572c4311Sfengbojiang /* Return the client object the `RM_Reply*` functions should target.
1084*572c4311Sfengbojiang  * Normally this is just `ctx->client`, that is the client that called
1085*572c4311Sfengbojiang  * the module command, however in the case of thread safe contexts there
1086*572c4311Sfengbojiang  * is no directly associated client (since it would not be safe to access
1087*572c4311Sfengbojiang  * the client from a thread), so instead the blocked client object referenced
1088*572c4311Sfengbojiang  * in the thread safe context, has a fake client that we just use to accumulate
1089*572c4311Sfengbojiang  * the replies. Later, when the client is unblocked, the accumulated replies
1090*572c4311Sfengbojiang  * are appended to the actual client.
1091*572c4311Sfengbojiang  *
1092*572c4311Sfengbojiang  * The function returns the client pointer depending on the context, or
1093*572c4311Sfengbojiang  * NULL if there is no potential client. This happens when we are in the
1094*572c4311Sfengbojiang  * context of a thread safe context that was not initialized with a blocked
1095*572c4311Sfengbojiang  * client object. Other contexts without associated clients are the ones
1096*572c4311Sfengbojiang  * initialized to run the timers callbacks. */
moduleGetReplyClient(RedisModuleCtx * ctx)1097*572c4311Sfengbojiang client *moduleGetReplyClient(RedisModuleCtx *ctx) {
1098*572c4311Sfengbojiang     if (ctx->flags & REDISMODULE_CTX_THREAD_SAFE) {
1099*572c4311Sfengbojiang         if (ctx->blocked_client)
1100*572c4311Sfengbojiang             return ctx->blocked_client->reply_client;
1101*572c4311Sfengbojiang         else
1102*572c4311Sfengbojiang             return NULL;
1103*572c4311Sfengbojiang     } else {
1104*572c4311Sfengbojiang         /* If this is a non thread safe context, just return the client
1105*572c4311Sfengbojiang          * that is running the command if any. This may be NULL as well
1106*572c4311Sfengbojiang          * in the case of contexts that are not executed with associated
1107*572c4311Sfengbojiang          * clients, like timer contexts. */
1108*572c4311Sfengbojiang         return ctx->client;
1109*572c4311Sfengbojiang     }
1110*572c4311Sfengbojiang }
1111*572c4311Sfengbojiang 
1112*572c4311Sfengbojiang /* Send an integer reply to the client, with the specified long long value.
1113*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplyWithLongLong(RedisModuleCtx * ctx,long long ll)1114*572c4311Sfengbojiang int RM_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll) {
1115*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1116*572c4311Sfengbojiang     if (c == NULL) return REDISMODULE_OK;
1117*572c4311Sfengbojiang     addReplyLongLong(c,ll);
1118*572c4311Sfengbojiang     return REDISMODULE_OK;
1119*572c4311Sfengbojiang }
1120*572c4311Sfengbojiang 
1121*572c4311Sfengbojiang /* Reply with an error or simple string (status message). Used to implement
1122*572c4311Sfengbojiang  * ReplyWithSimpleString() and ReplyWithError().
1123*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
replyWithStatus(RedisModuleCtx * ctx,const char * msg,char * prefix)1124*572c4311Sfengbojiang int replyWithStatus(RedisModuleCtx *ctx, const char *msg, char *prefix) {
1125*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1126*572c4311Sfengbojiang     if (c == NULL) return REDISMODULE_OK;
1127*572c4311Sfengbojiang     sds strmsg = sdsnewlen(prefix,1);
1128*572c4311Sfengbojiang     strmsg = sdscat(strmsg,msg);
1129*572c4311Sfengbojiang     strmsg = sdscatlen(strmsg,"\r\n",2);
1130*572c4311Sfengbojiang     addReplySds(c,strmsg);
1131*572c4311Sfengbojiang     return REDISMODULE_OK;
1132*572c4311Sfengbojiang }
1133*572c4311Sfengbojiang 
1134*572c4311Sfengbojiang /* Reply with the error 'err'.
1135*572c4311Sfengbojiang  *
1136*572c4311Sfengbojiang  * Note that 'err' must contain all the error, including
1137*572c4311Sfengbojiang  * the initial error code. The function only provides the initial "-", so
1138*572c4311Sfengbojiang  * the usage is, for example:
1139*572c4311Sfengbojiang  *
1140*572c4311Sfengbojiang  *     RedisModule_ReplyWithError(ctx,"ERR Wrong Type");
1141*572c4311Sfengbojiang  *
1142*572c4311Sfengbojiang  * and not just:
1143*572c4311Sfengbojiang  *
1144*572c4311Sfengbojiang  *     RedisModule_ReplyWithError(ctx,"Wrong Type");
1145*572c4311Sfengbojiang  *
1146*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK.
1147*572c4311Sfengbojiang  */
RM_ReplyWithError(RedisModuleCtx * ctx,const char * err)1148*572c4311Sfengbojiang int RM_ReplyWithError(RedisModuleCtx *ctx, const char *err) {
1149*572c4311Sfengbojiang     return replyWithStatus(ctx,err,"-");
1150*572c4311Sfengbojiang }
1151*572c4311Sfengbojiang 
1152*572c4311Sfengbojiang /* Reply with a simple string (+... \r\n in RESP protocol). This replies
1153*572c4311Sfengbojiang  * are suitable only when sending a small non-binary string with small
1154*572c4311Sfengbojiang  * overhead, like "OK" or similar replies.
1155*572c4311Sfengbojiang  *
1156*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplyWithSimpleString(RedisModuleCtx * ctx,const char * msg)1157*572c4311Sfengbojiang int RM_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg) {
1158*572c4311Sfengbojiang     return replyWithStatus(ctx,msg,"+");
1159*572c4311Sfengbojiang }
1160*572c4311Sfengbojiang 
1161*572c4311Sfengbojiang /* Reply with an array type of 'len' elements. However 'len' other calls
1162*572c4311Sfengbojiang  * to `ReplyWith*` style functions must follow in order to emit the elements
1163*572c4311Sfengbojiang  * of the array.
1164*572c4311Sfengbojiang  *
1165*572c4311Sfengbojiang  * When producing arrays with a number of element that is not known beforehand
1166*572c4311Sfengbojiang  * the function can be called with the special count
1167*572c4311Sfengbojiang  * REDISMODULE_POSTPONED_ARRAY_LEN, and the actual number of elements can be
1168*572c4311Sfengbojiang  * later set with RedisModule_ReplySetArrayLength() (which will set the
1169*572c4311Sfengbojiang  * latest "open" count if there are multiple ones).
1170*572c4311Sfengbojiang  *
1171*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplyWithArray(RedisModuleCtx * ctx,long len)1172*572c4311Sfengbojiang int RM_ReplyWithArray(RedisModuleCtx *ctx, long len) {
1173*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1174*572c4311Sfengbojiang     if (c == NULL) return REDISMODULE_OK;
1175*572c4311Sfengbojiang     if (len == REDISMODULE_POSTPONED_ARRAY_LEN) {
1176*572c4311Sfengbojiang         ctx->postponed_arrays = zrealloc(ctx->postponed_arrays,sizeof(void*)*
1177*572c4311Sfengbojiang                 (ctx->postponed_arrays_count+1));
1178*572c4311Sfengbojiang         ctx->postponed_arrays[ctx->postponed_arrays_count] =
1179*572c4311Sfengbojiang             addDeferredMultiBulkLength(c);
1180*572c4311Sfengbojiang         ctx->postponed_arrays_count++;
1181*572c4311Sfengbojiang     } else {
1182*572c4311Sfengbojiang         addReplyMultiBulkLen(c,len);
1183*572c4311Sfengbojiang     }
1184*572c4311Sfengbojiang     return REDISMODULE_OK;
1185*572c4311Sfengbojiang }
1186*572c4311Sfengbojiang 
1187*572c4311Sfengbojiang /* When RedisModule_ReplyWithArray() is used with the argument
1188*572c4311Sfengbojiang  * REDISMODULE_POSTPONED_ARRAY_LEN, because we don't know beforehand the number
1189*572c4311Sfengbojiang  * of items we are going to output as elements of the array, this function
1190*572c4311Sfengbojiang  * will take care to set the array length.
1191*572c4311Sfengbojiang  *
1192*572c4311Sfengbojiang  * Since it is possible to have multiple array replies pending with unknown
1193*572c4311Sfengbojiang  * length, this function guarantees to always set the latest array length
1194*572c4311Sfengbojiang  * that was created in a postponed way.
1195*572c4311Sfengbojiang  *
1196*572c4311Sfengbojiang  * For example in order to output an array like [1,[10,20,30]] we
1197*572c4311Sfengbojiang  * could write:
1198*572c4311Sfengbojiang  *
1199*572c4311Sfengbojiang  *      RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_ARRAY_LEN);
1200*572c4311Sfengbojiang  *      RedisModule_ReplyWithLongLong(ctx,1);
1201*572c4311Sfengbojiang  *      RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_ARRAY_LEN);
1202*572c4311Sfengbojiang  *      RedisModule_ReplyWithLongLong(ctx,10);
1203*572c4311Sfengbojiang  *      RedisModule_ReplyWithLongLong(ctx,20);
1204*572c4311Sfengbojiang  *      RedisModule_ReplyWithLongLong(ctx,30);
1205*572c4311Sfengbojiang  *      RedisModule_ReplySetArrayLength(ctx,3); // Set len of 10,20,30 array.
1206*572c4311Sfengbojiang  *      RedisModule_ReplySetArrayLength(ctx,2); // Set len of top array
1207*572c4311Sfengbojiang  *
1208*572c4311Sfengbojiang  * Note that in the above example there is no reason to postpone the array
1209*572c4311Sfengbojiang  * length, since we produce a fixed number of elements, but in the practice
1210*572c4311Sfengbojiang  * the code may use an iterator or other ways of creating the output so
1211*572c4311Sfengbojiang  * that is not easy to calculate in advance the number of elements.
1212*572c4311Sfengbojiang  */
RM_ReplySetArrayLength(RedisModuleCtx * ctx,long len)1213*572c4311Sfengbojiang void RM_ReplySetArrayLength(RedisModuleCtx *ctx, long len) {
1214*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1215*572c4311Sfengbojiang     if (c == NULL) return;
1216*572c4311Sfengbojiang     if (ctx->postponed_arrays_count == 0) {
1217*572c4311Sfengbojiang         serverLog(LL_WARNING,
1218*572c4311Sfengbojiang             "API misuse detected in module %s: "
1219*572c4311Sfengbojiang             "RedisModule_ReplySetArrayLength() called without previous "
1220*572c4311Sfengbojiang             "RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_ARRAY_LEN) "
1221*572c4311Sfengbojiang             "call.", ctx->module->name);
1222*572c4311Sfengbojiang             return;
1223*572c4311Sfengbojiang     }
1224*572c4311Sfengbojiang     ctx->postponed_arrays_count--;
1225*572c4311Sfengbojiang     setDeferredMultiBulkLength(c,
1226*572c4311Sfengbojiang             ctx->postponed_arrays[ctx->postponed_arrays_count],
1227*572c4311Sfengbojiang             len);
1228*572c4311Sfengbojiang     if (ctx->postponed_arrays_count == 0) {
1229*572c4311Sfengbojiang         zfree(ctx->postponed_arrays);
1230*572c4311Sfengbojiang         ctx->postponed_arrays = NULL;
1231*572c4311Sfengbojiang     }
1232*572c4311Sfengbojiang }
1233*572c4311Sfengbojiang 
1234*572c4311Sfengbojiang /* Reply with a bulk string, taking in input a C buffer pointer and length.
1235*572c4311Sfengbojiang  *
1236*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplyWithStringBuffer(RedisModuleCtx * ctx,const char * buf,size_t len)1237*572c4311Sfengbojiang int RM_ReplyWithStringBuffer(RedisModuleCtx *ctx, const char *buf, size_t len) {
1238*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1239*572c4311Sfengbojiang     if (c == NULL) return REDISMODULE_OK;
1240*572c4311Sfengbojiang     addReplyBulkCBuffer(c,(char*)buf,len);
1241*572c4311Sfengbojiang     return REDISMODULE_OK;
1242*572c4311Sfengbojiang }
1243*572c4311Sfengbojiang 
1244*572c4311Sfengbojiang /* Reply with a bulk string, taking in input a RedisModuleString object.
1245*572c4311Sfengbojiang  *
1246*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplyWithString(RedisModuleCtx * ctx,RedisModuleString * str)1247*572c4311Sfengbojiang int RM_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str) {
1248*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1249*572c4311Sfengbojiang     if (c == NULL) return REDISMODULE_OK;
1250*572c4311Sfengbojiang     addReplyBulk(c,str);
1251*572c4311Sfengbojiang     return REDISMODULE_OK;
1252*572c4311Sfengbojiang }
1253*572c4311Sfengbojiang 
1254*572c4311Sfengbojiang /* Reply to the client with a NULL. In the RESP protocol a NULL is encoded
1255*572c4311Sfengbojiang  * as the string "$-1\r\n".
1256*572c4311Sfengbojiang  *
1257*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplyWithNull(RedisModuleCtx * ctx)1258*572c4311Sfengbojiang int RM_ReplyWithNull(RedisModuleCtx *ctx) {
1259*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1260*572c4311Sfengbojiang     if (c == NULL) return REDISMODULE_OK;
1261*572c4311Sfengbojiang     addReply(c,shared.nullbulk);
1262*572c4311Sfengbojiang     return REDISMODULE_OK;
1263*572c4311Sfengbojiang }
1264*572c4311Sfengbojiang 
1265*572c4311Sfengbojiang /* Reply exactly what a Redis command returned us with RedisModule_Call().
1266*572c4311Sfengbojiang  * This function is useful when we use RedisModule_Call() in order to
1267*572c4311Sfengbojiang  * execute some command, as we want to reply to the client exactly the
1268*572c4311Sfengbojiang  * same reply we obtained by the command.
1269*572c4311Sfengbojiang  *
1270*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplyWithCallReply(RedisModuleCtx * ctx,RedisModuleCallReply * reply)1271*572c4311Sfengbojiang int RM_ReplyWithCallReply(RedisModuleCtx *ctx, RedisModuleCallReply *reply) {
1272*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1273*572c4311Sfengbojiang     if (c == NULL) return REDISMODULE_OK;
1274*572c4311Sfengbojiang     sds proto = sdsnewlen(reply->proto, reply->protolen);
1275*572c4311Sfengbojiang     addReplySds(c,proto);
1276*572c4311Sfengbojiang     return REDISMODULE_OK;
1277*572c4311Sfengbojiang }
1278*572c4311Sfengbojiang 
1279*572c4311Sfengbojiang /* Send a string reply obtained converting the double 'd' into a bulk string.
1280*572c4311Sfengbojiang  * This function is basically equivalent to converting a double into
1281*572c4311Sfengbojiang  * a string into a C buffer, and then calling the function
1282*572c4311Sfengbojiang  * RedisModule_ReplyWithStringBuffer() with the buffer and length.
1283*572c4311Sfengbojiang  *
1284*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplyWithDouble(RedisModuleCtx * ctx,double d)1285*572c4311Sfengbojiang int RM_ReplyWithDouble(RedisModuleCtx *ctx, double d) {
1286*572c4311Sfengbojiang     client *c = moduleGetReplyClient(ctx);
1287*572c4311Sfengbojiang     if (c == NULL) return REDISMODULE_OK;
1288*572c4311Sfengbojiang     addReplyDouble(c,d);
1289*572c4311Sfengbojiang     return REDISMODULE_OK;
1290*572c4311Sfengbojiang }
1291*572c4311Sfengbojiang 
1292*572c4311Sfengbojiang /* --------------------------------------------------------------------------
1293*572c4311Sfengbojiang  * Commands replication API
1294*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
1295*572c4311Sfengbojiang 
1296*572c4311Sfengbojiang /* Helper function to replicate MULTI the first time we replicate something
1297*572c4311Sfengbojiang  * in the context of a command execution. EXEC will be handled by the
1298*572c4311Sfengbojiang  * RedisModuleCommandDispatcher() function. */
moduleReplicateMultiIfNeeded(RedisModuleCtx * ctx)1299*572c4311Sfengbojiang void moduleReplicateMultiIfNeeded(RedisModuleCtx *ctx) {
1300*572c4311Sfengbojiang     /* Skip this if client explicitly wrap the command with MULTI, or if
1301*572c4311Sfengbojiang      * the module command was called by a script. */
1302*572c4311Sfengbojiang     if (ctx->client->flags & (CLIENT_MULTI|CLIENT_LUA)) return;
1303*572c4311Sfengbojiang     /* If we already emitted MULTI return ASAP. */
1304*572c4311Sfengbojiang     if (ctx->flags & REDISMODULE_CTX_MULTI_EMITTED) return;
1305*572c4311Sfengbojiang     /* If this is a thread safe context, we do not want to wrap commands
1306*572c4311Sfengbojiang      * executed into MUTLI/EXEC, they are executed as single commands
1307*572c4311Sfengbojiang      * from an external client in essence. */
1308*572c4311Sfengbojiang     if (ctx->flags & REDISMODULE_CTX_THREAD_SAFE) return;
1309*572c4311Sfengbojiang     execCommandPropagateMulti(ctx->client);
1310*572c4311Sfengbojiang     ctx->flags |= REDISMODULE_CTX_MULTI_EMITTED;
1311*572c4311Sfengbojiang }
1312*572c4311Sfengbojiang 
1313*572c4311Sfengbojiang /* Replicate the specified command and arguments to slaves and AOF, as effect
1314*572c4311Sfengbojiang  * of execution of the calling command implementation.
1315*572c4311Sfengbojiang  *
1316*572c4311Sfengbojiang  * The replicated commands are always wrapped into the MULTI/EXEC that
1317*572c4311Sfengbojiang  * contains all the commands replicated in a given module command
1318*572c4311Sfengbojiang  * execution. However the commands replicated with RedisModule_Call()
1319*572c4311Sfengbojiang  * are the first items, the ones replicated with RedisModule_Replicate()
1320*572c4311Sfengbojiang  * will all follow before the EXEC.
1321*572c4311Sfengbojiang  *
1322*572c4311Sfengbojiang  * Modules should try to use one interface or the other.
1323*572c4311Sfengbojiang  *
1324*572c4311Sfengbojiang  * This command follows exactly the same interface of RedisModule_Call(),
1325*572c4311Sfengbojiang  * so a set of format specifiers must be passed, followed by arguments
1326*572c4311Sfengbojiang  * matching the provided format specifiers.
1327*572c4311Sfengbojiang  *
1328*572c4311Sfengbojiang  * Please refer to RedisModule_Call() for more information.
1329*572c4311Sfengbojiang  *
1330*572c4311Sfengbojiang  * The command returns REDISMODULE_ERR if the format specifiers are invalid
1331*572c4311Sfengbojiang  * or the command name does not belong to a known command. */
RM_Replicate(RedisModuleCtx * ctx,const char * cmdname,const char * fmt,...)1332*572c4311Sfengbojiang int RM_Replicate(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
1333*572c4311Sfengbojiang     struct redisCommand *cmd;
1334*572c4311Sfengbojiang     robj **argv = NULL;
1335*572c4311Sfengbojiang     int argc = 0, flags = 0, j;
1336*572c4311Sfengbojiang     va_list ap;
1337*572c4311Sfengbojiang 
1338*572c4311Sfengbojiang     cmd = lookupCommandByCString((char*)cmdname);
1339*572c4311Sfengbojiang     if (!cmd) return REDISMODULE_ERR;
1340*572c4311Sfengbojiang 
1341*572c4311Sfengbojiang     /* Create the client and dispatch the command. */
1342*572c4311Sfengbojiang     va_start(ap, fmt);
1343*572c4311Sfengbojiang     argv = moduleCreateArgvFromUserFormat(cmdname,fmt,&argc,&flags,ap);
1344*572c4311Sfengbojiang     va_end(ap);
1345*572c4311Sfengbojiang     if (argv == NULL) return REDISMODULE_ERR;
1346*572c4311Sfengbojiang 
1347*572c4311Sfengbojiang     /* Replicate! */
1348*572c4311Sfengbojiang     moduleReplicateMultiIfNeeded(ctx);
1349*572c4311Sfengbojiang     alsoPropagate(cmd,ctx->client->db->id,argv,argc,
1350*572c4311Sfengbojiang         PROPAGATE_AOF|PROPAGATE_REPL);
1351*572c4311Sfengbojiang 
1352*572c4311Sfengbojiang     /* Release the argv. */
1353*572c4311Sfengbojiang     for (j = 0; j < argc; j++) decrRefCount(argv[j]);
1354*572c4311Sfengbojiang     zfree(argv);
1355*572c4311Sfengbojiang     server.dirty++;
1356*572c4311Sfengbojiang     return REDISMODULE_OK;
1357*572c4311Sfengbojiang }
1358*572c4311Sfengbojiang 
1359*572c4311Sfengbojiang /* This function will replicate the command exactly as it was invoked
1360*572c4311Sfengbojiang  * by the client. Note that this function will not wrap the command into
1361*572c4311Sfengbojiang  * a MULTI/EXEC stanza, so it should not be mixed with other replication
1362*572c4311Sfengbojiang  * commands.
1363*572c4311Sfengbojiang  *
1364*572c4311Sfengbojiang  * Basically this form of replication is useful when you want to propagate
1365*572c4311Sfengbojiang  * the command to the slaves and AOF file exactly as it was called, since
1366*572c4311Sfengbojiang  * the command can just be re-executed to deterministically re-create the
1367*572c4311Sfengbojiang  * new state starting from the old one.
1368*572c4311Sfengbojiang  *
1369*572c4311Sfengbojiang  * The function always returns REDISMODULE_OK. */
RM_ReplicateVerbatim(RedisModuleCtx * ctx)1370*572c4311Sfengbojiang int RM_ReplicateVerbatim(RedisModuleCtx *ctx) {
1371*572c4311Sfengbojiang     alsoPropagate(ctx->client->cmd,ctx->client->db->id,
1372*572c4311Sfengbojiang         ctx->client->argv,ctx->client->argc,
1373*572c4311Sfengbojiang         PROPAGATE_AOF|PROPAGATE_REPL);
1374*572c4311Sfengbojiang     server.dirty++;
1375*572c4311Sfengbojiang     return REDISMODULE_OK;
1376*572c4311Sfengbojiang }
1377*572c4311Sfengbojiang 
1378*572c4311Sfengbojiang /* --------------------------------------------------------------------------
1379*572c4311Sfengbojiang  * DB and Key APIs -- Generic API
1380*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
1381*572c4311Sfengbojiang 
1382*572c4311Sfengbojiang /* Return the ID of the current client calling the currently active module
1383*572c4311Sfengbojiang  * command. The returned ID has a few guarantees:
1384*572c4311Sfengbojiang  *
1385*572c4311Sfengbojiang  * 1. The ID is different for each different client, so if the same client
1386*572c4311Sfengbojiang  *    executes a module command multiple times, it can be recognized as
1387*572c4311Sfengbojiang  *    having the same ID, otherwise the ID will be different.
1388*572c4311Sfengbojiang  * 2. The ID increases monotonically. Clients connecting to the server later
1389*572c4311Sfengbojiang  *    are guaranteed to get IDs greater than any past ID previously seen.
1390*572c4311Sfengbojiang  *
1391*572c4311Sfengbojiang  * Valid IDs are from 1 to 2^64-1. If 0 is returned it means there is no way
1392*572c4311Sfengbojiang  * to fetch the ID in the context the function was currently called. */
RM_GetClientId(RedisModuleCtx * ctx)1393*572c4311Sfengbojiang unsigned long long RM_GetClientId(RedisModuleCtx *ctx) {
1394*572c4311Sfengbojiang     if (ctx->client == NULL) return 0;
1395*572c4311Sfengbojiang     return ctx->client->id;
1396*572c4311Sfengbojiang }
1397*572c4311Sfengbojiang 
1398*572c4311Sfengbojiang /* Return the currently selected DB. */
RM_GetSelectedDb(RedisModuleCtx * ctx)1399*572c4311Sfengbojiang int RM_GetSelectedDb(RedisModuleCtx *ctx) {
1400*572c4311Sfengbojiang     return ctx->client->db->id;
1401*572c4311Sfengbojiang }
1402*572c4311Sfengbojiang 
1403*572c4311Sfengbojiang 
1404*572c4311Sfengbojiang /* Return the current context's flags. The flags provide information on the
1405*572c4311Sfengbojiang  * current request context (whether the client is a Lua script or in a MULTI),
1406*572c4311Sfengbojiang  * and about the Redis instance in general, i.e replication and persistence.
1407*572c4311Sfengbojiang  *
1408*572c4311Sfengbojiang  * The available flags are:
1409*572c4311Sfengbojiang  *
1410*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_LUA: The command is running in a Lua script
1411*572c4311Sfengbojiang  *
1412*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_MULTI: The command is running inside a transaction
1413*572c4311Sfengbojiang  *
1414*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_REPLICATED: The command was sent over the replication
1415*572c4311Sfengbojiang  *    link by the MASTER
1416*572c4311Sfengbojiang  *
1417*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_MASTER: The Redis instance is a master
1418*572c4311Sfengbojiang  *
1419*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_SLAVE: The Redis instance is a slave
1420*572c4311Sfengbojiang  *
1421*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_READONLY: The Redis instance is read-only
1422*572c4311Sfengbojiang  *
1423*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_CLUSTER: The Redis instance is in cluster mode
1424*572c4311Sfengbojiang  *
1425*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_AOF: The Redis instance has AOF enabled
1426*572c4311Sfengbojiang  *
1427*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_RDB: The instance has RDB enabled
1428*572c4311Sfengbojiang  *
1429*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_MAXMEMORY:  The instance has Maxmemory set
1430*572c4311Sfengbojiang  *
1431*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_EVICT:  Maxmemory is set and has an eviction
1432*572c4311Sfengbojiang  *    policy that may delete keys
1433*572c4311Sfengbojiang  *
1434*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_OOM: Redis is out of memory according to the
1435*572c4311Sfengbojiang  *    maxmemory setting.
1436*572c4311Sfengbojiang  *
1437*572c4311Sfengbojiang  *  * REDISMODULE_CTX_FLAGS_OOM_WARNING: Less than 25% of memory remains before
1438*572c4311Sfengbojiang  *                                       reaching the maxmemory level.
1439*572c4311Sfengbojiang  */
RM_GetContextFlags(RedisModuleCtx * ctx)1440*572c4311Sfengbojiang int RM_GetContextFlags(RedisModuleCtx *ctx) {
1441*572c4311Sfengbojiang 
1442*572c4311Sfengbojiang     int flags = 0;
1443*572c4311Sfengbojiang     /* Client specific flags */
1444*572c4311Sfengbojiang     if (ctx->client) {
1445*572c4311Sfengbojiang         if (ctx->client->flags & CLIENT_LUA)
1446*572c4311Sfengbojiang          flags |= REDISMODULE_CTX_FLAGS_LUA;
1447*572c4311Sfengbojiang         if (ctx->client->flags & CLIENT_MULTI)
1448*572c4311Sfengbojiang          flags |= REDISMODULE_CTX_FLAGS_MULTI;
1449*572c4311Sfengbojiang         /* Module command recieved from MASTER, is replicated. */
1450*572c4311Sfengbojiang         if (ctx->client->flags & CLIENT_MASTER)
1451*572c4311Sfengbojiang          flags |= REDISMODULE_CTX_FLAGS_REPLICATED;
1452*572c4311Sfengbojiang     }
1453*572c4311Sfengbojiang 
1454*572c4311Sfengbojiang     if (server.cluster_enabled)
1455*572c4311Sfengbojiang         flags |= REDISMODULE_CTX_FLAGS_CLUSTER;
1456*572c4311Sfengbojiang 
1457*572c4311Sfengbojiang     /* Maxmemory and eviction policy */
1458*572c4311Sfengbojiang     if (server.maxmemory > 0) {
1459*572c4311Sfengbojiang         flags |= REDISMODULE_CTX_FLAGS_MAXMEMORY;
1460*572c4311Sfengbojiang 
1461*572c4311Sfengbojiang         if (server.maxmemory_policy != MAXMEMORY_NO_EVICTION)
1462*572c4311Sfengbojiang             flags |= REDISMODULE_CTX_FLAGS_EVICT;
1463*572c4311Sfengbojiang     }
1464*572c4311Sfengbojiang 
1465*572c4311Sfengbojiang     /* Persistence flags */
1466*572c4311Sfengbojiang     if (server.aof_state != AOF_OFF)
1467*572c4311Sfengbojiang         flags |= REDISMODULE_CTX_FLAGS_AOF;
1468*572c4311Sfengbojiang     if (server.saveparamslen > 0)
1469*572c4311Sfengbojiang         flags |= REDISMODULE_CTX_FLAGS_RDB;
1470*572c4311Sfengbojiang 
1471*572c4311Sfengbojiang     /* Replication flags */
1472*572c4311Sfengbojiang     if (server.masterhost == NULL) {
1473*572c4311Sfengbojiang         flags |= REDISMODULE_CTX_FLAGS_MASTER;
1474*572c4311Sfengbojiang     } else {
1475*572c4311Sfengbojiang         flags |= REDISMODULE_CTX_FLAGS_SLAVE;
1476*572c4311Sfengbojiang         if (server.repl_slave_ro)
1477*572c4311Sfengbojiang             flags |= REDISMODULE_CTX_FLAGS_READONLY;
1478*572c4311Sfengbojiang     }
1479*572c4311Sfengbojiang 
1480*572c4311Sfengbojiang     /* OOM flag. */
1481*572c4311Sfengbojiang     float level;
1482*572c4311Sfengbojiang     int retval = getMaxmemoryState(NULL,NULL,NULL,&level);
1483*572c4311Sfengbojiang     if (retval == C_ERR) flags |= REDISMODULE_CTX_FLAGS_OOM;
1484*572c4311Sfengbojiang     if (level > 0.75) flags |= REDISMODULE_CTX_FLAGS_OOM_WARNING;
1485*572c4311Sfengbojiang 
1486*572c4311Sfengbojiang     return flags;
1487*572c4311Sfengbojiang }
1488*572c4311Sfengbojiang 
1489*572c4311Sfengbojiang /* Change the currently selected DB. Returns an error if the id
1490*572c4311Sfengbojiang  * is out of range.
1491*572c4311Sfengbojiang  *
1492*572c4311Sfengbojiang  * Note that the client will retain the currently selected DB even after
1493*572c4311Sfengbojiang  * the Redis command implemented by the module calling this function
1494*572c4311Sfengbojiang  * returns.
1495*572c4311Sfengbojiang  *
1496*572c4311Sfengbojiang  * If the module command wishes to change something in a different DB and
1497*572c4311Sfengbojiang  * returns back to the original one, it should call RedisModule_GetSelectedDb()
1498*572c4311Sfengbojiang  * before in order to restore the old DB number before returning. */
RM_SelectDb(RedisModuleCtx * ctx,int newid)1499*572c4311Sfengbojiang int RM_SelectDb(RedisModuleCtx *ctx, int newid) {
1500*572c4311Sfengbojiang     int retval = selectDb(ctx->client,newid);
1501*572c4311Sfengbojiang     return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
1502*572c4311Sfengbojiang }
1503*572c4311Sfengbojiang 
1504*572c4311Sfengbojiang /* Return an handle representing a Redis key, so that it is possible
1505*572c4311Sfengbojiang  * to call other APIs with the key handle as argument to perform
1506*572c4311Sfengbojiang  * operations on the key.
1507*572c4311Sfengbojiang  *
1508*572c4311Sfengbojiang  * The return value is the handle representing the key, that must be
1509*572c4311Sfengbojiang  * closed with RM_CloseKey().
1510*572c4311Sfengbojiang  *
1511*572c4311Sfengbojiang  * If the key does not exist and WRITE mode is requested, the handle
1512*572c4311Sfengbojiang  * is still returned, since it is possible to perform operations on
1513*572c4311Sfengbojiang  * a yet not existing key (that will be created, for example, after
1514*572c4311Sfengbojiang  * a list push operation). If the mode is just READ instead, and the
1515*572c4311Sfengbojiang  * key does not exist, NULL is returned. However it is still safe to
1516*572c4311Sfengbojiang  * call RedisModule_CloseKey() and RedisModule_KeyType() on a NULL
1517*572c4311Sfengbojiang  * value. */
RM_OpenKey(RedisModuleCtx * ctx,robj * keyname,int mode)1518*572c4311Sfengbojiang void *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
1519*572c4311Sfengbojiang     RedisModuleKey *kp;
1520*572c4311Sfengbojiang     robj *value;
1521*572c4311Sfengbojiang 
1522*572c4311Sfengbojiang     if (mode & REDISMODULE_WRITE) {
1523*572c4311Sfengbojiang         value = lookupKeyWrite(ctx->client->db,keyname);
1524*572c4311Sfengbojiang     } else {
1525*572c4311Sfengbojiang         value = lookupKeyRead(ctx->client->db,keyname);
1526*572c4311Sfengbojiang         if (value == NULL) {
1527*572c4311Sfengbojiang             return NULL;
1528*572c4311Sfengbojiang         }
1529*572c4311Sfengbojiang     }
1530*572c4311Sfengbojiang 
1531*572c4311Sfengbojiang     /* Setup the key handle. */
1532*572c4311Sfengbojiang     kp = zmalloc(sizeof(*kp));
1533*572c4311Sfengbojiang     kp->ctx = ctx;
1534*572c4311Sfengbojiang     kp->db = ctx->client->db;
1535*572c4311Sfengbojiang     kp->key = keyname;
1536*572c4311Sfengbojiang     incrRefCount(keyname);
1537*572c4311Sfengbojiang     kp->value = value;
1538*572c4311Sfengbojiang     kp->iter = NULL;
1539*572c4311Sfengbojiang     kp->mode = mode;
1540*572c4311Sfengbojiang     zsetKeyReset(kp);
1541*572c4311Sfengbojiang     autoMemoryAdd(ctx,REDISMODULE_AM_KEY,kp);
1542*572c4311Sfengbojiang     return (void*)kp;
1543*572c4311Sfengbojiang }
1544*572c4311Sfengbojiang 
1545*572c4311Sfengbojiang /* Close a key handle. */
RM_CloseKey(RedisModuleKey * key)1546*572c4311Sfengbojiang void RM_CloseKey(RedisModuleKey *key) {
1547*572c4311Sfengbojiang     if (key == NULL) return;
1548*572c4311Sfengbojiang     if (key->mode & REDISMODULE_WRITE) signalModifiedKey(key->db,key->key);
1549*572c4311Sfengbojiang     /* TODO: if (key->iter) RM_KeyIteratorStop(kp); */
1550*572c4311Sfengbojiang     RM_ZsetRangeStop(key);
1551*572c4311Sfengbojiang     decrRefCount(key->key);
1552*572c4311Sfengbojiang     autoMemoryFreed(key->ctx,REDISMODULE_AM_KEY,key);
1553*572c4311Sfengbojiang     zfree(key);
1554*572c4311Sfengbojiang }
1555*572c4311Sfengbojiang 
1556*572c4311Sfengbojiang /* Return the type of the key. If the key pointer is NULL then
1557*572c4311Sfengbojiang  * REDISMODULE_KEYTYPE_EMPTY is returned. */
RM_KeyType(RedisModuleKey * key)1558*572c4311Sfengbojiang int RM_KeyType(RedisModuleKey *key) {
1559*572c4311Sfengbojiang     if (key == NULL || key->value ==  NULL) return REDISMODULE_KEYTYPE_EMPTY;
1560*572c4311Sfengbojiang     /* We map between defines so that we are free to change the internal
1561*572c4311Sfengbojiang      * defines as desired. */
1562*572c4311Sfengbojiang     switch(key->value->type) {
1563*572c4311Sfengbojiang     case OBJ_STRING: return REDISMODULE_KEYTYPE_STRING;
1564*572c4311Sfengbojiang     case OBJ_LIST: return REDISMODULE_KEYTYPE_LIST;
1565*572c4311Sfengbojiang     case OBJ_SET: return REDISMODULE_KEYTYPE_SET;
1566*572c4311Sfengbojiang     case OBJ_ZSET: return REDISMODULE_KEYTYPE_ZSET;
1567*572c4311Sfengbojiang     case OBJ_HASH: return REDISMODULE_KEYTYPE_HASH;
1568*572c4311Sfengbojiang     case OBJ_MODULE: return REDISMODULE_KEYTYPE_MODULE;
1569*572c4311Sfengbojiang     default: return 0;
1570*572c4311Sfengbojiang     }
1571*572c4311Sfengbojiang }
1572*572c4311Sfengbojiang 
1573*572c4311Sfengbojiang /* Return the length of the value associated with the key.
1574*572c4311Sfengbojiang  * For strings this is the length of the string. For all the other types
1575*572c4311Sfengbojiang  * is the number of elements (just counting keys for hashes).
1576*572c4311Sfengbojiang  *
1577*572c4311Sfengbojiang  * If the key pointer is NULL or the key is empty, zero is returned. */
RM_ValueLength(RedisModuleKey * key)1578*572c4311Sfengbojiang size_t RM_ValueLength(RedisModuleKey *key) {
1579*572c4311Sfengbojiang     if (key == NULL || key->value == NULL) return 0;
1580*572c4311Sfengbojiang     switch(key->value->type) {
1581*572c4311Sfengbojiang     case OBJ_STRING: return stringObjectLen(key->value);
1582*572c4311Sfengbojiang     case OBJ_LIST: return listTypeLength(key->value);
1583*572c4311Sfengbojiang     case OBJ_SET: return setTypeSize(key->value);
1584*572c4311Sfengbojiang     case OBJ_ZSET: return zsetLength(key->value);
1585*572c4311Sfengbojiang     case OBJ_HASH: return hashTypeLength(key->value);
1586*572c4311Sfengbojiang     default: return 0;
1587*572c4311Sfengbojiang     }
1588*572c4311Sfengbojiang }
1589*572c4311Sfengbojiang 
1590*572c4311Sfengbojiang /* If the key is open for writing, remove it, and setup the key to
1591*572c4311Sfengbojiang  * accept new writes as an empty key (that will be created on demand).
1592*572c4311Sfengbojiang  * On success REDISMODULE_OK is returned. If the key is not open for
1593*572c4311Sfengbojiang  * writing REDISMODULE_ERR is returned. */
RM_DeleteKey(RedisModuleKey * key)1594*572c4311Sfengbojiang int RM_DeleteKey(RedisModuleKey *key) {
1595*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
1596*572c4311Sfengbojiang     if (key->value) {
1597*572c4311Sfengbojiang         dbDelete(key->db,key->key);
1598*572c4311Sfengbojiang         key->value = NULL;
1599*572c4311Sfengbojiang     }
1600*572c4311Sfengbojiang     return REDISMODULE_OK;
1601*572c4311Sfengbojiang }
1602*572c4311Sfengbojiang 
1603*572c4311Sfengbojiang /* If the key is open for writing, unlink it (that is delete it in a
1604*572c4311Sfengbojiang  * non-blocking way, not reclaiming memory immediately) and setup the key to
1605*572c4311Sfengbojiang  * accept new writes as an empty key (that will be created on demand).
1606*572c4311Sfengbojiang  * On success REDISMODULE_OK is returned. If the key is not open for
1607*572c4311Sfengbojiang  * writing REDISMODULE_ERR is returned. */
RM_UnlinkKey(RedisModuleKey * key)1608*572c4311Sfengbojiang int RM_UnlinkKey(RedisModuleKey *key) {
1609*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
1610*572c4311Sfengbojiang     if (key->value) {
1611*572c4311Sfengbojiang         dbAsyncDelete(key->db,key->key);
1612*572c4311Sfengbojiang         key->value = NULL;
1613*572c4311Sfengbojiang     }
1614*572c4311Sfengbojiang     return REDISMODULE_OK;
1615*572c4311Sfengbojiang }
1616*572c4311Sfengbojiang 
1617*572c4311Sfengbojiang /* Return the key expire value, as milliseconds of remaining TTL.
1618*572c4311Sfengbojiang  * If no TTL is associated with the key or if the key is empty,
1619*572c4311Sfengbojiang  * REDISMODULE_NO_EXPIRE is returned. */
RM_GetExpire(RedisModuleKey * key)1620*572c4311Sfengbojiang mstime_t RM_GetExpire(RedisModuleKey *key) {
1621*572c4311Sfengbojiang     mstime_t expire = getExpire(key->db,key->key);
1622*572c4311Sfengbojiang     if (expire == -1 || key->value == NULL) return -1;
1623*572c4311Sfengbojiang     expire -= mstime();
1624*572c4311Sfengbojiang     return expire >= 0 ? expire : 0;
1625*572c4311Sfengbojiang }
1626*572c4311Sfengbojiang 
1627*572c4311Sfengbojiang /* Set a new expire for the key. If the special expire
1628*572c4311Sfengbojiang  * REDISMODULE_NO_EXPIRE is set, the expire is cancelled if there was
1629*572c4311Sfengbojiang  * one (the same as the PERSIST command).
1630*572c4311Sfengbojiang  *
1631*572c4311Sfengbojiang  * Note that the expire must be provided as a positive integer representing
1632*572c4311Sfengbojiang  * the number of milliseconds of TTL the key should have.
1633*572c4311Sfengbojiang  *
1634*572c4311Sfengbojiang  * The function returns REDISMODULE_OK on success or REDISMODULE_ERR if
1635*572c4311Sfengbojiang  * the key was not open for writing or is an empty key. */
RM_SetExpire(RedisModuleKey * key,mstime_t expire)1636*572c4311Sfengbojiang int RM_SetExpire(RedisModuleKey *key, mstime_t expire) {
1637*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE) || key->value == NULL)
1638*572c4311Sfengbojiang         return REDISMODULE_ERR;
1639*572c4311Sfengbojiang     if (expire != REDISMODULE_NO_EXPIRE) {
1640*572c4311Sfengbojiang         expire += mstime();
1641*572c4311Sfengbojiang         setExpire(key->ctx->client,key->db,key->key,expire);
1642*572c4311Sfengbojiang     } else {
1643*572c4311Sfengbojiang         removeExpire(key->db,key->key);
1644*572c4311Sfengbojiang     }
1645*572c4311Sfengbojiang     return REDISMODULE_OK;
1646*572c4311Sfengbojiang }
1647*572c4311Sfengbojiang 
1648*572c4311Sfengbojiang /* --------------------------------------------------------------------------
1649*572c4311Sfengbojiang  * Key API for String type
1650*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
1651*572c4311Sfengbojiang 
1652*572c4311Sfengbojiang /* If the key is open for writing, set the specified string 'str' as the
1653*572c4311Sfengbojiang  * value of the key, deleting the old value if any.
1654*572c4311Sfengbojiang  * On success REDISMODULE_OK is returned. If the key is not open for
1655*572c4311Sfengbojiang  * writing or there is an active iterator, REDISMODULE_ERR is returned. */
RM_StringSet(RedisModuleKey * key,RedisModuleString * str)1656*572c4311Sfengbojiang int RM_StringSet(RedisModuleKey *key, RedisModuleString *str) {
1657*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE) || key->iter) return REDISMODULE_ERR;
1658*572c4311Sfengbojiang     RM_DeleteKey(key);
1659*572c4311Sfengbojiang     setKey(key->db,key->key,str);
1660*572c4311Sfengbojiang     key->value = str;
1661*572c4311Sfengbojiang     return REDISMODULE_OK;
1662*572c4311Sfengbojiang }
1663*572c4311Sfengbojiang 
1664*572c4311Sfengbojiang /* Prepare the key associated string value for DMA access, and returns
1665*572c4311Sfengbojiang  * a pointer and size (by reference), that the user can use to read or
1666*572c4311Sfengbojiang  * modify the string in-place accessing it directly via pointer.
1667*572c4311Sfengbojiang  *
1668*572c4311Sfengbojiang  * The 'mode' is composed by bitwise OR-ing the following flags:
1669*572c4311Sfengbojiang  *
1670*572c4311Sfengbojiang  *     REDISMODULE_READ -- Read access
1671*572c4311Sfengbojiang  *     REDISMODULE_WRITE -- Write access
1672*572c4311Sfengbojiang  *
1673*572c4311Sfengbojiang  * If the DMA is not requested for writing, the pointer returned should
1674*572c4311Sfengbojiang  * only be accessed in a read-only fashion.
1675*572c4311Sfengbojiang  *
1676*572c4311Sfengbojiang  * On error (wrong type) NULL is returned.
1677*572c4311Sfengbojiang  *
1678*572c4311Sfengbojiang  * DMA access rules:
1679*572c4311Sfengbojiang  *
1680*572c4311Sfengbojiang  * 1. No other key writing function should be called since the moment
1681*572c4311Sfengbojiang  * the pointer is obtained, for all the time we want to use DMA access
1682*572c4311Sfengbojiang  * to read or modify the string.
1683*572c4311Sfengbojiang  *
1684*572c4311Sfengbojiang  * 2. Each time RM_StringTruncate() is called, to continue with the DMA
1685*572c4311Sfengbojiang  * access, RM_StringDMA() should be called again to re-obtain
1686*572c4311Sfengbojiang  * a new pointer and length.
1687*572c4311Sfengbojiang  *
1688*572c4311Sfengbojiang  * 3. If the returned pointer is not NULL, but the length is zero, no
1689*572c4311Sfengbojiang  * byte can be touched (the string is empty, or the key itself is empty)
1690*572c4311Sfengbojiang  * so a RM_StringTruncate() call should be used if there is to enlarge
1691*572c4311Sfengbojiang  * the string, and later call StringDMA() again to get the pointer.
1692*572c4311Sfengbojiang  */
RM_StringDMA(RedisModuleKey * key,size_t * len,int mode)1693*572c4311Sfengbojiang char *RM_StringDMA(RedisModuleKey *key, size_t *len, int mode) {
1694*572c4311Sfengbojiang     /* We need to return *some* pointer for empty keys, we just return
1695*572c4311Sfengbojiang      * a string literal pointer, that is the advantage to be mapped into
1696*572c4311Sfengbojiang      * a read only memory page, so the module will segfault if a write
1697*572c4311Sfengbojiang      * attempt is performed. */
1698*572c4311Sfengbojiang     char *emptystring = "<dma-empty-string>";
1699*572c4311Sfengbojiang     if (key->value == NULL) {
1700*572c4311Sfengbojiang         *len = 0;
1701*572c4311Sfengbojiang         return emptystring;
1702*572c4311Sfengbojiang     }
1703*572c4311Sfengbojiang 
1704*572c4311Sfengbojiang     if (key->value->type != OBJ_STRING) return NULL;
1705*572c4311Sfengbojiang 
1706*572c4311Sfengbojiang     /* For write access, and even for read access if the object is encoded,
1707*572c4311Sfengbojiang      * we unshare the string (that has the side effect of decoding it). */
1708*572c4311Sfengbojiang     if ((mode & REDISMODULE_WRITE) || key->value->encoding != OBJ_ENCODING_RAW)
1709*572c4311Sfengbojiang         key->value = dbUnshareStringValue(key->db, key->key, key->value);
1710*572c4311Sfengbojiang 
1711*572c4311Sfengbojiang     *len = sdslen(key->value->ptr);
1712*572c4311Sfengbojiang     return key->value->ptr;
1713*572c4311Sfengbojiang }
1714*572c4311Sfengbojiang 
1715*572c4311Sfengbojiang /* If the string is open for writing and is of string type, resize it, padding
1716*572c4311Sfengbojiang  * with zero bytes if the new length is greater than the old one.
1717*572c4311Sfengbojiang  *
1718*572c4311Sfengbojiang  * After this call, RM_StringDMA() must be called again to continue
1719*572c4311Sfengbojiang  * DMA access with the new pointer.
1720*572c4311Sfengbojiang  *
1721*572c4311Sfengbojiang  * The function returns REDISMODULE_OK on success, and REDISMODULE_ERR on
1722*572c4311Sfengbojiang  * error, that is, the key is not open for writing, is not a string
1723*572c4311Sfengbojiang  * or resizing for more than 512 MB is requested.
1724*572c4311Sfengbojiang  *
1725*572c4311Sfengbojiang  * If the key is empty, a string key is created with the new string value
1726*572c4311Sfengbojiang  * unless the new length value requested is zero. */
RM_StringTruncate(RedisModuleKey * key,size_t newlen)1727*572c4311Sfengbojiang int RM_StringTruncate(RedisModuleKey *key, size_t newlen) {
1728*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
1729*572c4311Sfengbojiang     if (key->value && key->value->type != OBJ_STRING) return REDISMODULE_ERR;
1730*572c4311Sfengbojiang     if (newlen > 512*1024*1024) return REDISMODULE_ERR;
1731*572c4311Sfengbojiang 
1732*572c4311Sfengbojiang     /* Empty key and new len set to 0. Just return REDISMODULE_OK without
1733*572c4311Sfengbojiang      * doing anything. */
1734*572c4311Sfengbojiang     if (key->value == NULL && newlen == 0) return REDISMODULE_OK;
1735*572c4311Sfengbojiang 
1736*572c4311Sfengbojiang     if (key->value == NULL) {
1737*572c4311Sfengbojiang         /* Empty key: create it with the new size. */
1738*572c4311Sfengbojiang         robj *o = createObject(OBJ_STRING,sdsnewlen(NULL, newlen));
1739*572c4311Sfengbojiang         setKey(key->db,key->key,o);
1740*572c4311Sfengbojiang         key->value = o;
1741*572c4311Sfengbojiang         decrRefCount(o);
1742*572c4311Sfengbojiang     } else {
1743*572c4311Sfengbojiang         /* Unshare and resize. */
1744*572c4311Sfengbojiang         key->value = dbUnshareStringValue(key->db, key->key, key->value);
1745*572c4311Sfengbojiang         size_t curlen = sdslen(key->value->ptr);
1746*572c4311Sfengbojiang         if (newlen > curlen) {
1747*572c4311Sfengbojiang             key->value->ptr = sdsgrowzero(key->value->ptr,newlen);
1748*572c4311Sfengbojiang         } else if (newlen < curlen) {
1749*572c4311Sfengbojiang             sdsrange(key->value->ptr,0,newlen-1);
1750*572c4311Sfengbojiang             /* If the string is too wasteful, reallocate it. */
1751*572c4311Sfengbojiang             if (sdslen(key->value->ptr) < sdsavail(key->value->ptr))
1752*572c4311Sfengbojiang                 key->value->ptr = sdsRemoveFreeSpace(key->value->ptr);
1753*572c4311Sfengbojiang         }
1754*572c4311Sfengbojiang     }
1755*572c4311Sfengbojiang     return REDISMODULE_OK;
1756*572c4311Sfengbojiang }
1757*572c4311Sfengbojiang 
1758*572c4311Sfengbojiang /* --------------------------------------------------------------------------
1759*572c4311Sfengbojiang  * Key API for List type
1760*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
1761*572c4311Sfengbojiang 
1762*572c4311Sfengbojiang /* Push an element into a list, on head or tail depending on 'where' argument.
1763*572c4311Sfengbojiang  * If the key pointer is about an empty key opened for writing, the key
1764*572c4311Sfengbojiang  * is created. On error (key opened for read-only operations or of the wrong
1765*572c4311Sfengbojiang  * type) REDISMODULE_ERR is returned, otherwise REDISMODULE_OK is returned. */
RM_ListPush(RedisModuleKey * key,int where,RedisModuleString * ele)1766*572c4311Sfengbojiang int RM_ListPush(RedisModuleKey *key, int where, RedisModuleString *ele) {
1767*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
1768*572c4311Sfengbojiang     if (key->value && key->value->type != OBJ_LIST) return REDISMODULE_ERR;
1769*572c4311Sfengbojiang     if (key->value == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_LIST);
1770*572c4311Sfengbojiang     listTypePush(key->value, ele,
1771*572c4311Sfengbojiang         (where == REDISMODULE_LIST_HEAD) ? QUICKLIST_HEAD : QUICKLIST_TAIL);
1772*572c4311Sfengbojiang     return REDISMODULE_OK;
1773*572c4311Sfengbojiang }
1774*572c4311Sfengbojiang 
1775*572c4311Sfengbojiang /* Pop an element from the list, and returns it as a module string object
1776*572c4311Sfengbojiang  * that the user should be free with RM_FreeString() or by enabling
1777*572c4311Sfengbojiang  * automatic memory. 'where' specifies if the element should be popped from
1778*572c4311Sfengbojiang  * head or tail. The command returns NULL if:
1779*572c4311Sfengbojiang  * 1) The list is empty.
1780*572c4311Sfengbojiang  * 2) The key was not open for writing.
1781*572c4311Sfengbojiang  * 3) The key is not a list. */
RM_ListPop(RedisModuleKey * key,int where)1782*572c4311Sfengbojiang RedisModuleString *RM_ListPop(RedisModuleKey *key, int where) {
1783*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE) ||
1784*572c4311Sfengbojiang         key->value == NULL ||
1785*572c4311Sfengbojiang         key->value->type != OBJ_LIST) return NULL;
1786*572c4311Sfengbojiang     robj *ele = listTypePop(key->value,
1787*572c4311Sfengbojiang         (where == REDISMODULE_LIST_HEAD) ? QUICKLIST_HEAD : QUICKLIST_TAIL);
1788*572c4311Sfengbojiang     robj *decoded = getDecodedObject(ele);
1789*572c4311Sfengbojiang     decrRefCount(ele);
1790*572c4311Sfengbojiang     moduleDelKeyIfEmpty(key);
1791*572c4311Sfengbojiang     autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,decoded);
1792*572c4311Sfengbojiang     return decoded;
1793*572c4311Sfengbojiang }
1794*572c4311Sfengbojiang 
1795*572c4311Sfengbojiang /* --------------------------------------------------------------------------
1796*572c4311Sfengbojiang  * Key API for Sorted Set type
1797*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
1798*572c4311Sfengbojiang 
1799*572c4311Sfengbojiang /* Conversion from/to public flags of the Modules API and our private flags,
1800*572c4311Sfengbojiang  * so that we have everything decoupled. */
RM_ZsetAddFlagsToCoreFlags(int flags)1801*572c4311Sfengbojiang int RM_ZsetAddFlagsToCoreFlags(int flags) {
1802*572c4311Sfengbojiang     int retflags = 0;
1803*572c4311Sfengbojiang     if (flags & REDISMODULE_ZADD_XX) retflags |= ZADD_XX;
1804*572c4311Sfengbojiang     if (flags & REDISMODULE_ZADD_NX) retflags |= ZADD_NX;
1805*572c4311Sfengbojiang     return retflags;
1806*572c4311Sfengbojiang }
1807*572c4311Sfengbojiang 
1808*572c4311Sfengbojiang /* See previous function comment. */
RM_ZsetAddFlagsFromCoreFlags(int flags)1809*572c4311Sfengbojiang int RM_ZsetAddFlagsFromCoreFlags(int flags) {
1810*572c4311Sfengbojiang     int retflags = 0;
1811*572c4311Sfengbojiang     if (flags & ZADD_ADDED) retflags |= REDISMODULE_ZADD_ADDED;
1812*572c4311Sfengbojiang     if (flags & ZADD_UPDATED) retflags |= REDISMODULE_ZADD_UPDATED;
1813*572c4311Sfengbojiang     if (flags & ZADD_NOP) retflags |= REDISMODULE_ZADD_NOP;
1814*572c4311Sfengbojiang     return retflags;
1815*572c4311Sfengbojiang }
1816*572c4311Sfengbojiang 
1817*572c4311Sfengbojiang /* Add a new element into a sorted set, with the specified 'score'.
1818*572c4311Sfengbojiang  * If the element already exists, the score is updated.
1819*572c4311Sfengbojiang  *
1820*572c4311Sfengbojiang  * A new sorted set is created at value if the key is an empty open key
1821*572c4311Sfengbojiang  * setup for writing.
1822*572c4311Sfengbojiang  *
1823*572c4311Sfengbojiang  * Additional flags can be passed to the function via a pointer, the flags
1824*572c4311Sfengbojiang  * are both used to receive input and to communicate state when the function
1825*572c4311Sfengbojiang  * returns. 'flagsptr' can be NULL if no special flags are used.
1826*572c4311Sfengbojiang  *
1827*572c4311Sfengbojiang  * The input flags are:
1828*572c4311Sfengbojiang  *
1829*572c4311Sfengbojiang  *     REDISMODULE_ZADD_XX: Element must already exist. Do nothing otherwise.
1830*572c4311Sfengbojiang  *     REDISMODULE_ZADD_NX: Element must not exist. Do nothing otherwise.
1831*572c4311Sfengbojiang  *
1832*572c4311Sfengbojiang  * The output flags are:
1833*572c4311Sfengbojiang  *
1834*572c4311Sfengbojiang  *     REDISMODULE_ZADD_ADDED: The new element was added to the sorted set.
1835*572c4311Sfengbojiang  *     REDISMODULE_ZADD_UPDATED: The score of the element was updated.
1836*572c4311Sfengbojiang  *     REDISMODULE_ZADD_NOP: No operation was performed because XX or NX flags.
1837*572c4311Sfengbojiang  *
1838*572c4311Sfengbojiang  * On success the function returns REDISMODULE_OK. On the following errors
1839*572c4311Sfengbojiang  * REDISMODULE_ERR is returned:
1840*572c4311Sfengbojiang  *
1841*572c4311Sfengbojiang  * * The key was not opened for writing.
1842*572c4311Sfengbojiang  * * The key is of the wrong type.
1843*572c4311Sfengbojiang  * * 'score' double value is not a number (NaN).
1844*572c4311Sfengbojiang  */
RM_ZsetAdd(RedisModuleKey * key,double score,RedisModuleString * ele,int * flagsptr)1845*572c4311Sfengbojiang int RM_ZsetAdd(RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr) {
1846*572c4311Sfengbojiang     int flags = 0;
1847*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
1848*572c4311Sfengbojiang     if (key->value && key->value->type != OBJ_ZSET) return REDISMODULE_ERR;
1849*572c4311Sfengbojiang     if (key->value == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_ZSET);
1850*572c4311Sfengbojiang     if (flagsptr) flags = RM_ZsetAddFlagsToCoreFlags(*flagsptr);
1851*572c4311Sfengbojiang     if (zsetAdd(key->value,score,ele->ptr,&flags,NULL) == 0) {
1852*572c4311Sfengbojiang         if (flagsptr) *flagsptr = 0;
1853*572c4311Sfengbojiang         return REDISMODULE_ERR;
1854*572c4311Sfengbojiang     }
1855*572c4311Sfengbojiang     if (flagsptr) *flagsptr = RM_ZsetAddFlagsFromCoreFlags(flags);
1856*572c4311Sfengbojiang     return REDISMODULE_OK;
1857*572c4311Sfengbojiang }
1858*572c4311Sfengbojiang 
1859*572c4311Sfengbojiang /* This function works exactly like RM_ZsetAdd(), but instead of setting
1860*572c4311Sfengbojiang  * a new score, the score of the existing element is incremented, or if the
1861*572c4311Sfengbojiang  * element does not already exist, it is added assuming the old score was
1862*572c4311Sfengbojiang  * zero.
1863*572c4311Sfengbojiang  *
1864*572c4311Sfengbojiang  * The input and output flags, and the return value, have the same exact
1865*572c4311Sfengbojiang  * meaning, with the only difference that this function will return
1866*572c4311Sfengbojiang  * REDISMODULE_ERR even when 'score' is a valid double number, but adding it
1867*572c4311Sfengbojiang  * to the existing score results into a NaN (not a number) condition.
1868*572c4311Sfengbojiang  *
1869*572c4311Sfengbojiang  * This function has an additional field 'newscore', if not NULL is filled
1870*572c4311Sfengbojiang  * with the new score of the element after the increment, if no error
1871*572c4311Sfengbojiang  * is returned. */
RM_ZsetIncrby(RedisModuleKey * key,double score,RedisModuleString * ele,int * flagsptr,double * newscore)1872*572c4311Sfengbojiang int RM_ZsetIncrby(RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr, double *newscore) {
1873*572c4311Sfengbojiang     int flags = 0;
1874*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
1875*572c4311Sfengbojiang     if (key->value && key->value->type != OBJ_ZSET) return REDISMODULE_ERR;
1876*572c4311Sfengbojiang     if (key->value == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_ZSET);
1877*572c4311Sfengbojiang     if (flagsptr) flags = RM_ZsetAddFlagsToCoreFlags(*flagsptr);
1878*572c4311Sfengbojiang     flags |= ZADD_INCR;
1879*572c4311Sfengbojiang     if (zsetAdd(key->value,score,ele->ptr,&flags,newscore) == 0) {
1880*572c4311Sfengbojiang         if (flagsptr) *flagsptr = 0;
1881*572c4311Sfengbojiang         return REDISMODULE_ERR;
1882*572c4311Sfengbojiang     }
1883*572c4311Sfengbojiang     /* zsetAdd() may signal back that the resulting score is not a number. */
1884*572c4311Sfengbojiang     if (flagsptr && (*flagsptr & ZADD_NAN)) {
1885*572c4311Sfengbojiang         *flagsptr = 0;
1886*572c4311Sfengbojiang         return REDISMODULE_ERR;
1887*572c4311Sfengbojiang     }
1888*572c4311Sfengbojiang     if (flagsptr) *flagsptr = RM_ZsetAddFlagsFromCoreFlags(flags);
1889*572c4311Sfengbojiang     return REDISMODULE_OK;
1890*572c4311Sfengbojiang }
1891*572c4311Sfengbojiang 
1892*572c4311Sfengbojiang /* Remove the specified element from the sorted set.
1893*572c4311Sfengbojiang  * The function returns REDISMODULE_OK on success, and REDISMODULE_ERR
1894*572c4311Sfengbojiang  * on one of the following conditions:
1895*572c4311Sfengbojiang  *
1896*572c4311Sfengbojiang  * * The key was not opened for writing.
1897*572c4311Sfengbojiang  * * The key is of the wrong type.
1898*572c4311Sfengbojiang  *
1899*572c4311Sfengbojiang  * The return value does NOT indicate the fact the element was really
1900*572c4311Sfengbojiang  * removed (since it existed) or not, just if the function was executed
1901*572c4311Sfengbojiang  * with success.
1902*572c4311Sfengbojiang  *
1903*572c4311Sfengbojiang  * In order to know if the element was removed, the additional argument
1904*572c4311Sfengbojiang  * 'deleted' must be passed, that populates the integer by reference
1905*572c4311Sfengbojiang  * setting it to 1 or 0 depending on the outcome of the operation.
1906*572c4311Sfengbojiang  * The 'deleted' argument can be NULL if the caller is not interested
1907*572c4311Sfengbojiang  * to know if the element was really removed.
1908*572c4311Sfengbojiang  *
1909*572c4311Sfengbojiang  * Empty keys will be handled correctly by doing nothing. */
RM_ZsetRem(RedisModuleKey * key,RedisModuleString * ele,int * deleted)1910*572c4311Sfengbojiang int RM_ZsetRem(RedisModuleKey *key, RedisModuleString *ele, int *deleted) {
1911*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
1912*572c4311Sfengbojiang     if (key->value && key->value->type != OBJ_ZSET) return REDISMODULE_ERR;
1913*572c4311Sfengbojiang     if (key->value != NULL && zsetDel(key->value,ele->ptr)) {
1914*572c4311Sfengbojiang         if (deleted) *deleted = 1;
1915*572c4311Sfengbojiang     } else {
1916*572c4311Sfengbojiang         if (deleted) *deleted = 0;
1917*572c4311Sfengbojiang     }
1918*572c4311Sfengbojiang     return REDISMODULE_OK;
1919*572c4311Sfengbojiang }
1920*572c4311Sfengbojiang 
1921*572c4311Sfengbojiang /* On success retrieve the double score associated at the sorted set element
1922*572c4311Sfengbojiang  * 'ele' and returns REDISMODULE_OK. Otherwise REDISMODULE_ERR is returned
1923*572c4311Sfengbojiang  * to signal one of the following conditions:
1924*572c4311Sfengbojiang  *
1925*572c4311Sfengbojiang  * * There is no such element 'ele' in the sorted set.
1926*572c4311Sfengbojiang  * * The key is not a sorted set.
1927*572c4311Sfengbojiang  * * The key is an open empty key.
1928*572c4311Sfengbojiang  */
RM_ZsetScore(RedisModuleKey * key,RedisModuleString * ele,double * score)1929*572c4311Sfengbojiang int RM_ZsetScore(RedisModuleKey *key, RedisModuleString *ele, double *score) {
1930*572c4311Sfengbojiang     if (key->value == NULL) return REDISMODULE_ERR;
1931*572c4311Sfengbojiang     if (key->value->type != OBJ_ZSET) return REDISMODULE_ERR;
1932*572c4311Sfengbojiang     if (zsetScore(key->value,ele->ptr,score) == C_ERR) return REDISMODULE_ERR;
1933*572c4311Sfengbojiang     return REDISMODULE_OK;
1934*572c4311Sfengbojiang }
1935*572c4311Sfengbojiang 
1936*572c4311Sfengbojiang /* --------------------------------------------------------------------------
1937*572c4311Sfengbojiang  * Key API for Sorted Set iterator
1938*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
1939*572c4311Sfengbojiang 
zsetKeyReset(RedisModuleKey * key)1940*572c4311Sfengbojiang void zsetKeyReset(RedisModuleKey *key) {
1941*572c4311Sfengbojiang     key->ztype = REDISMODULE_ZSET_RANGE_NONE;
1942*572c4311Sfengbojiang     key->zcurrent = NULL;
1943*572c4311Sfengbojiang     key->zer = 1;
1944*572c4311Sfengbojiang }
1945*572c4311Sfengbojiang 
1946*572c4311Sfengbojiang /* Stop a sorted set iteration. */
RM_ZsetRangeStop(RedisModuleKey * key)1947*572c4311Sfengbojiang void RM_ZsetRangeStop(RedisModuleKey *key) {
1948*572c4311Sfengbojiang     /* Free resources if needed. */
1949*572c4311Sfengbojiang     if (key->ztype == REDISMODULE_ZSET_RANGE_LEX)
1950*572c4311Sfengbojiang         zslFreeLexRange(&key->zlrs);
1951*572c4311Sfengbojiang     /* Setup sensible values so that misused iteration API calls when an
1952*572c4311Sfengbojiang      * iterator is not active will result into something more sensible
1953*572c4311Sfengbojiang      * than crashing. */
1954*572c4311Sfengbojiang     zsetKeyReset(key);
1955*572c4311Sfengbojiang }
1956*572c4311Sfengbojiang 
1957*572c4311Sfengbojiang /* Return the "End of range" flag value to signal the end of the iteration. */
RM_ZsetRangeEndReached(RedisModuleKey * key)1958*572c4311Sfengbojiang int RM_ZsetRangeEndReached(RedisModuleKey *key) {
1959*572c4311Sfengbojiang     return key->zer;
1960*572c4311Sfengbojiang }
1961*572c4311Sfengbojiang 
1962*572c4311Sfengbojiang /* Helper function for RM_ZsetFirstInScoreRange() and RM_ZsetLastInScoreRange().
1963*572c4311Sfengbojiang  * Setup the sorted set iteration according to the specified score range
1964*572c4311Sfengbojiang  * (see the functions calling it for more info). If 'first' is true the
1965*572c4311Sfengbojiang  * first element in the range is used as a starting point for the iterator
1966*572c4311Sfengbojiang  * otherwise the last. Return REDISMODULE_OK on success otherwise
1967*572c4311Sfengbojiang  * REDISMODULE_ERR. */
zsetInitScoreRange(RedisModuleKey * key,double min,double max,int minex,int maxex,int first)1968*572c4311Sfengbojiang int zsetInitScoreRange(RedisModuleKey *key, double min, double max, int minex, int maxex, int first) {
1969*572c4311Sfengbojiang     if (!key->value || key->value->type != OBJ_ZSET) return REDISMODULE_ERR;
1970*572c4311Sfengbojiang 
1971*572c4311Sfengbojiang     RM_ZsetRangeStop(key);
1972*572c4311Sfengbojiang     key->ztype = REDISMODULE_ZSET_RANGE_SCORE;
1973*572c4311Sfengbojiang     key->zer = 0;
1974*572c4311Sfengbojiang 
1975*572c4311Sfengbojiang     /* Setup the range structure used by the sorted set core implementation
1976*572c4311Sfengbojiang      * in order to seek at the specified element. */
1977*572c4311Sfengbojiang     zrangespec *zrs = &key->zrs;
1978*572c4311Sfengbojiang     zrs->min = min;
1979*572c4311Sfengbojiang     zrs->max = max;
1980*572c4311Sfengbojiang     zrs->minex = minex;
1981*572c4311Sfengbojiang     zrs->maxex = maxex;
1982*572c4311Sfengbojiang 
1983*572c4311Sfengbojiang     if (key->value->encoding == OBJ_ENCODING_ZIPLIST) {
1984*572c4311Sfengbojiang         key->zcurrent = first ? zzlFirstInRange(key->value->ptr,zrs) :
1985*572c4311Sfengbojiang                                 zzlLastInRange(key->value->ptr,zrs);
1986*572c4311Sfengbojiang     } else if (key->value->encoding == OBJ_ENCODING_SKIPLIST) {
1987*572c4311Sfengbojiang         zset *zs = key->value->ptr;
1988*572c4311Sfengbojiang         zskiplist *zsl = zs->zsl;
1989*572c4311Sfengbojiang         key->zcurrent = first ? zslFirstInRange(zsl,zrs) :
1990*572c4311Sfengbojiang                                 zslLastInRange(zsl,zrs);
1991*572c4311Sfengbojiang     } else {
1992*572c4311Sfengbojiang         serverPanic("Unsupported zset encoding");
1993*572c4311Sfengbojiang     }
1994*572c4311Sfengbojiang     if (key->zcurrent == NULL) key->zer = 1;
1995*572c4311Sfengbojiang     return REDISMODULE_OK;
1996*572c4311Sfengbojiang }
1997*572c4311Sfengbojiang 
1998*572c4311Sfengbojiang /* Setup a sorted set iterator seeking the first element in the specified
1999*572c4311Sfengbojiang  * range. Returns REDISMODULE_OK if the iterator was correctly initialized
2000*572c4311Sfengbojiang  * otherwise REDISMODULE_ERR is returned in the following conditions:
2001*572c4311Sfengbojiang  *
2002*572c4311Sfengbojiang  * 1. The value stored at key is not a sorted set or the key is empty.
2003*572c4311Sfengbojiang  *
2004*572c4311Sfengbojiang  * The range is specified according to the two double values 'min' and 'max'.
2005*572c4311Sfengbojiang  * Both can be infinite using the following two macros:
2006*572c4311Sfengbojiang  *
2007*572c4311Sfengbojiang  * REDISMODULE_POSITIVE_INFINITE for positive infinite value
2008*572c4311Sfengbojiang  * REDISMODULE_NEGATIVE_INFINITE for negative infinite value
2009*572c4311Sfengbojiang  *
2010*572c4311Sfengbojiang  * 'minex' and 'maxex' parameters, if true, respectively setup a range
2011*572c4311Sfengbojiang  * where the min and max value are exclusive (not included) instead of
2012*572c4311Sfengbojiang  * inclusive. */
RM_ZsetFirstInScoreRange(RedisModuleKey * key,double min,double max,int minex,int maxex)2013*572c4311Sfengbojiang int RM_ZsetFirstInScoreRange(RedisModuleKey *key, double min, double max, int minex, int maxex) {
2014*572c4311Sfengbojiang     return zsetInitScoreRange(key,min,max,minex,maxex,1);
2015*572c4311Sfengbojiang }
2016*572c4311Sfengbojiang 
2017*572c4311Sfengbojiang /* Exactly like RedisModule_ZsetFirstInScoreRange() but the last element of
2018*572c4311Sfengbojiang  * the range is selected for the start of the iteration instead. */
RM_ZsetLastInScoreRange(RedisModuleKey * key,double min,double max,int minex,int maxex)2019*572c4311Sfengbojiang int RM_ZsetLastInScoreRange(RedisModuleKey *key, double min, double max, int minex, int maxex) {
2020*572c4311Sfengbojiang     return zsetInitScoreRange(key,min,max,minex,maxex,0);
2021*572c4311Sfengbojiang }
2022*572c4311Sfengbojiang 
2023*572c4311Sfengbojiang /* Helper function for RM_ZsetFirstInLexRange() and RM_ZsetLastInLexRange().
2024*572c4311Sfengbojiang  * Setup the sorted set iteration according to the specified lexicographical
2025*572c4311Sfengbojiang  * range (see the functions calling it for more info). If 'first' is true the
2026*572c4311Sfengbojiang  * first element in the range is used as a starting point for the iterator
2027*572c4311Sfengbojiang  * otherwise the last. Return REDISMODULE_OK on success otherwise
2028*572c4311Sfengbojiang  * REDISMODULE_ERR.
2029*572c4311Sfengbojiang  *
2030*572c4311Sfengbojiang  * Note that this function takes 'min' and 'max' in the same form of the
2031*572c4311Sfengbojiang  * Redis ZRANGEBYLEX command. */
zsetInitLexRange(RedisModuleKey * key,RedisModuleString * min,RedisModuleString * max,int first)2032*572c4311Sfengbojiang int zsetInitLexRange(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max, int first) {
2033*572c4311Sfengbojiang     if (!key->value || key->value->type != OBJ_ZSET) return REDISMODULE_ERR;
2034*572c4311Sfengbojiang 
2035*572c4311Sfengbojiang     RM_ZsetRangeStop(key);
2036*572c4311Sfengbojiang     key->zer = 0;
2037*572c4311Sfengbojiang 
2038*572c4311Sfengbojiang     /* Setup the range structure used by the sorted set core implementation
2039*572c4311Sfengbojiang      * in order to seek at the specified element. */
2040*572c4311Sfengbojiang     zlexrangespec *zlrs = &key->zlrs;
2041*572c4311Sfengbojiang     if (zslParseLexRange(min, max, zlrs) == C_ERR) return REDISMODULE_ERR;
2042*572c4311Sfengbojiang 
2043*572c4311Sfengbojiang     /* Set the range type to lex only after successfully parsing the range,
2044*572c4311Sfengbojiang      * otherwise we don't want the zlexrangespec to be freed. */
2045*572c4311Sfengbojiang     key->ztype = REDISMODULE_ZSET_RANGE_LEX;
2046*572c4311Sfengbojiang 
2047*572c4311Sfengbojiang     if (key->value->encoding == OBJ_ENCODING_ZIPLIST) {
2048*572c4311Sfengbojiang         key->zcurrent = first ? zzlFirstInLexRange(key->value->ptr,zlrs) :
2049*572c4311Sfengbojiang                                 zzlLastInLexRange(key->value->ptr,zlrs);
2050*572c4311Sfengbojiang     } else if (key->value->encoding == OBJ_ENCODING_SKIPLIST) {
2051*572c4311Sfengbojiang         zset *zs = key->value->ptr;
2052*572c4311Sfengbojiang         zskiplist *zsl = zs->zsl;
2053*572c4311Sfengbojiang         key->zcurrent = first ? zslFirstInLexRange(zsl,zlrs) :
2054*572c4311Sfengbojiang                                 zslLastInLexRange(zsl,zlrs);
2055*572c4311Sfengbojiang     } else {
2056*572c4311Sfengbojiang         serverPanic("Unsupported zset encoding");
2057*572c4311Sfengbojiang     }
2058*572c4311Sfengbojiang     if (key->zcurrent == NULL) key->zer = 1;
2059*572c4311Sfengbojiang 
2060*572c4311Sfengbojiang     return REDISMODULE_OK;
2061*572c4311Sfengbojiang }
2062*572c4311Sfengbojiang 
2063*572c4311Sfengbojiang /* Setup a sorted set iterator seeking the first element in the specified
2064*572c4311Sfengbojiang  * lexicographical range. Returns REDISMODULE_OK if the iterator was correctly
2065*572c4311Sfengbojiang  * initialized otherwise REDISMODULE_ERR is returned in the
2066*572c4311Sfengbojiang  * following conditions:
2067*572c4311Sfengbojiang  *
2068*572c4311Sfengbojiang  * 1. The value stored at key is not a sorted set or the key is empty.
2069*572c4311Sfengbojiang  * 2. The lexicographical range 'min' and 'max' format is invalid.
2070*572c4311Sfengbojiang  *
2071*572c4311Sfengbojiang  * 'min' and 'max' should be provided as two RedisModuleString objects
2072*572c4311Sfengbojiang  * in the same format as the parameters passed to the ZRANGEBYLEX command.
2073*572c4311Sfengbojiang  * The function does not take ownership of the objects, so they can be released
2074*572c4311Sfengbojiang  * ASAP after the iterator is setup. */
RM_ZsetFirstInLexRange(RedisModuleKey * key,RedisModuleString * min,RedisModuleString * max)2075*572c4311Sfengbojiang int RM_ZsetFirstInLexRange(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max) {
2076*572c4311Sfengbojiang     return zsetInitLexRange(key,min,max,1);
2077*572c4311Sfengbojiang }
2078*572c4311Sfengbojiang 
2079*572c4311Sfengbojiang /* Exactly like RedisModule_ZsetFirstInLexRange() but the last element of
2080*572c4311Sfengbojiang  * the range is selected for the start of the iteration instead. */
RM_ZsetLastInLexRange(RedisModuleKey * key,RedisModuleString * min,RedisModuleString * max)2081*572c4311Sfengbojiang int RM_ZsetLastInLexRange(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max) {
2082*572c4311Sfengbojiang     return zsetInitLexRange(key,min,max,0);
2083*572c4311Sfengbojiang }
2084*572c4311Sfengbojiang 
2085*572c4311Sfengbojiang /* Return the current sorted set element of an active sorted set iterator
2086*572c4311Sfengbojiang  * or NULL if the range specified in the iterator does not include any
2087*572c4311Sfengbojiang  * element. */
RM_ZsetRangeCurrentElement(RedisModuleKey * key,double * score)2088*572c4311Sfengbojiang RedisModuleString *RM_ZsetRangeCurrentElement(RedisModuleKey *key, double *score) {
2089*572c4311Sfengbojiang     RedisModuleString *str;
2090*572c4311Sfengbojiang 
2091*572c4311Sfengbojiang     if (key->zcurrent == NULL) return NULL;
2092*572c4311Sfengbojiang     if (key->value->encoding == OBJ_ENCODING_ZIPLIST) {
2093*572c4311Sfengbojiang         unsigned char *eptr, *sptr;
2094*572c4311Sfengbojiang         eptr = key->zcurrent;
2095*572c4311Sfengbojiang         sds ele = ziplistGetObject(eptr);
2096*572c4311Sfengbojiang         if (score) {
2097*572c4311Sfengbojiang             sptr = ziplistNext(key->value->ptr,eptr);
2098*572c4311Sfengbojiang             *score = zzlGetScore(sptr);
2099*572c4311Sfengbojiang         }
2100*572c4311Sfengbojiang         str = createObject(OBJ_STRING,ele);
2101*572c4311Sfengbojiang     } else if (key->value->encoding == OBJ_ENCODING_SKIPLIST) {
2102*572c4311Sfengbojiang         zskiplistNode *ln = key->zcurrent;
2103*572c4311Sfengbojiang         if (score) *score = ln->score;
2104*572c4311Sfengbojiang         str = createStringObject(ln->ele,sdslen(ln->ele));
2105*572c4311Sfengbojiang     } else {
2106*572c4311Sfengbojiang         serverPanic("Unsupported zset encoding");
2107*572c4311Sfengbojiang     }
2108*572c4311Sfengbojiang     autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,str);
2109*572c4311Sfengbojiang     return str;
2110*572c4311Sfengbojiang }
2111*572c4311Sfengbojiang 
2112*572c4311Sfengbojiang /* Go to the next element of the sorted set iterator. Returns 1 if there was
2113*572c4311Sfengbojiang  * a next element, 0 if we are already at the latest element or the range
2114*572c4311Sfengbojiang  * does not include any item at all. */
RM_ZsetRangeNext(RedisModuleKey * key)2115*572c4311Sfengbojiang int RM_ZsetRangeNext(RedisModuleKey *key) {
2116*572c4311Sfengbojiang     if (!key->ztype || !key->zcurrent) return 0; /* No active iterator. */
2117*572c4311Sfengbojiang 
2118*572c4311Sfengbojiang     if (key->value->encoding == OBJ_ENCODING_ZIPLIST) {
2119*572c4311Sfengbojiang         unsigned char *zl = key->value->ptr;
2120*572c4311Sfengbojiang         unsigned char *eptr = key->zcurrent;
2121*572c4311Sfengbojiang         unsigned char *next;
2122*572c4311Sfengbojiang         next = ziplistNext(zl,eptr); /* Skip element. */
2123*572c4311Sfengbojiang         if (next) next = ziplistNext(zl,next); /* Skip score. */
2124*572c4311Sfengbojiang         if (next == NULL) {
2125*572c4311Sfengbojiang             key->zer = 1;
2126*572c4311Sfengbojiang             return 0;
2127*572c4311Sfengbojiang         } else {
2128*572c4311Sfengbojiang             /* Are we still within the range? */
2129*572c4311Sfengbojiang             if (key->ztype == REDISMODULE_ZSET_RANGE_SCORE) {
2130*572c4311Sfengbojiang                 /* Fetch the next element score for the
2131*572c4311Sfengbojiang                  * range check. */
2132*572c4311Sfengbojiang                 unsigned char *saved_next = next;
2133*572c4311Sfengbojiang                 next = ziplistNext(zl,next); /* Skip next element. */
2134*572c4311Sfengbojiang                 double score = zzlGetScore(next); /* Obtain the next score. */
2135*572c4311Sfengbojiang                 if (!zslValueLteMax(score,&key->zrs)) {
2136*572c4311Sfengbojiang                     key->zer = 1;
2137*572c4311Sfengbojiang                     return 0;
2138*572c4311Sfengbojiang                 }
2139*572c4311Sfengbojiang                 next = saved_next;
2140*572c4311Sfengbojiang             } else if (key->ztype == REDISMODULE_ZSET_RANGE_LEX) {
2141*572c4311Sfengbojiang                 if (!zzlLexValueLteMax(next,&key->zlrs)) {
2142*572c4311Sfengbojiang                     key->zer = 1;
2143*572c4311Sfengbojiang                     return 0;
2144*572c4311Sfengbojiang                 }
2145*572c4311Sfengbojiang             }
2146*572c4311Sfengbojiang             key->zcurrent = next;
2147*572c4311Sfengbojiang             return 1;
2148*572c4311Sfengbojiang         }
2149*572c4311Sfengbojiang     } else if (key->value->encoding == OBJ_ENCODING_SKIPLIST) {
2150*572c4311Sfengbojiang         zskiplistNode *ln = key->zcurrent, *next = ln->level[0].forward;
2151*572c4311Sfengbojiang         if (next == NULL) {
2152*572c4311Sfengbojiang             key->zer = 1;
2153*572c4311Sfengbojiang             return 0;
2154*572c4311Sfengbojiang         } else {
2155*572c4311Sfengbojiang             /* Are we still within the range? */
2156*572c4311Sfengbojiang             if (key->ztype == REDISMODULE_ZSET_RANGE_SCORE &&
2157*572c4311Sfengbojiang                 !zslValueLteMax(next->score,&key->zrs))
2158*572c4311Sfengbojiang             {
2159*572c4311Sfengbojiang                 key->zer = 1;
2160*572c4311Sfengbojiang                 return 0;
2161*572c4311Sfengbojiang             } else if (key->ztype == REDISMODULE_ZSET_RANGE_LEX) {
2162*572c4311Sfengbojiang                 if (!zslLexValueLteMax(next->ele,&key->zlrs)) {
2163*572c4311Sfengbojiang                     key->zer = 1;
2164*572c4311Sfengbojiang                     return 0;
2165*572c4311Sfengbojiang                 }
2166*572c4311Sfengbojiang             }
2167*572c4311Sfengbojiang             key->zcurrent = next;
2168*572c4311Sfengbojiang             return 1;
2169*572c4311Sfengbojiang         }
2170*572c4311Sfengbojiang     } else {
2171*572c4311Sfengbojiang         serverPanic("Unsupported zset encoding");
2172*572c4311Sfengbojiang     }
2173*572c4311Sfengbojiang }
2174*572c4311Sfengbojiang 
2175*572c4311Sfengbojiang /* Go to the previous element of the sorted set iterator. Returns 1 if there was
2176*572c4311Sfengbojiang  * a previous element, 0 if we are already at the first element or the range
2177*572c4311Sfengbojiang  * does not include any item at all. */
RM_ZsetRangePrev(RedisModuleKey * key)2178*572c4311Sfengbojiang int RM_ZsetRangePrev(RedisModuleKey *key) {
2179*572c4311Sfengbojiang     if (!key->ztype || !key->zcurrent) return 0; /* No active iterator. */
2180*572c4311Sfengbojiang 
2181*572c4311Sfengbojiang     if (key->value->encoding == OBJ_ENCODING_ZIPLIST) {
2182*572c4311Sfengbojiang         unsigned char *zl = key->value->ptr;
2183*572c4311Sfengbojiang         unsigned char *eptr = key->zcurrent;
2184*572c4311Sfengbojiang         unsigned char *prev;
2185*572c4311Sfengbojiang         prev = ziplistPrev(zl,eptr); /* Go back to previous score. */
2186*572c4311Sfengbojiang         if (prev) prev = ziplistPrev(zl,prev); /* Back to previous ele. */
2187*572c4311Sfengbojiang         if (prev == NULL) {
2188*572c4311Sfengbojiang             key->zer = 1;
2189*572c4311Sfengbojiang             return 0;
2190*572c4311Sfengbojiang         } else {
2191*572c4311Sfengbojiang             /* Are we still within the range? */
2192*572c4311Sfengbojiang             if (key->ztype == REDISMODULE_ZSET_RANGE_SCORE) {
2193*572c4311Sfengbojiang                 /* Fetch the previous element score for the
2194*572c4311Sfengbojiang                  * range check. */
2195*572c4311Sfengbojiang                 unsigned char *saved_prev = prev;
2196*572c4311Sfengbojiang                 prev = ziplistNext(zl,prev); /* Skip element to get the score.*/
2197*572c4311Sfengbojiang                 double score = zzlGetScore(prev); /* Obtain the prev score. */
2198*572c4311Sfengbojiang                 if (!zslValueGteMin(score,&key->zrs)) {
2199*572c4311Sfengbojiang                     key->zer = 1;
2200*572c4311Sfengbojiang                     return 0;
2201*572c4311Sfengbojiang                 }
2202*572c4311Sfengbojiang                 prev = saved_prev;
2203*572c4311Sfengbojiang             } else if (key->ztype == REDISMODULE_ZSET_RANGE_LEX) {
2204*572c4311Sfengbojiang                 if (!zzlLexValueGteMin(prev,&key->zlrs)) {
2205*572c4311Sfengbojiang                     key->zer = 1;
2206*572c4311Sfengbojiang                     return 0;
2207*572c4311Sfengbojiang                 }
2208*572c4311Sfengbojiang             }
2209*572c4311Sfengbojiang             key->zcurrent = prev;
2210*572c4311Sfengbojiang             return 1;
2211*572c4311Sfengbojiang         }
2212*572c4311Sfengbojiang     } else if (key->value->encoding == OBJ_ENCODING_SKIPLIST) {
2213*572c4311Sfengbojiang         zskiplistNode *ln = key->zcurrent, *prev = ln->backward;
2214*572c4311Sfengbojiang         if (prev == NULL) {
2215*572c4311Sfengbojiang             key->zer = 1;
2216*572c4311Sfengbojiang             return 0;
2217*572c4311Sfengbojiang         } else {
2218*572c4311Sfengbojiang             /* Are we still within the range? */
2219*572c4311Sfengbojiang             if (key->ztype == REDISMODULE_ZSET_RANGE_SCORE &&
2220*572c4311Sfengbojiang                 !zslValueGteMin(prev->score,&key->zrs))
2221*572c4311Sfengbojiang             {
2222*572c4311Sfengbojiang                 key->zer = 1;
2223*572c4311Sfengbojiang                 return 0;
2224*572c4311Sfengbojiang             } else if (key->ztype == REDISMODULE_ZSET_RANGE_LEX) {
2225*572c4311Sfengbojiang                 if (!zslLexValueGteMin(prev->ele,&key->zlrs)) {
2226*572c4311Sfengbojiang                     key->zer = 1;
2227*572c4311Sfengbojiang                     return 0;
2228*572c4311Sfengbojiang                 }
2229*572c4311Sfengbojiang             }
2230*572c4311Sfengbojiang             key->zcurrent = prev;
2231*572c4311Sfengbojiang             return 1;
2232*572c4311Sfengbojiang         }
2233*572c4311Sfengbojiang     } else {
2234*572c4311Sfengbojiang         serverPanic("Unsupported zset encoding");
2235*572c4311Sfengbojiang     }
2236*572c4311Sfengbojiang }
2237*572c4311Sfengbojiang 
2238*572c4311Sfengbojiang /* --------------------------------------------------------------------------
2239*572c4311Sfengbojiang  * Key API for Hash type
2240*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
2241*572c4311Sfengbojiang 
2242*572c4311Sfengbojiang /* Set the field of the specified hash field to the specified value.
2243*572c4311Sfengbojiang  * If the key is an empty key open for writing, it is created with an empty
2244*572c4311Sfengbojiang  * hash value, in order to set the specified field.
2245*572c4311Sfengbojiang  *
2246*572c4311Sfengbojiang  * The function is variadic and the user must specify pairs of field
2247*572c4311Sfengbojiang  * names and values, both as RedisModuleString pointers (unless the
2248*572c4311Sfengbojiang  * CFIELD option is set, see later). At the end of the field/value-ptr pairs,
2249*572c4311Sfengbojiang  * NULL must be specified as last argument to signal the end of the arguments
2250*572c4311Sfengbojiang  * in the variadic function.
2251*572c4311Sfengbojiang  *
2252*572c4311Sfengbojiang  * Example to set the hash argv[1] to the value argv[2]:
2253*572c4311Sfengbojiang  *
2254*572c4311Sfengbojiang  *      RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],argv[2],NULL);
2255*572c4311Sfengbojiang  *
2256*572c4311Sfengbojiang  * The function can also be used in order to delete fields (if they exist)
2257*572c4311Sfengbojiang  * by setting them to the specified value of REDISMODULE_HASH_DELETE:
2258*572c4311Sfengbojiang  *
2259*572c4311Sfengbojiang  *      RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],
2260*572c4311Sfengbojiang  *                          REDISMODULE_HASH_DELETE,NULL);
2261*572c4311Sfengbojiang  *
2262*572c4311Sfengbojiang  * The behavior of the command changes with the specified flags, that can be
2263*572c4311Sfengbojiang  * set to REDISMODULE_HASH_NONE if no special behavior is needed.
2264*572c4311Sfengbojiang  *
2265*572c4311Sfengbojiang  *     REDISMODULE_HASH_NX: The operation is performed only if the field was not
2266*572c4311Sfengbojiang  *                          already existing in the hash.
2267*572c4311Sfengbojiang  *     REDISMODULE_HASH_XX: The operation is performed only if the field was
2268*572c4311Sfengbojiang  *                          already existing, so that a new value could be
2269*572c4311Sfengbojiang  *                          associated to an existing filed, but no new fields
2270*572c4311Sfengbojiang  *                          are created.
2271*572c4311Sfengbojiang  *     REDISMODULE_HASH_CFIELDS: The field names passed are null terminated C
2272*572c4311Sfengbojiang  *                               strings instead of RedisModuleString objects.
2273*572c4311Sfengbojiang  *
2274*572c4311Sfengbojiang  * Unless NX is specified, the command overwrites the old field value with
2275*572c4311Sfengbojiang  * the new one.
2276*572c4311Sfengbojiang  *
2277*572c4311Sfengbojiang  * When using REDISMODULE_HASH_CFIELDS, field names are reported using
2278*572c4311Sfengbojiang  * normal C strings, so for example to delete the field "foo" the following
2279*572c4311Sfengbojiang  * code can be used:
2280*572c4311Sfengbojiang  *
2281*572c4311Sfengbojiang  *      RedisModule_HashSet(key,REDISMODULE_HASH_CFIELDS,"foo",
2282*572c4311Sfengbojiang  *                          REDISMODULE_HASH_DELETE,NULL);
2283*572c4311Sfengbojiang  *
2284*572c4311Sfengbojiang  * Return value:
2285*572c4311Sfengbojiang  *
2286*572c4311Sfengbojiang  * The number of fields updated (that may be less than the number of fields
2287*572c4311Sfengbojiang  * specified because of the XX or NX options).
2288*572c4311Sfengbojiang  *
2289*572c4311Sfengbojiang  * In the following case the return value is always zero:
2290*572c4311Sfengbojiang  *
2291*572c4311Sfengbojiang  * * The key was not open for writing.
2292*572c4311Sfengbojiang  * * The key was associated with a non Hash value.
2293*572c4311Sfengbojiang  */
RM_HashSet(RedisModuleKey * key,int flags,...)2294*572c4311Sfengbojiang int RM_HashSet(RedisModuleKey *key, int flags, ...) {
2295*572c4311Sfengbojiang     va_list ap;
2296*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE)) return 0;
2297*572c4311Sfengbojiang     if (key->value && key->value->type != OBJ_HASH) return 0;
2298*572c4311Sfengbojiang     if (key->value == NULL) moduleCreateEmptyKey(key,REDISMODULE_KEYTYPE_HASH);
2299*572c4311Sfengbojiang 
2300*572c4311Sfengbojiang     int updated = 0;
2301*572c4311Sfengbojiang     va_start(ap, flags);
2302*572c4311Sfengbojiang     while(1) {
2303*572c4311Sfengbojiang         RedisModuleString *field, *value;
2304*572c4311Sfengbojiang         /* Get the field and value objects. */
2305*572c4311Sfengbojiang         if (flags & REDISMODULE_HASH_CFIELDS) {
2306*572c4311Sfengbojiang             char *cfield = va_arg(ap,char*);
2307*572c4311Sfengbojiang             if (cfield == NULL) break;
2308*572c4311Sfengbojiang             field = createRawStringObject(cfield,strlen(cfield));
2309*572c4311Sfengbojiang         } else {
2310*572c4311Sfengbojiang             field = va_arg(ap,RedisModuleString*);
2311*572c4311Sfengbojiang             if (field == NULL) break;
2312*572c4311Sfengbojiang         }
2313*572c4311Sfengbojiang         value = va_arg(ap,RedisModuleString*);
2314*572c4311Sfengbojiang 
2315*572c4311Sfengbojiang         /* Handle XX and NX */
2316*572c4311Sfengbojiang         if (flags & (REDISMODULE_HASH_XX|REDISMODULE_HASH_NX)) {
2317*572c4311Sfengbojiang             int exists = hashTypeExists(key->value, field->ptr);
2318*572c4311Sfengbojiang             if (((flags & REDISMODULE_HASH_XX) && !exists) ||
2319*572c4311Sfengbojiang                 ((flags & REDISMODULE_HASH_NX) && exists))
2320*572c4311Sfengbojiang             {
2321*572c4311Sfengbojiang                 if (flags & REDISMODULE_HASH_CFIELDS) decrRefCount(field);
2322*572c4311Sfengbojiang                 continue;
2323*572c4311Sfengbojiang             }
2324*572c4311Sfengbojiang         }
2325*572c4311Sfengbojiang 
2326*572c4311Sfengbojiang         /* Handle deletion if value is REDISMODULE_HASH_DELETE. */
2327*572c4311Sfengbojiang         if (value == REDISMODULE_HASH_DELETE) {
2328*572c4311Sfengbojiang             updated += hashTypeDelete(key->value, field->ptr);
2329*572c4311Sfengbojiang             if (flags & REDISMODULE_HASH_CFIELDS) decrRefCount(field);
2330*572c4311Sfengbojiang             continue;
2331*572c4311Sfengbojiang         }
2332*572c4311Sfengbojiang 
2333*572c4311Sfengbojiang         int low_flags = HASH_SET_COPY;
2334*572c4311Sfengbojiang         /* If CFIELDS is active, we can pass the ownership of the
2335*572c4311Sfengbojiang          * SDS object to the low level function that sets the field
2336*572c4311Sfengbojiang          * to avoid a useless copy. */
2337*572c4311Sfengbojiang         if (flags & REDISMODULE_HASH_CFIELDS)
2338*572c4311Sfengbojiang             low_flags |= HASH_SET_TAKE_FIELD;
2339*572c4311Sfengbojiang 
2340*572c4311Sfengbojiang         robj *argv[2] = {field,value};
2341*572c4311Sfengbojiang         hashTypeTryConversion(key->value,argv,0,1);
2342*572c4311Sfengbojiang         updated += hashTypeSet(key->value, field->ptr, value->ptr, low_flags);
2343*572c4311Sfengbojiang 
2344*572c4311Sfengbojiang         /* If CFIELDS is active, SDS string ownership is now of hashTypeSet(),
2345*572c4311Sfengbojiang          * however we still have to release the 'field' object shell. */
2346*572c4311Sfengbojiang         if (flags & REDISMODULE_HASH_CFIELDS) {
2347*572c4311Sfengbojiang            field->ptr = NULL; /* Prevent the SDS string from being freed. */
2348*572c4311Sfengbojiang            decrRefCount(field);
2349*572c4311Sfengbojiang         }
2350*572c4311Sfengbojiang     }
2351*572c4311Sfengbojiang     va_end(ap);
2352*572c4311Sfengbojiang     moduleDelKeyIfEmpty(key);
2353*572c4311Sfengbojiang     return updated;
2354*572c4311Sfengbojiang }
2355*572c4311Sfengbojiang 
2356*572c4311Sfengbojiang /* Get fields from an hash value. This function is called using a variable
2357*572c4311Sfengbojiang  * number of arguments, alternating a field name (as a StringRedisModule
2358*572c4311Sfengbojiang  * pointer) with a pointer to a StringRedisModule pointer, that is set to the
2359*572c4311Sfengbojiang  * value of the field if the field exist, or NULL if the field did not exist.
2360*572c4311Sfengbojiang  * At the end of the field/value-ptr pairs, NULL must be specified as last
2361*572c4311Sfengbojiang  * argument to signal the end of the arguments in the variadic function.
2362*572c4311Sfengbojiang  *
2363*572c4311Sfengbojiang  * This is an example usage:
2364*572c4311Sfengbojiang  *
2365*572c4311Sfengbojiang  *      RedisModuleString *first, *second;
2366*572c4311Sfengbojiang  *      RedisModule_HashGet(mykey,REDISMODULE_HASH_NONE,argv[1],&first,
2367*572c4311Sfengbojiang  *                      argv[2],&second,NULL);
2368*572c4311Sfengbojiang  *
2369*572c4311Sfengbojiang  * As with RedisModule_HashSet() the behavior of the command can be specified
2370*572c4311Sfengbojiang  * passing flags different than REDISMODULE_HASH_NONE:
2371*572c4311Sfengbojiang  *
2372*572c4311Sfengbojiang  * REDISMODULE_HASH_CFIELD: field names as null terminated C strings.
2373*572c4311Sfengbojiang  *
2374*572c4311Sfengbojiang  * REDISMODULE_HASH_EXISTS: instead of setting the value of the field
2375*572c4311Sfengbojiang  * expecting a RedisModuleString pointer to pointer, the function just
2376*572c4311Sfengbojiang  * reports if the field esists or not and expects an integer pointer
2377*572c4311Sfengbojiang  * as the second element of each pair.
2378*572c4311Sfengbojiang  *
2379*572c4311Sfengbojiang  * Example of REDISMODULE_HASH_CFIELD:
2380*572c4311Sfengbojiang  *
2381*572c4311Sfengbojiang  *      RedisModuleString *username, *hashedpass;
2382*572c4311Sfengbojiang  *      RedisModule_HashGet(mykey,"username",&username,"hp",&hashedpass, NULL);
2383*572c4311Sfengbojiang  *
2384*572c4311Sfengbojiang  * Example of REDISMODULE_HASH_EXISTS:
2385*572c4311Sfengbojiang  *
2386*572c4311Sfengbojiang  *      int exists;
2387*572c4311Sfengbojiang  *      RedisModule_HashGet(mykey,argv[1],&exists,NULL);
2388*572c4311Sfengbojiang  *
2389*572c4311Sfengbojiang  * The function returns REDISMODULE_OK on success and REDISMODULE_ERR if
2390*572c4311Sfengbojiang  * the key is not an hash value.
2391*572c4311Sfengbojiang  *
2392*572c4311Sfengbojiang  * Memory management:
2393*572c4311Sfengbojiang  *
2394*572c4311Sfengbojiang  * The returned RedisModuleString objects should be released with
2395*572c4311Sfengbojiang  * RedisModule_FreeString(), or by enabling automatic memory management.
2396*572c4311Sfengbojiang  */
RM_HashGet(RedisModuleKey * key,int flags,...)2397*572c4311Sfengbojiang int RM_HashGet(RedisModuleKey *key, int flags, ...) {
2398*572c4311Sfengbojiang     va_list ap;
2399*572c4311Sfengbojiang     if (key->value && key->value->type != OBJ_HASH) return REDISMODULE_ERR;
2400*572c4311Sfengbojiang 
2401*572c4311Sfengbojiang     va_start(ap, flags);
2402*572c4311Sfengbojiang     while(1) {
2403*572c4311Sfengbojiang         RedisModuleString *field, **valueptr;
2404*572c4311Sfengbojiang         int *existsptr;
2405*572c4311Sfengbojiang         /* Get the field object and the value pointer to pointer. */
2406*572c4311Sfengbojiang         if (flags & REDISMODULE_HASH_CFIELDS) {
2407*572c4311Sfengbojiang             char *cfield = va_arg(ap,char*);
2408*572c4311Sfengbojiang             if (cfield == NULL) break;
2409*572c4311Sfengbojiang             field = createRawStringObject(cfield,strlen(cfield));
2410*572c4311Sfengbojiang         } else {
2411*572c4311Sfengbojiang             field = va_arg(ap,RedisModuleString*);
2412*572c4311Sfengbojiang             if (field == NULL) break;
2413*572c4311Sfengbojiang         }
2414*572c4311Sfengbojiang 
2415*572c4311Sfengbojiang         /* Query the hash for existence or value object. */
2416*572c4311Sfengbojiang         if (flags & REDISMODULE_HASH_EXISTS) {
2417*572c4311Sfengbojiang             existsptr = va_arg(ap,int*);
2418*572c4311Sfengbojiang             if (key->value)
2419*572c4311Sfengbojiang                 *existsptr = hashTypeExists(key->value,field->ptr);
2420*572c4311Sfengbojiang             else
2421*572c4311Sfengbojiang                 *existsptr = 0;
2422*572c4311Sfengbojiang         } else {
2423*572c4311Sfengbojiang             valueptr = va_arg(ap,RedisModuleString**);
2424*572c4311Sfengbojiang             if (key->value) {
2425*572c4311Sfengbojiang                 *valueptr = hashTypeGetValueObject(key->value,field->ptr);
2426*572c4311Sfengbojiang                 if (*valueptr) {
2427*572c4311Sfengbojiang                     robj *decoded = getDecodedObject(*valueptr);
2428*572c4311Sfengbojiang                     decrRefCount(*valueptr);
2429*572c4311Sfengbojiang                     *valueptr = decoded;
2430*572c4311Sfengbojiang                 }
2431*572c4311Sfengbojiang                 if (*valueptr)
2432*572c4311Sfengbojiang                     autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,*valueptr);
2433*572c4311Sfengbojiang             } else {
2434*572c4311Sfengbojiang                 *valueptr = NULL;
2435*572c4311Sfengbojiang             }
2436*572c4311Sfengbojiang         }
2437*572c4311Sfengbojiang 
2438*572c4311Sfengbojiang         /* Cleanup */
2439*572c4311Sfengbojiang         if (flags & REDISMODULE_HASH_CFIELDS) decrRefCount(field);
2440*572c4311Sfengbojiang     }
2441*572c4311Sfengbojiang     va_end(ap);
2442*572c4311Sfengbojiang     return REDISMODULE_OK;
2443*572c4311Sfengbojiang }
2444*572c4311Sfengbojiang 
2445*572c4311Sfengbojiang /* --------------------------------------------------------------------------
2446*572c4311Sfengbojiang  * Redis <-> Modules generic Call() API
2447*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
2448*572c4311Sfengbojiang 
2449*572c4311Sfengbojiang /* Create a new RedisModuleCallReply object. The processing of the reply
2450*572c4311Sfengbojiang  * is lazy, the object is just populated with the raw protocol and later
2451*572c4311Sfengbojiang  * is processed as needed. Initially we just make sure to set the right
2452*572c4311Sfengbojiang  * reply type, which is extremely cheap to do. */
moduleCreateCallReplyFromProto(RedisModuleCtx * ctx,sds proto)2453*572c4311Sfengbojiang RedisModuleCallReply *moduleCreateCallReplyFromProto(RedisModuleCtx *ctx, sds proto) {
2454*572c4311Sfengbojiang     RedisModuleCallReply *reply = zmalloc(sizeof(*reply));
2455*572c4311Sfengbojiang     reply->ctx = ctx;
2456*572c4311Sfengbojiang     reply->proto = proto;
2457*572c4311Sfengbojiang     reply->protolen = sdslen(proto);
2458*572c4311Sfengbojiang     reply->flags = REDISMODULE_REPLYFLAG_TOPARSE; /* Lazy parsing. */
2459*572c4311Sfengbojiang     switch(proto[0]) {
2460*572c4311Sfengbojiang     case '$':
2461*572c4311Sfengbojiang     case '+': reply->type = REDISMODULE_REPLY_STRING; break;
2462*572c4311Sfengbojiang     case '-': reply->type = REDISMODULE_REPLY_ERROR; break;
2463*572c4311Sfengbojiang     case ':': reply->type = REDISMODULE_REPLY_INTEGER; break;
2464*572c4311Sfengbojiang     case '*': reply->type = REDISMODULE_REPLY_ARRAY; break;
2465*572c4311Sfengbojiang     default: reply->type = REDISMODULE_REPLY_UNKNOWN; break;
2466*572c4311Sfengbojiang     }
2467*572c4311Sfengbojiang     if ((proto[0] == '*' || proto[0] == '$') && proto[1] == '-')
2468*572c4311Sfengbojiang         reply->type = REDISMODULE_REPLY_NULL;
2469*572c4311Sfengbojiang     return reply;
2470*572c4311Sfengbojiang }
2471*572c4311Sfengbojiang 
2472*572c4311Sfengbojiang void moduleParseCallReply_Int(RedisModuleCallReply *reply);
2473*572c4311Sfengbojiang void moduleParseCallReply_BulkString(RedisModuleCallReply *reply);
2474*572c4311Sfengbojiang void moduleParseCallReply_SimpleString(RedisModuleCallReply *reply);
2475*572c4311Sfengbojiang void moduleParseCallReply_Array(RedisModuleCallReply *reply);
2476*572c4311Sfengbojiang 
2477*572c4311Sfengbojiang /* Do nothing if REDISMODULE_REPLYFLAG_TOPARSE is false, otherwise
2478*572c4311Sfengbojiang  * use the protcol of the reply in reply->proto in order to fill the
2479*572c4311Sfengbojiang  * reply with parsed data according to the reply type. */
moduleParseCallReply(RedisModuleCallReply * reply)2480*572c4311Sfengbojiang void moduleParseCallReply(RedisModuleCallReply *reply) {
2481*572c4311Sfengbojiang     if (!(reply->flags & REDISMODULE_REPLYFLAG_TOPARSE)) return;
2482*572c4311Sfengbojiang     reply->flags &= ~REDISMODULE_REPLYFLAG_TOPARSE;
2483*572c4311Sfengbojiang 
2484*572c4311Sfengbojiang     switch(reply->proto[0]) {
2485*572c4311Sfengbojiang     case ':': moduleParseCallReply_Int(reply); break;
2486*572c4311Sfengbojiang     case '$': moduleParseCallReply_BulkString(reply); break;
2487*572c4311Sfengbojiang     case '-': /* handled by next item. */
2488*572c4311Sfengbojiang     case '+': moduleParseCallReply_SimpleString(reply); break;
2489*572c4311Sfengbojiang     case '*': moduleParseCallReply_Array(reply); break;
2490*572c4311Sfengbojiang     }
2491*572c4311Sfengbojiang }
2492*572c4311Sfengbojiang 
moduleParseCallReply_Int(RedisModuleCallReply * reply)2493*572c4311Sfengbojiang void moduleParseCallReply_Int(RedisModuleCallReply *reply) {
2494*572c4311Sfengbojiang     char *proto = reply->proto;
2495*572c4311Sfengbojiang     char *p = strchr(proto+1,'\r');
2496*572c4311Sfengbojiang 
2497*572c4311Sfengbojiang     string2ll(proto+1,p-proto-1,&reply->val.ll);
2498*572c4311Sfengbojiang     reply->protolen = p-proto+2;
2499*572c4311Sfengbojiang     reply->type = REDISMODULE_REPLY_INTEGER;
2500*572c4311Sfengbojiang }
2501*572c4311Sfengbojiang 
moduleParseCallReply_BulkString(RedisModuleCallReply * reply)2502*572c4311Sfengbojiang void moduleParseCallReply_BulkString(RedisModuleCallReply *reply) {
2503*572c4311Sfengbojiang     char *proto = reply->proto;
2504*572c4311Sfengbojiang     char *p = strchr(proto+1,'\r');
2505*572c4311Sfengbojiang     long long bulklen;
2506*572c4311Sfengbojiang 
2507*572c4311Sfengbojiang     string2ll(proto+1,p-proto-1,&bulklen);
2508*572c4311Sfengbojiang     if (bulklen == -1) {
2509*572c4311Sfengbojiang         reply->protolen = p-proto+2;
2510*572c4311Sfengbojiang         reply->type = REDISMODULE_REPLY_NULL;
2511*572c4311Sfengbojiang     } else {
2512*572c4311Sfengbojiang         reply->val.str = p+2;
2513*572c4311Sfengbojiang         reply->len = bulklen;
2514*572c4311Sfengbojiang         reply->protolen = p-proto+2+bulklen+2;
2515*572c4311Sfengbojiang         reply->type = REDISMODULE_REPLY_STRING;
2516*572c4311Sfengbojiang     }
2517*572c4311Sfengbojiang }
2518*572c4311Sfengbojiang 
moduleParseCallReply_SimpleString(RedisModuleCallReply * reply)2519*572c4311Sfengbojiang void moduleParseCallReply_SimpleString(RedisModuleCallReply *reply) {
2520*572c4311Sfengbojiang     char *proto = reply->proto;
2521*572c4311Sfengbojiang     char *p = strchr(proto+1,'\r');
2522*572c4311Sfengbojiang 
2523*572c4311Sfengbojiang     reply->val.str = proto+1;
2524*572c4311Sfengbojiang     reply->len = p-proto-1;
2525*572c4311Sfengbojiang     reply->protolen = p-proto+2;
2526*572c4311Sfengbojiang     reply->type = proto[0] == '+' ? REDISMODULE_REPLY_STRING :
2527*572c4311Sfengbojiang                                     REDISMODULE_REPLY_ERROR;
2528*572c4311Sfengbojiang }
2529*572c4311Sfengbojiang 
moduleParseCallReply_Array(RedisModuleCallReply * reply)2530*572c4311Sfengbojiang void moduleParseCallReply_Array(RedisModuleCallReply *reply) {
2531*572c4311Sfengbojiang     char *proto = reply->proto;
2532*572c4311Sfengbojiang     char *p = strchr(proto+1,'\r');
2533*572c4311Sfengbojiang     long long arraylen, j;
2534*572c4311Sfengbojiang 
2535*572c4311Sfengbojiang     string2ll(proto+1,p-proto-1,&arraylen);
2536*572c4311Sfengbojiang     p += 2;
2537*572c4311Sfengbojiang 
2538*572c4311Sfengbojiang     if (arraylen == -1) {
2539*572c4311Sfengbojiang         reply->protolen = p-proto;
2540*572c4311Sfengbojiang         reply->type = REDISMODULE_REPLY_NULL;
2541*572c4311Sfengbojiang         return;
2542*572c4311Sfengbojiang     }
2543*572c4311Sfengbojiang 
2544*572c4311Sfengbojiang     reply->val.array = zmalloc(sizeof(RedisModuleCallReply)*arraylen);
2545*572c4311Sfengbojiang     reply->len = arraylen;
2546*572c4311Sfengbojiang     for (j = 0; j < arraylen; j++) {
2547*572c4311Sfengbojiang         RedisModuleCallReply *ele = reply->val.array+j;
2548*572c4311Sfengbojiang         ele->flags = REDISMODULE_REPLYFLAG_NESTED |
2549*572c4311Sfengbojiang                      REDISMODULE_REPLYFLAG_TOPARSE;
2550*572c4311Sfengbojiang         ele->proto = p;
2551*572c4311Sfengbojiang         ele->ctx = reply->ctx;
2552*572c4311Sfengbojiang         moduleParseCallReply(ele);
2553*572c4311Sfengbojiang         p += ele->protolen;
2554*572c4311Sfengbojiang     }
2555*572c4311Sfengbojiang     reply->protolen = p-proto;
2556*572c4311Sfengbojiang     reply->type = REDISMODULE_REPLY_ARRAY;
2557*572c4311Sfengbojiang }
2558*572c4311Sfengbojiang 
2559*572c4311Sfengbojiang /* Free a Call reply and all the nested replies it contains if it's an
2560*572c4311Sfengbojiang  * array. */
RM_FreeCallReply_Rec(RedisModuleCallReply * reply,int freenested)2561*572c4311Sfengbojiang void RM_FreeCallReply_Rec(RedisModuleCallReply *reply, int freenested){
2562*572c4311Sfengbojiang     /* Don't free nested replies by default: the user must always free the
2563*572c4311Sfengbojiang      * toplevel reply. However be gentle and don't crash if the module
2564*572c4311Sfengbojiang      * misuses the API. */
2565*572c4311Sfengbojiang     if (!freenested && reply->flags & REDISMODULE_REPLYFLAG_NESTED) return;
2566*572c4311Sfengbojiang 
2567*572c4311Sfengbojiang     if (!(reply->flags & REDISMODULE_REPLYFLAG_TOPARSE)) {
2568*572c4311Sfengbojiang         if (reply->type == REDISMODULE_REPLY_ARRAY) {
2569*572c4311Sfengbojiang             size_t j;
2570*572c4311Sfengbojiang             for (j = 0; j < reply->len; j++)
2571*572c4311Sfengbojiang                 RM_FreeCallReply_Rec(reply->val.array+j,1);
2572*572c4311Sfengbojiang             zfree(reply->val.array);
2573*572c4311Sfengbojiang         }
2574*572c4311Sfengbojiang     }
2575*572c4311Sfengbojiang 
2576*572c4311Sfengbojiang     /* For nested replies, we don't free reply->proto (which if not NULL
2577*572c4311Sfengbojiang      * references the parent reply->proto buffer), nor the structure
2578*572c4311Sfengbojiang      * itself which is allocated as an array of structures, and is freed
2579*572c4311Sfengbojiang      * when the array value is released. */
2580*572c4311Sfengbojiang     if (!(reply->flags & REDISMODULE_REPLYFLAG_NESTED)) {
2581*572c4311Sfengbojiang         if (reply->proto) sdsfree(reply->proto);
2582*572c4311Sfengbojiang         zfree(reply);
2583*572c4311Sfengbojiang     }
2584*572c4311Sfengbojiang }
2585*572c4311Sfengbojiang 
2586*572c4311Sfengbojiang /* Wrapper for the recursive free reply function. This is needed in order
2587*572c4311Sfengbojiang  * to have the first level function to return on nested replies, but only
2588*572c4311Sfengbojiang  * if called by the module API. */
RM_FreeCallReply(RedisModuleCallReply * reply)2589*572c4311Sfengbojiang void RM_FreeCallReply(RedisModuleCallReply *reply) {
2590*572c4311Sfengbojiang 
2591*572c4311Sfengbojiang     RedisModuleCtx *ctx = reply->ctx;
2592*572c4311Sfengbojiang     RM_FreeCallReply_Rec(reply,0);
2593*572c4311Sfengbojiang     autoMemoryFreed(ctx,REDISMODULE_AM_REPLY,reply);
2594*572c4311Sfengbojiang }
2595*572c4311Sfengbojiang 
2596*572c4311Sfengbojiang /* Return the reply type. */
RM_CallReplyType(RedisModuleCallReply * reply)2597*572c4311Sfengbojiang int RM_CallReplyType(RedisModuleCallReply *reply) {
2598*572c4311Sfengbojiang     if (!reply) return REDISMODULE_REPLY_UNKNOWN;
2599*572c4311Sfengbojiang     return reply->type;
2600*572c4311Sfengbojiang }
2601*572c4311Sfengbojiang 
2602*572c4311Sfengbojiang /* Return the reply type length, where applicable. */
RM_CallReplyLength(RedisModuleCallReply * reply)2603*572c4311Sfengbojiang size_t RM_CallReplyLength(RedisModuleCallReply *reply) {
2604*572c4311Sfengbojiang     moduleParseCallReply(reply);
2605*572c4311Sfengbojiang     switch(reply->type) {
2606*572c4311Sfengbojiang     case REDISMODULE_REPLY_STRING:
2607*572c4311Sfengbojiang     case REDISMODULE_REPLY_ERROR:
2608*572c4311Sfengbojiang     case REDISMODULE_REPLY_ARRAY:
2609*572c4311Sfengbojiang         return reply->len;
2610*572c4311Sfengbojiang     default:
2611*572c4311Sfengbojiang         return 0;
2612*572c4311Sfengbojiang     }
2613*572c4311Sfengbojiang }
2614*572c4311Sfengbojiang 
2615*572c4311Sfengbojiang /* Return the 'idx'-th nested call reply element of an array reply, or NULL
2616*572c4311Sfengbojiang  * if the reply type is wrong or the index is out of range. */
RM_CallReplyArrayElement(RedisModuleCallReply * reply,size_t idx)2617*572c4311Sfengbojiang RedisModuleCallReply *RM_CallReplyArrayElement(RedisModuleCallReply *reply, size_t idx) {
2618*572c4311Sfengbojiang     moduleParseCallReply(reply);
2619*572c4311Sfengbojiang     if (reply->type != REDISMODULE_REPLY_ARRAY) return NULL;
2620*572c4311Sfengbojiang     if (idx >= reply->len) return NULL;
2621*572c4311Sfengbojiang     return reply->val.array+idx;
2622*572c4311Sfengbojiang }
2623*572c4311Sfengbojiang 
2624*572c4311Sfengbojiang /* Return the long long of an integer reply. */
RM_CallReplyInteger(RedisModuleCallReply * reply)2625*572c4311Sfengbojiang long long RM_CallReplyInteger(RedisModuleCallReply *reply) {
2626*572c4311Sfengbojiang     moduleParseCallReply(reply);
2627*572c4311Sfengbojiang     if (reply->type != REDISMODULE_REPLY_INTEGER) return LLONG_MIN;
2628*572c4311Sfengbojiang     return reply->val.ll;
2629*572c4311Sfengbojiang }
2630*572c4311Sfengbojiang 
2631*572c4311Sfengbojiang /* Return the pointer and length of a string or error reply. */
RM_CallReplyStringPtr(RedisModuleCallReply * reply,size_t * len)2632*572c4311Sfengbojiang const char *RM_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *len) {
2633*572c4311Sfengbojiang     moduleParseCallReply(reply);
2634*572c4311Sfengbojiang     if (reply->type != REDISMODULE_REPLY_STRING &&
2635*572c4311Sfengbojiang         reply->type != REDISMODULE_REPLY_ERROR) return NULL;
2636*572c4311Sfengbojiang     if (len) *len = reply->len;
2637*572c4311Sfengbojiang     return reply->val.str;
2638*572c4311Sfengbojiang }
2639*572c4311Sfengbojiang 
2640*572c4311Sfengbojiang /* Return a new string object from a call reply of type string, error or
2641*572c4311Sfengbojiang  * integer. Otherwise (wrong reply type) return NULL. */
RM_CreateStringFromCallReply(RedisModuleCallReply * reply)2642*572c4311Sfengbojiang RedisModuleString *RM_CreateStringFromCallReply(RedisModuleCallReply *reply) {
2643*572c4311Sfengbojiang     moduleParseCallReply(reply);
2644*572c4311Sfengbojiang     switch(reply->type) {
2645*572c4311Sfengbojiang     case REDISMODULE_REPLY_STRING:
2646*572c4311Sfengbojiang     case REDISMODULE_REPLY_ERROR:
2647*572c4311Sfengbojiang         return RM_CreateString(reply->ctx,reply->val.str,reply->len);
2648*572c4311Sfengbojiang     case REDISMODULE_REPLY_INTEGER: {
2649*572c4311Sfengbojiang         char buf[64];
2650*572c4311Sfengbojiang         int len = ll2string(buf,sizeof(buf),reply->val.ll);
2651*572c4311Sfengbojiang         return RM_CreateString(reply->ctx,buf,len);
2652*572c4311Sfengbojiang         }
2653*572c4311Sfengbojiang     default: return NULL;
2654*572c4311Sfengbojiang     }
2655*572c4311Sfengbojiang }
2656*572c4311Sfengbojiang 
2657*572c4311Sfengbojiang /* Returns an array of robj pointers, and populates *argc with the number
2658*572c4311Sfengbojiang  * of items, by parsing the format specifier "fmt" as described for
2659*572c4311Sfengbojiang  * the RM_Call(), RM_Replicate() and other module APIs.
2660*572c4311Sfengbojiang  *
2661*572c4311Sfengbojiang  * The integer pointed by 'flags' is populated with flags according
2662*572c4311Sfengbojiang  * to special modifiers in "fmt". For now only one exists:
2663*572c4311Sfengbojiang  *
2664*572c4311Sfengbojiang  *     "!" -> REDISMODULE_ARGV_REPLICATE
2665*572c4311Sfengbojiang  *
2666*572c4311Sfengbojiang  * On error (format specifier error) NULL is returned and nothing is
2667*572c4311Sfengbojiang  * allocated. On success the argument vector is returned. */
2668*572c4311Sfengbojiang 
2669*572c4311Sfengbojiang #define REDISMODULE_ARGV_REPLICATE (1<<0)
2670*572c4311Sfengbojiang 
moduleCreateArgvFromUserFormat(const char * cmdname,const char * fmt,int * argcp,int * flags,va_list ap)2671*572c4311Sfengbojiang robj **moduleCreateArgvFromUserFormat(const char *cmdname, const char *fmt, int *argcp, int *flags, va_list ap) {
2672*572c4311Sfengbojiang     int argc = 0, argv_size, j;
2673*572c4311Sfengbojiang     robj **argv = NULL;
2674*572c4311Sfengbojiang 
2675*572c4311Sfengbojiang     /* As a first guess to avoid useless reallocations, size argv to
2676*572c4311Sfengbojiang      * hold one argument for each char specifier in 'fmt'. */
2677*572c4311Sfengbojiang     argv_size = strlen(fmt)+1; /* +1 because of the command name. */
2678*572c4311Sfengbojiang     argv = zrealloc(argv,sizeof(robj*)*argv_size);
2679*572c4311Sfengbojiang 
2680*572c4311Sfengbojiang     /* Build the arguments vector based on the format specifier. */
2681*572c4311Sfengbojiang     argv[0] = createStringObject(cmdname,strlen(cmdname));
2682*572c4311Sfengbojiang     argc++;
2683*572c4311Sfengbojiang 
2684*572c4311Sfengbojiang     /* Create the client and dispatch the command. */
2685*572c4311Sfengbojiang     const char *p = fmt;
2686*572c4311Sfengbojiang     while(*p) {
2687*572c4311Sfengbojiang         if (*p == 'c') {
2688*572c4311Sfengbojiang             char *cstr = va_arg(ap,char*);
2689*572c4311Sfengbojiang             argv[argc++] = createStringObject(cstr,strlen(cstr));
2690*572c4311Sfengbojiang         } else if (*p == 's') {
2691*572c4311Sfengbojiang             robj *obj = va_arg(ap,void*);
2692*572c4311Sfengbojiang             argv[argc++] = obj;
2693*572c4311Sfengbojiang             incrRefCount(obj);
2694*572c4311Sfengbojiang         } else if (*p == 'b') {
2695*572c4311Sfengbojiang             char *buf = va_arg(ap,char*);
2696*572c4311Sfengbojiang             size_t len = va_arg(ap,size_t);
2697*572c4311Sfengbojiang             argv[argc++] = createStringObject(buf,len);
2698*572c4311Sfengbojiang         } else if (*p == 'l') {
2699*572c4311Sfengbojiang             long ll = va_arg(ap,long long);
2700*572c4311Sfengbojiang             argv[argc++] = createObject(OBJ_STRING,sdsfromlonglong(ll));
2701*572c4311Sfengbojiang         } else if (*p == 'v') {
2702*572c4311Sfengbojiang              /* A vector of strings */
2703*572c4311Sfengbojiang              robj **v = va_arg(ap, void*);
2704*572c4311Sfengbojiang              size_t vlen = va_arg(ap, size_t);
2705*572c4311Sfengbojiang 
2706*572c4311Sfengbojiang              /* We need to grow argv to hold the vector's elements.
2707*572c4311Sfengbojiang               * We resize by vector_len-1 elements, because we held
2708*572c4311Sfengbojiang               * one element in argv for the vector already */
2709*572c4311Sfengbojiang              argv_size += vlen-1;
2710*572c4311Sfengbojiang              argv = zrealloc(argv,sizeof(robj*)*argv_size);
2711*572c4311Sfengbojiang 
2712*572c4311Sfengbojiang              size_t i = 0;
2713*572c4311Sfengbojiang              for (i = 0; i < vlen; i++) {
2714*572c4311Sfengbojiang                  incrRefCount(v[i]);
2715*572c4311Sfengbojiang                  argv[argc++] = v[i];
2716*572c4311Sfengbojiang              }
2717*572c4311Sfengbojiang         } else if (*p == '!') {
2718*572c4311Sfengbojiang             if (flags) (*flags) |= REDISMODULE_ARGV_REPLICATE;
2719*572c4311Sfengbojiang         } else {
2720*572c4311Sfengbojiang             goto fmterr;
2721*572c4311Sfengbojiang         }
2722*572c4311Sfengbojiang         p++;
2723*572c4311Sfengbojiang     }
2724*572c4311Sfengbojiang     *argcp = argc;
2725*572c4311Sfengbojiang     return argv;
2726*572c4311Sfengbojiang 
2727*572c4311Sfengbojiang fmterr:
2728*572c4311Sfengbojiang     for (j = 0; j < argc; j++)
2729*572c4311Sfengbojiang         decrRefCount(argv[j]);
2730*572c4311Sfengbojiang     zfree(argv);
2731*572c4311Sfengbojiang     return NULL;
2732*572c4311Sfengbojiang }
2733*572c4311Sfengbojiang 
2734*572c4311Sfengbojiang /* Exported API to call any Redis command from modules.
2735*572c4311Sfengbojiang  * On success a RedisModuleCallReply object is returned, otherwise
2736*572c4311Sfengbojiang  * NULL is returned and errno is set to the following values:
2737*572c4311Sfengbojiang  *
2738*572c4311Sfengbojiang  * EINVAL: command non existing, wrong arity, wrong format specifier.
2739*572c4311Sfengbojiang  * EPERM:  operation in Cluster instance with key in non local slot. */
RM_Call(RedisModuleCtx * ctx,const char * cmdname,const char * fmt,...)2740*572c4311Sfengbojiang RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
2741*572c4311Sfengbojiang     struct redisCommand *cmd;
2742*572c4311Sfengbojiang     client *c = NULL;
2743*572c4311Sfengbojiang     robj **argv = NULL;
2744*572c4311Sfengbojiang     int argc = 0, flags = 0;
2745*572c4311Sfengbojiang     va_list ap;
2746*572c4311Sfengbojiang     RedisModuleCallReply *reply = NULL;
2747*572c4311Sfengbojiang     int replicate = 0; /* Replicate this command? */
2748*572c4311Sfengbojiang 
2749*572c4311Sfengbojiang     /* Create the client and dispatch the command. */
2750*572c4311Sfengbojiang     va_start(ap, fmt);
2751*572c4311Sfengbojiang     c = createClient(-1);
2752*572c4311Sfengbojiang     argv = moduleCreateArgvFromUserFormat(cmdname,fmt,&argc,&flags,ap);
2753*572c4311Sfengbojiang     replicate = flags & REDISMODULE_ARGV_REPLICATE;
2754*572c4311Sfengbojiang     va_end(ap);
2755*572c4311Sfengbojiang 
2756*572c4311Sfengbojiang     /* Setup our fake client for command execution. */
2757*572c4311Sfengbojiang     c->flags |= CLIENT_MODULE;
2758*572c4311Sfengbojiang     c->db = ctx->client->db;
2759*572c4311Sfengbojiang     c->argv = argv;
2760*572c4311Sfengbojiang     c->argc = argc;
2761*572c4311Sfengbojiang     if (ctx->module) ctx->module->in_call++;
2762*572c4311Sfengbojiang 
2763*572c4311Sfengbojiang     /* We handle the above format error only when the client is setup so that
2764*572c4311Sfengbojiang      * we can free it normally. */
2765*572c4311Sfengbojiang     if (argv == NULL) goto cleanup;
2766*572c4311Sfengbojiang 
2767*572c4311Sfengbojiang     /* Call command filters */
2768*572c4311Sfengbojiang     moduleCallCommandFilters(c);
2769*572c4311Sfengbojiang 
2770*572c4311Sfengbojiang     /* Lookup command now, after filters had a chance to make modifications
2771*572c4311Sfengbojiang      * if necessary.
2772*572c4311Sfengbojiang      */
2773*572c4311Sfengbojiang     cmd = lookupCommand(c->argv[0]->ptr);
2774*572c4311Sfengbojiang     if (!cmd) {
2775*572c4311Sfengbojiang         errno = EINVAL;
2776*572c4311Sfengbojiang         goto cleanup;
2777*572c4311Sfengbojiang     }
2778*572c4311Sfengbojiang     c->cmd = c->lastcmd = cmd;
2779*572c4311Sfengbojiang 
2780*572c4311Sfengbojiang     /* Basic arity checks. */
2781*572c4311Sfengbojiang     if ((cmd->arity > 0 && cmd->arity != argc) || (argc < -cmd->arity)) {
2782*572c4311Sfengbojiang         errno = EINVAL;
2783*572c4311Sfengbojiang         goto cleanup;
2784*572c4311Sfengbojiang     }
2785*572c4311Sfengbojiang 
2786*572c4311Sfengbojiang     /* If this is a Redis Cluster node, we need to make sure the module is not
2787*572c4311Sfengbojiang      * trying to access non-local keys, with the exception of commands
2788*572c4311Sfengbojiang      * received from our master. */
2789*572c4311Sfengbojiang     if (server.cluster_enabled && !(ctx->client->flags & CLIENT_MASTER)) {
2790*572c4311Sfengbojiang         /* Duplicate relevant flags in the module client. */
2791*572c4311Sfengbojiang         c->flags &= ~(CLIENT_READONLY|CLIENT_ASKING);
2792*572c4311Sfengbojiang         c->flags |= ctx->client->flags & (CLIENT_READONLY|CLIENT_ASKING);
2793*572c4311Sfengbojiang         if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,NULL) !=
2794*572c4311Sfengbojiang                            server.cluster->myself)
2795*572c4311Sfengbojiang         {
2796*572c4311Sfengbojiang             errno = EPERM;
2797*572c4311Sfengbojiang             goto cleanup;
2798*572c4311Sfengbojiang         }
2799*572c4311Sfengbojiang     }
2800*572c4311Sfengbojiang 
2801*572c4311Sfengbojiang     /* If we are using single commands replication, we need to wrap what
2802*572c4311Sfengbojiang      * we propagate into a MULTI/EXEC block, so that it will be atomic like
2803*572c4311Sfengbojiang      * a Lua script in the context of AOF and slaves. */
2804*572c4311Sfengbojiang     if (replicate) moduleReplicateMultiIfNeeded(ctx);
2805*572c4311Sfengbojiang 
2806*572c4311Sfengbojiang     /* Run the command */
2807*572c4311Sfengbojiang     int call_flags = CMD_CALL_SLOWLOG | CMD_CALL_STATS;
2808*572c4311Sfengbojiang     if (replicate) {
2809*572c4311Sfengbojiang         call_flags |= CMD_CALL_PROPAGATE_AOF;
2810*572c4311Sfengbojiang         call_flags |= CMD_CALL_PROPAGATE_REPL;
2811*572c4311Sfengbojiang     }
2812*572c4311Sfengbojiang     call(c,call_flags);
2813*572c4311Sfengbojiang 
2814*572c4311Sfengbojiang     /* Convert the result of the Redis command into a suitable Lua type.
2815*572c4311Sfengbojiang      * The first thing we need is to create a single string from the client
2816*572c4311Sfengbojiang      * output buffers. */
2817*572c4311Sfengbojiang     sds proto = sdsnewlen(c->buf,c->bufpos);
2818*572c4311Sfengbojiang     c->bufpos = 0;
2819*572c4311Sfengbojiang     while(listLength(c->reply)) {
2820*572c4311Sfengbojiang         clientReplyBlock *o = listNodeValue(listFirst(c->reply));
2821*572c4311Sfengbojiang 
2822*572c4311Sfengbojiang         proto = sdscatlen(proto,o->buf,o->used);
2823*572c4311Sfengbojiang         listDelNode(c->reply,listFirst(c->reply));
2824*572c4311Sfengbojiang     }
2825*572c4311Sfengbojiang     reply = moduleCreateCallReplyFromProto(ctx,proto);
2826*572c4311Sfengbojiang     autoMemoryAdd(ctx,REDISMODULE_AM_REPLY,reply);
2827*572c4311Sfengbojiang 
2828*572c4311Sfengbojiang cleanup:
2829*572c4311Sfengbojiang     if (ctx->module) ctx->module->in_call--;
2830*572c4311Sfengbojiang     freeClient(c);
2831*572c4311Sfengbojiang     return reply;
2832*572c4311Sfengbojiang }
2833*572c4311Sfengbojiang 
2834*572c4311Sfengbojiang /* Return a pointer, and a length, to the protocol returned by the command
2835*572c4311Sfengbojiang  * that returned the reply object. */
RM_CallReplyProto(RedisModuleCallReply * reply,size_t * len)2836*572c4311Sfengbojiang const char *RM_CallReplyProto(RedisModuleCallReply *reply, size_t *len) {
2837*572c4311Sfengbojiang     if (reply->proto) *len = sdslen(reply->proto);
2838*572c4311Sfengbojiang     return reply->proto;
2839*572c4311Sfengbojiang }
2840*572c4311Sfengbojiang 
2841*572c4311Sfengbojiang /* --------------------------------------------------------------------------
2842*572c4311Sfengbojiang  * Modules data types
2843*572c4311Sfengbojiang  *
2844*572c4311Sfengbojiang  * When String DMA or using existing data structures is not enough, it is
2845*572c4311Sfengbojiang  * possible to create new data types from scratch and export them to
2846*572c4311Sfengbojiang  * Redis. The module must provide a set of callbacks for handling the
2847*572c4311Sfengbojiang  * new values exported (for example in order to provide RDB saving/loading,
2848*572c4311Sfengbojiang  * AOF rewrite, and so forth). In this section we define this API.
2849*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
2850*572c4311Sfengbojiang 
2851*572c4311Sfengbojiang /* Turn a 9 chars name in the specified charset and a 10 bit encver into
2852*572c4311Sfengbojiang  * a single 64 bit unsigned integer that represents this exact module name
2853*572c4311Sfengbojiang  * and version. This final number is called a "type ID" and is used when
2854*572c4311Sfengbojiang  * writing module exported values to RDB files, in order to re-associate the
2855*572c4311Sfengbojiang  * value to the right module to load them during RDB loading.
2856*572c4311Sfengbojiang  *
2857*572c4311Sfengbojiang  * If the string is not of the right length or the charset is wrong, or
2858*572c4311Sfengbojiang  * if encver is outside the unsigned 10 bit integer range, 0 is returned,
2859*572c4311Sfengbojiang  * otherwise the function returns the right type ID.
2860*572c4311Sfengbojiang  *
2861*572c4311Sfengbojiang  * The resulting 64 bit integer is composed as follows:
2862*572c4311Sfengbojiang  *
2863*572c4311Sfengbojiang  *     (high order bits) 6|6|6|6|6|6|6|6|6|10 (low order bits)
2864*572c4311Sfengbojiang  *
2865*572c4311Sfengbojiang  * The first 6 bits value is the first character, name[0], while the last
2866*572c4311Sfengbojiang  * 6 bits value, immediately before the 10 bits integer, is name[8].
2867*572c4311Sfengbojiang  * The last 10 bits are the encoding version.
2868*572c4311Sfengbojiang  *
2869*572c4311Sfengbojiang  * Note that a name and encver combo of "AAAAAAAAA" and 0, will produce
2870*572c4311Sfengbojiang  * zero as return value, that is the same we use to signal errors, thus
2871*572c4311Sfengbojiang  * this combination is invalid, and also useless since type names should
2872*572c4311Sfengbojiang  * try to be vary to avoid collisions. */
2873*572c4311Sfengbojiang 
2874*572c4311Sfengbojiang const char *ModuleTypeNameCharSet =
2875*572c4311Sfengbojiang              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2876*572c4311Sfengbojiang              "abcdefghijklmnopqrstuvwxyz"
2877*572c4311Sfengbojiang              "0123456789-_";
2878*572c4311Sfengbojiang 
moduleTypeEncodeId(const char * name,int encver)2879*572c4311Sfengbojiang uint64_t moduleTypeEncodeId(const char *name, int encver) {
2880*572c4311Sfengbojiang     /* We use 64 symbols so that we can map each character into 6 bits
2881*572c4311Sfengbojiang      * of the final output. */
2882*572c4311Sfengbojiang     const char *cset = ModuleTypeNameCharSet;
2883*572c4311Sfengbojiang     if (strlen(name) != 9) return 0;
2884*572c4311Sfengbojiang     if (encver < 0 || encver > 1023) return 0;
2885*572c4311Sfengbojiang 
2886*572c4311Sfengbojiang     uint64_t id = 0;
2887*572c4311Sfengbojiang     for (int j = 0; j < 9; j++) {
2888*572c4311Sfengbojiang         char *p = strchr(cset,name[j]);
2889*572c4311Sfengbojiang         if (!p) return 0;
2890*572c4311Sfengbojiang         unsigned long pos = p-cset;
2891*572c4311Sfengbojiang         id = (id << 6) | pos;
2892*572c4311Sfengbojiang     }
2893*572c4311Sfengbojiang     id = (id << 10) | encver;
2894*572c4311Sfengbojiang     return id;
2895*572c4311Sfengbojiang }
2896*572c4311Sfengbojiang 
2897*572c4311Sfengbojiang /* Search, in the list of exported data types of all the modules registered,
2898*572c4311Sfengbojiang  * a type with the same name as the one given. Returns the moduleType
2899*572c4311Sfengbojiang  * structure pointer if such a module is found, or NULL otherwise. */
moduleTypeLookupModuleByName(const char * name)2900*572c4311Sfengbojiang moduleType *moduleTypeLookupModuleByName(const char *name) {
2901*572c4311Sfengbojiang     dictIterator *di = dictGetIterator(modules);
2902*572c4311Sfengbojiang     dictEntry *de;
2903*572c4311Sfengbojiang 
2904*572c4311Sfengbojiang     while ((de = dictNext(di)) != NULL) {
2905*572c4311Sfengbojiang         struct RedisModule *module = dictGetVal(de);
2906*572c4311Sfengbojiang         listIter li;
2907*572c4311Sfengbojiang         listNode *ln;
2908*572c4311Sfengbojiang 
2909*572c4311Sfengbojiang         listRewind(module->types,&li);
2910*572c4311Sfengbojiang         while((ln = listNext(&li))) {
2911*572c4311Sfengbojiang             moduleType *mt = ln->value;
2912*572c4311Sfengbojiang             if (memcmp(name,mt->name,sizeof(mt->name)) == 0) {
2913*572c4311Sfengbojiang                 dictReleaseIterator(di);
2914*572c4311Sfengbojiang                 return mt;
2915*572c4311Sfengbojiang             }
2916*572c4311Sfengbojiang         }
2917*572c4311Sfengbojiang     }
2918*572c4311Sfengbojiang     dictReleaseIterator(di);
2919*572c4311Sfengbojiang     return NULL;
2920*572c4311Sfengbojiang }
2921*572c4311Sfengbojiang 
2922*572c4311Sfengbojiang /* Lookup a module by ID, with caching. This function is used during RDB
2923*572c4311Sfengbojiang  * loading. Modules exporting data types should never be able to unload, so
2924*572c4311Sfengbojiang  * our cache does not need to expire. */
2925*572c4311Sfengbojiang #define MODULE_LOOKUP_CACHE_SIZE 3
2926*572c4311Sfengbojiang 
moduleTypeLookupModuleByID(uint64_t id)2927*572c4311Sfengbojiang moduleType *moduleTypeLookupModuleByID(uint64_t id) {
2928*572c4311Sfengbojiang     static struct {
2929*572c4311Sfengbojiang         uint64_t id;
2930*572c4311Sfengbojiang         moduleType *mt;
2931*572c4311Sfengbojiang     } cache[MODULE_LOOKUP_CACHE_SIZE];
2932*572c4311Sfengbojiang 
2933*572c4311Sfengbojiang     /* Search in cache to start. */
2934*572c4311Sfengbojiang     int j;
2935*572c4311Sfengbojiang     for (j = 0; j < MODULE_LOOKUP_CACHE_SIZE && cache[j].mt != NULL; j++)
2936*572c4311Sfengbojiang         if (cache[j].id == id) return cache[j].mt;
2937*572c4311Sfengbojiang 
2938*572c4311Sfengbojiang     /* Slow module by module lookup. */
2939*572c4311Sfengbojiang     moduleType *mt = NULL;
2940*572c4311Sfengbojiang     dictIterator *di = dictGetIterator(modules);
2941*572c4311Sfengbojiang     dictEntry *de;
2942*572c4311Sfengbojiang 
2943*572c4311Sfengbojiang     while ((de = dictNext(di)) != NULL && mt == NULL) {
2944*572c4311Sfengbojiang         struct RedisModule *module = dictGetVal(de);
2945*572c4311Sfengbojiang         listIter li;
2946*572c4311Sfengbojiang         listNode *ln;
2947*572c4311Sfengbojiang 
2948*572c4311Sfengbojiang         listRewind(module->types,&li);
2949*572c4311Sfengbojiang         while((ln = listNext(&li))) {
2950*572c4311Sfengbojiang             moduleType *this_mt = ln->value;
2951*572c4311Sfengbojiang             /* Compare only the 54 bit module identifier and not the
2952*572c4311Sfengbojiang              * encoding version. */
2953*572c4311Sfengbojiang             if (this_mt->id >> 10 == id >> 10) {
2954*572c4311Sfengbojiang                 mt = this_mt;
2955*572c4311Sfengbojiang                 break;
2956*572c4311Sfengbojiang             }
2957*572c4311Sfengbojiang         }
2958*572c4311Sfengbojiang     }
2959*572c4311Sfengbojiang     dictReleaseIterator(di);
2960*572c4311Sfengbojiang 
2961*572c4311Sfengbojiang     /* Add to cache if possible. */
2962*572c4311Sfengbojiang     if (mt && j < MODULE_LOOKUP_CACHE_SIZE) {
2963*572c4311Sfengbojiang         cache[j].id = id;
2964*572c4311Sfengbojiang         cache[j].mt = mt;
2965*572c4311Sfengbojiang     }
2966*572c4311Sfengbojiang     return mt;
2967*572c4311Sfengbojiang }
2968*572c4311Sfengbojiang 
2969*572c4311Sfengbojiang /* Turn an (unresolved) module ID into a type name, to show the user an
2970*572c4311Sfengbojiang  * error when RDB files contain module data we can't load.
2971*572c4311Sfengbojiang  * The buffer pointed by 'name' must be 10 bytes at least. The function will
2972*572c4311Sfengbojiang  * fill it with a null terminated module name. */
moduleTypeNameByID(char * name,uint64_t moduleid)2973*572c4311Sfengbojiang void moduleTypeNameByID(char *name, uint64_t moduleid) {
2974*572c4311Sfengbojiang     const char *cset = ModuleTypeNameCharSet;
2975*572c4311Sfengbojiang 
2976*572c4311Sfengbojiang     name[9] = '\0';
2977*572c4311Sfengbojiang     char *p = name+8;
2978*572c4311Sfengbojiang     moduleid >>= 10;
2979*572c4311Sfengbojiang     for (int j = 0; j < 9; j++) {
2980*572c4311Sfengbojiang         *p-- = cset[moduleid & 63];
2981*572c4311Sfengbojiang         moduleid >>= 6;
2982*572c4311Sfengbojiang     }
2983*572c4311Sfengbojiang }
2984*572c4311Sfengbojiang 
2985*572c4311Sfengbojiang /* Register a new data type exported by the module. The parameters are the
2986*572c4311Sfengbojiang  * following. Please for in depth documentation check the modules API
2987*572c4311Sfengbojiang  * documentation, especially the TYPES.md file.
2988*572c4311Sfengbojiang  *
2989*572c4311Sfengbojiang  * * **name**: A 9 characters data type name that MUST be unique in the Redis
2990*572c4311Sfengbojiang  *   Modules ecosystem. Be creative... and there will be no collisions. Use
2991*572c4311Sfengbojiang  *   the charset A-Z a-z 9-0, plus the two "-_" characters. A good
2992*572c4311Sfengbojiang  *   idea is to use, for example `<typename>-<vendor>`. For example
2993*572c4311Sfengbojiang  *   "tree-AntZ" may mean "Tree data structure by @antirez". To use both
2994*572c4311Sfengbojiang  *   lower case and upper case letters helps in order to prevent collisions.
2995*572c4311Sfengbojiang  * * **encver**: Encoding version, which is, the version of the serialization
2996*572c4311Sfengbojiang  *   that a module used in order to persist data. As long as the "name"
2997*572c4311Sfengbojiang  *   matches, the RDB loading will be dispatched to the type callbacks
2998*572c4311Sfengbojiang  *   whatever 'encver' is used, however the module can understand if
2999*572c4311Sfengbojiang  *   the encoding it must load are of an older version of the module.
3000*572c4311Sfengbojiang  *   For example the module "tree-AntZ" initially used encver=0. Later
3001*572c4311Sfengbojiang  *   after an upgrade, it started to serialize data in a different format
3002*572c4311Sfengbojiang  *   and to register the type with encver=1. However this module may
3003*572c4311Sfengbojiang  *   still load old data produced by an older version if the rdb_load
3004*572c4311Sfengbojiang  *   callback is able to check the encver value and act accordingly.
3005*572c4311Sfengbojiang  *   The encver must be a positive value between 0 and 1023.
3006*572c4311Sfengbojiang  * * **typemethods_ptr** is a pointer to a RedisModuleTypeMethods structure
3007*572c4311Sfengbojiang  *   that should be populated with the methods callbacks and structure
3008*572c4311Sfengbojiang  *   version, like in the following example:
3009*572c4311Sfengbojiang  *
3010*572c4311Sfengbojiang  *      RedisModuleTypeMethods tm = {
3011*572c4311Sfengbojiang  *          .version = REDISMODULE_TYPE_METHOD_VERSION,
3012*572c4311Sfengbojiang  *          .rdb_load = myType_RDBLoadCallBack,
3013*572c4311Sfengbojiang  *          .rdb_save = myType_RDBSaveCallBack,
3014*572c4311Sfengbojiang  *          .aof_rewrite = myType_AOFRewriteCallBack,
3015*572c4311Sfengbojiang  *          .free = myType_FreeCallBack,
3016*572c4311Sfengbojiang  *
3017*572c4311Sfengbojiang  *          // Optional fields
3018*572c4311Sfengbojiang  *          .digest = myType_DigestCallBack,
3019*572c4311Sfengbojiang  *          .mem_usage = myType_MemUsageCallBack,
3020*572c4311Sfengbojiang  *      }
3021*572c4311Sfengbojiang  *
3022*572c4311Sfengbojiang  * * **rdb_load**: A callback function pointer that loads data from RDB files.
3023*572c4311Sfengbojiang  * * **rdb_save**: A callback function pointer that saves data to RDB files.
3024*572c4311Sfengbojiang  * * **aof_rewrite**: A callback function pointer that rewrites data as commands.
3025*572c4311Sfengbojiang  * * **digest**: A callback function pointer that is used for `DEBUG DIGEST`.
3026*572c4311Sfengbojiang  * * **free**: A callback function pointer that can free a type value.
3027*572c4311Sfengbojiang  *
3028*572c4311Sfengbojiang  * The **digest* and **mem_usage** methods should currently be omitted since
3029*572c4311Sfengbojiang  * they are not yet implemented inside the Redis modules core.
3030*572c4311Sfengbojiang  *
3031*572c4311Sfengbojiang  * Note: the module name "AAAAAAAAA" is reserved and produces an error, it
3032*572c4311Sfengbojiang  * happens to be pretty lame as well.
3033*572c4311Sfengbojiang  *
3034*572c4311Sfengbojiang  * If there is already a module registering a type with the same name,
3035*572c4311Sfengbojiang  * and if the module name or encver is invalid, NULL is returned.
3036*572c4311Sfengbojiang  * Otherwise the new type is registered into Redis, and a reference of
3037*572c4311Sfengbojiang  * type RedisModuleType is returned: the caller of the function should store
3038*572c4311Sfengbojiang  * this reference into a gobal variable to make future use of it in the
3039*572c4311Sfengbojiang  * modules type API, since a single module may register multiple types.
3040*572c4311Sfengbojiang  * Example code fragment:
3041*572c4311Sfengbojiang  *
3042*572c4311Sfengbojiang  *      static RedisModuleType *BalancedTreeType;
3043*572c4311Sfengbojiang  *
3044*572c4311Sfengbojiang  *      int RedisModule_OnLoad(RedisModuleCtx *ctx) {
3045*572c4311Sfengbojiang  *          // some code here ...
3046*572c4311Sfengbojiang  *          BalancedTreeType = RM_CreateDataType(...);
3047*572c4311Sfengbojiang  *      }
3048*572c4311Sfengbojiang  */
RM_CreateDataType(RedisModuleCtx * ctx,const char * name,int encver,void * typemethods_ptr)3049*572c4311Sfengbojiang moduleType *RM_CreateDataType(RedisModuleCtx *ctx, const char *name, int encver, void *typemethods_ptr) {
3050*572c4311Sfengbojiang     uint64_t id = moduleTypeEncodeId(name,encver);
3051*572c4311Sfengbojiang     if (id == 0) return NULL;
3052*572c4311Sfengbojiang     if (moduleTypeLookupModuleByName(name) != NULL) return NULL;
3053*572c4311Sfengbojiang 
3054*572c4311Sfengbojiang     long typemethods_version = ((long*)typemethods_ptr)[0];
3055*572c4311Sfengbojiang     if (typemethods_version == 0) return NULL;
3056*572c4311Sfengbojiang 
3057*572c4311Sfengbojiang     struct typemethods {
3058*572c4311Sfengbojiang         uint64_t version;
3059*572c4311Sfengbojiang         moduleTypeLoadFunc rdb_load;
3060*572c4311Sfengbojiang         moduleTypeSaveFunc rdb_save;
3061*572c4311Sfengbojiang         moduleTypeRewriteFunc aof_rewrite;
3062*572c4311Sfengbojiang         moduleTypeMemUsageFunc mem_usage;
3063*572c4311Sfengbojiang         moduleTypeDigestFunc digest;
3064*572c4311Sfengbojiang         moduleTypeFreeFunc free;
3065*572c4311Sfengbojiang     } *tms = (struct typemethods*) typemethods_ptr;
3066*572c4311Sfengbojiang 
3067*572c4311Sfengbojiang     moduleType *mt = zcalloc(sizeof(*mt));
3068*572c4311Sfengbojiang     mt->id = id;
3069*572c4311Sfengbojiang     mt->module = ctx->module;
3070*572c4311Sfengbojiang     mt->rdb_load = tms->rdb_load;
3071*572c4311Sfengbojiang     mt->rdb_save = tms->rdb_save;
3072*572c4311Sfengbojiang     mt->aof_rewrite = tms->aof_rewrite;
3073*572c4311Sfengbojiang     mt->mem_usage = tms->mem_usage;
3074*572c4311Sfengbojiang     mt->digest = tms->digest;
3075*572c4311Sfengbojiang     mt->free = tms->free;
3076*572c4311Sfengbojiang     memcpy(mt->name,name,sizeof(mt->name));
3077*572c4311Sfengbojiang     listAddNodeTail(ctx->module->types,mt);
3078*572c4311Sfengbojiang     return mt;
3079*572c4311Sfengbojiang }
3080*572c4311Sfengbojiang 
3081*572c4311Sfengbojiang /* If the key is open for writing, set the specified module type object
3082*572c4311Sfengbojiang  * as the value of the key, deleting the old value if any.
3083*572c4311Sfengbojiang  * On success REDISMODULE_OK is returned. If the key is not open for
3084*572c4311Sfengbojiang  * writing or there is an active iterator, REDISMODULE_ERR is returned. */
RM_ModuleTypeSetValue(RedisModuleKey * key,moduleType * mt,void * value)3085*572c4311Sfengbojiang int RM_ModuleTypeSetValue(RedisModuleKey *key, moduleType *mt, void *value) {
3086*572c4311Sfengbojiang     if (!(key->mode & REDISMODULE_WRITE) || key->iter) return REDISMODULE_ERR;
3087*572c4311Sfengbojiang     RM_DeleteKey(key);
3088*572c4311Sfengbojiang     robj *o = createModuleObject(mt,value);
3089*572c4311Sfengbojiang     setKey(key->db,key->key,o);
3090*572c4311Sfengbojiang     decrRefCount(o);
3091*572c4311Sfengbojiang     key->value = o;
3092*572c4311Sfengbojiang     return REDISMODULE_OK;
3093*572c4311Sfengbojiang }
3094*572c4311Sfengbojiang 
3095*572c4311Sfengbojiang /* Assuming RedisModule_KeyType() returned REDISMODULE_KEYTYPE_MODULE on
3096*572c4311Sfengbojiang  * the key, returns the module type pointer of the value stored at key.
3097*572c4311Sfengbojiang  *
3098*572c4311Sfengbojiang  * If the key is NULL, is not associated with a module type, or is empty,
3099*572c4311Sfengbojiang  * then NULL is returned instead. */
RM_ModuleTypeGetType(RedisModuleKey * key)3100*572c4311Sfengbojiang moduleType *RM_ModuleTypeGetType(RedisModuleKey *key) {
3101*572c4311Sfengbojiang     if (key == NULL ||
3102*572c4311Sfengbojiang         key->value == NULL ||
3103*572c4311Sfengbojiang         RM_KeyType(key) != REDISMODULE_KEYTYPE_MODULE) return NULL;
3104*572c4311Sfengbojiang     moduleValue *mv = key->value->ptr;
3105*572c4311Sfengbojiang     return mv->type;
3106*572c4311Sfengbojiang }
3107*572c4311Sfengbojiang 
3108*572c4311Sfengbojiang /* Assuming RedisModule_KeyType() returned REDISMODULE_KEYTYPE_MODULE on
3109*572c4311Sfengbojiang  * the key, returns the module type low-level value stored at key, as
3110*572c4311Sfengbojiang  * it was set by the user via RedisModule_ModuleTypeSet().
3111*572c4311Sfengbojiang  *
3112*572c4311Sfengbojiang  * If the key is NULL, is not associated with a module type, or is empty,
3113*572c4311Sfengbojiang  * then NULL is returned instead. */
RM_ModuleTypeGetValue(RedisModuleKey * key)3114*572c4311Sfengbojiang void *RM_ModuleTypeGetValue(RedisModuleKey *key) {
3115*572c4311Sfengbojiang     if (key == NULL ||
3116*572c4311Sfengbojiang         key->value == NULL ||
3117*572c4311Sfengbojiang         RM_KeyType(key) != REDISMODULE_KEYTYPE_MODULE) return NULL;
3118*572c4311Sfengbojiang     moduleValue *mv = key->value->ptr;
3119*572c4311Sfengbojiang     return mv->value;
3120*572c4311Sfengbojiang }
3121*572c4311Sfengbojiang 
3122*572c4311Sfengbojiang /* --------------------------------------------------------------------------
3123*572c4311Sfengbojiang  * RDB loading and saving functions
3124*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
3125*572c4311Sfengbojiang 
3126*572c4311Sfengbojiang /* Called when there is a load error in the context of a module. This cannot
3127*572c4311Sfengbojiang  * be recovered like for the built-in types. */
moduleRDBLoadError(RedisModuleIO * io)3128*572c4311Sfengbojiang void moduleRDBLoadError(RedisModuleIO *io) {
3129*572c4311Sfengbojiang     serverLog(LL_WARNING,
3130*572c4311Sfengbojiang         "Error loading data from RDB (short read or EOF). "
3131*572c4311Sfengbojiang         "Read performed by module '%s' about type '%s' "
3132*572c4311Sfengbojiang         "after reading '%llu' bytes of a value.",
3133*572c4311Sfengbojiang         io->type->module->name,
3134*572c4311Sfengbojiang         io->type->name,
3135*572c4311Sfengbojiang         (unsigned long long)io->bytes);
3136*572c4311Sfengbojiang     exit(1);
3137*572c4311Sfengbojiang }
3138*572c4311Sfengbojiang 
3139*572c4311Sfengbojiang /* Save an unsigned 64 bit value into the RDB file. This function should only
3140*572c4311Sfengbojiang  * be called in the context of the rdb_save method of modules implementing new
3141*572c4311Sfengbojiang  * data types. */
RM_SaveUnsigned(RedisModuleIO * io,uint64_t value)3142*572c4311Sfengbojiang void RM_SaveUnsigned(RedisModuleIO *io, uint64_t value) {
3143*572c4311Sfengbojiang     if (io->error) return;
3144*572c4311Sfengbojiang     /* Save opcode. */
3145*572c4311Sfengbojiang     int retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_UINT);
3146*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3147*572c4311Sfengbojiang     io->bytes += retval;
3148*572c4311Sfengbojiang     /* Save value. */
3149*572c4311Sfengbojiang     retval = rdbSaveLen(io->rio, value);
3150*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3151*572c4311Sfengbojiang     io->bytes += retval;
3152*572c4311Sfengbojiang     return;
3153*572c4311Sfengbojiang 
3154*572c4311Sfengbojiang saveerr:
3155*572c4311Sfengbojiang     io->error = 1;
3156*572c4311Sfengbojiang }
3157*572c4311Sfengbojiang 
3158*572c4311Sfengbojiang /* Load an unsigned 64 bit value from the RDB file. This function should only
3159*572c4311Sfengbojiang  * be called in the context of the rdb_load method of modules implementing
3160*572c4311Sfengbojiang  * new data types. */
RM_LoadUnsigned(RedisModuleIO * io)3161*572c4311Sfengbojiang uint64_t RM_LoadUnsigned(RedisModuleIO *io) {
3162*572c4311Sfengbojiang     if (io->ver == 2) {
3163*572c4311Sfengbojiang         uint64_t opcode = rdbLoadLen(io->rio,NULL);
3164*572c4311Sfengbojiang         if (opcode != RDB_MODULE_OPCODE_UINT) goto loaderr;
3165*572c4311Sfengbojiang     }
3166*572c4311Sfengbojiang     uint64_t value;
3167*572c4311Sfengbojiang     int retval = rdbLoadLenByRef(io->rio, NULL, &value);
3168*572c4311Sfengbojiang     if (retval == -1) goto loaderr;
3169*572c4311Sfengbojiang     return value;
3170*572c4311Sfengbojiang 
3171*572c4311Sfengbojiang loaderr:
3172*572c4311Sfengbojiang     moduleRDBLoadError(io);
3173*572c4311Sfengbojiang     return 0; /* Never reached. */
3174*572c4311Sfengbojiang }
3175*572c4311Sfengbojiang 
3176*572c4311Sfengbojiang /* Like RedisModule_SaveUnsigned() but for signed 64 bit values. */
RM_SaveSigned(RedisModuleIO * io,int64_t value)3177*572c4311Sfengbojiang void RM_SaveSigned(RedisModuleIO *io, int64_t value) {
3178*572c4311Sfengbojiang     union {uint64_t u; int64_t i;} conv;
3179*572c4311Sfengbojiang     conv.i = value;
3180*572c4311Sfengbojiang     RM_SaveUnsigned(io,conv.u);
3181*572c4311Sfengbojiang }
3182*572c4311Sfengbojiang 
3183*572c4311Sfengbojiang /* Like RedisModule_LoadUnsigned() but for signed 64 bit values. */
RM_LoadSigned(RedisModuleIO * io)3184*572c4311Sfengbojiang int64_t RM_LoadSigned(RedisModuleIO *io) {
3185*572c4311Sfengbojiang     union {uint64_t u; int64_t i;} conv;
3186*572c4311Sfengbojiang     conv.u = RM_LoadUnsigned(io);
3187*572c4311Sfengbojiang     return conv.i;
3188*572c4311Sfengbojiang }
3189*572c4311Sfengbojiang 
3190*572c4311Sfengbojiang /* In the context of the rdb_save method of a module type, saves a
3191*572c4311Sfengbojiang  * string into the RDB file taking as input a RedisModuleString.
3192*572c4311Sfengbojiang  *
3193*572c4311Sfengbojiang  * The string can be later loaded with RedisModule_LoadString() or
3194*572c4311Sfengbojiang  * other Load family functions expecting a serialized string inside
3195*572c4311Sfengbojiang  * the RDB file. */
RM_SaveString(RedisModuleIO * io,RedisModuleString * s)3196*572c4311Sfengbojiang void RM_SaveString(RedisModuleIO *io, RedisModuleString *s) {
3197*572c4311Sfengbojiang     if (io->error) return;
3198*572c4311Sfengbojiang     /* Save opcode. */
3199*572c4311Sfengbojiang     ssize_t retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_STRING);
3200*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3201*572c4311Sfengbojiang     io->bytes += retval;
3202*572c4311Sfengbojiang     /* Save value. */
3203*572c4311Sfengbojiang     retval = rdbSaveStringObject(io->rio, s);
3204*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3205*572c4311Sfengbojiang     io->bytes += retval;
3206*572c4311Sfengbojiang     return;
3207*572c4311Sfengbojiang 
3208*572c4311Sfengbojiang saveerr:
3209*572c4311Sfengbojiang     io->error = 1;
3210*572c4311Sfengbojiang }
3211*572c4311Sfengbojiang 
3212*572c4311Sfengbojiang /* Like RedisModule_SaveString() but takes a raw C pointer and length
3213*572c4311Sfengbojiang  * as input. */
RM_SaveStringBuffer(RedisModuleIO * io,const char * str,size_t len)3214*572c4311Sfengbojiang void RM_SaveStringBuffer(RedisModuleIO *io, const char *str, size_t len) {
3215*572c4311Sfengbojiang     if (io->error) return;
3216*572c4311Sfengbojiang     /* Save opcode. */
3217*572c4311Sfengbojiang     ssize_t retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_STRING);
3218*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3219*572c4311Sfengbojiang     io->bytes += retval;
3220*572c4311Sfengbojiang     /* Save value. */
3221*572c4311Sfengbojiang     retval = rdbSaveRawString(io->rio, (unsigned char*)str,len);
3222*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3223*572c4311Sfengbojiang     io->bytes += retval;
3224*572c4311Sfengbojiang     return;
3225*572c4311Sfengbojiang 
3226*572c4311Sfengbojiang saveerr:
3227*572c4311Sfengbojiang     io->error = 1;
3228*572c4311Sfengbojiang }
3229*572c4311Sfengbojiang 
3230*572c4311Sfengbojiang /* Implements RM_LoadString() and RM_LoadStringBuffer() */
moduleLoadString(RedisModuleIO * io,int plain,size_t * lenptr)3231*572c4311Sfengbojiang void *moduleLoadString(RedisModuleIO *io, int plain, size_t *lenptr) {
3232*572c4311Sfengbojiang     if (io->ver == 2) {
3233*572c4311Sfengbojiang         uint64_t opcode = rdbLoadLen(io->rio,NULL);
3234*572c4311Sfengbojiang         if (opcode != RDB_MODULE_OPCODE_STRING) goto loaderr;
3235*572c4311Sfengbojiang     }
3236*572c4311Sfengbojiang     void *s = rdbGenericLoadStringObject(io->rio,
3237*572c4311Sfengbojiang               plain ? RDB_LOAD_PLAIN : RDB_LOAD_NONE, lenptr);
3238*572c4311Sfengbojiang     if (s == NULL) goto loaderr;
3239*572c4311Sfengbojiang     return s;
3240*572c4311Sfengbojiang 
3241*572c4311Sfengbojiang loaderr:
3242*572c4311Sfengbojiang     moduleRDBLoadError(io);
3243*572c4311Sfengbojiang     return NULL; /* Never reached. */
3244*572c4311Sfengbojiang }
3245*572c4311Sfengbojiang 
3246*572c4311Sfengbojiang /* In the context of the rdb_load method of a module data type, loads a string
3247*572c4311Sfengbojiang  * from the RDB file, that was previously saved with RedisModule_SaveString()
3248*572c4311Sfengbojiang  * functions family.
3249*572c4311Sfengbojiang  *
3250*572c4311Sfengbojiang  * The returned string is a newly allocated RedisModuleString object, and
3251*572c4311Sfengbojiang  * the user should at some point free it with a call to RedisModule_FreeString().
3252*572c4311Sfengbojiang  *
3253*572c4311Sfengbojiang  * If the data structure does not store strings as RedisModuleString objects,
3254*572c4311Sfengbojiang  * the similar function RedisModule_LoadStringBuffer() could be used instead. */
RM_LoadString(RedisModuleIO * io)3255*572c4311Sfengbojiang RedisModuleString *RM_LoadString(RedisModuleIO *io) {
3256*572c4311Sfengbojiang     return moduleLoadString(io,0,NULL);
3257*572c4311Sfengbojiang }
3258*572c4311Sfengbojiang 
3259*572c4311Sfengbojiang /* Like RedisModule_LoadString() but returns an heap allocated string that
3260*572c4311Sfengbojiang  * was allocated with RedisModule_Alloc(), and can be resized or freed with
3261*572c4311Sfengbojiang  * RedisModule_Realloc() or RedisModule_Free().
3262*572c4311Sfengbojiang  *
3263*572c4311Sfengbojiang  * The size of the string is stored at '*lenptr' if not NULL.
3264*572c4311Sfengbojiang  * The returned string is not automatically NULL termianted, it is loaded
3265*572c4311Sfengbojiang  * exactly as it was stored inisde the RDB file. */
RM_LoadStringBuffer(RedisModuleIO * io,size_t * lenptr)3266*572c4311Sfengbojiang char *RM_LoadStringBuffer(RedisModuleIO *io, size_t *lenptr) {
3267*572c4311Sfengbojiang     return moduleLoadString(io,1,lenptr);
3268*572c4311Sfengbojiang }
3269*572c4311Sfengbojiang 
3270*572c4311Sfengbojiang /* In the context of the rdb_save method of a module data type, saves a double
3271*572c4311Sfengbojiang  * value to the RDB file. The double can be a valid number, a NaN or infinity.
3272*572c4311Sfengbojiang  * It is possible to load back the value with RedisModule_LoadDouble(). */
RM_SaveDouble(RedisModuleIO * io,double value)3273*572c4311Sfengbojiang void RM_SaveDouble(RedisModuleIO *io, double value) {
3274*572c4311Sfengbojiang     if (io->error) return;
3275*572c4311Sfengbojiang     /* Save opcode. */
3276*572c4311Sfengbojiang     int retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_DOUBLE);
3277*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3278*572c4311Sfengbojiang     io->bytes += retval;
3279*572c4311Sfengbojiang     /* Save value. */
3280*572c4311Sfengbojiang     retval = rdbSaveBinaryDoubleValue(io->rio, value);
3281*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3282*572c4311Sfengbojiang     io->bytes += retval;
3283*572c4311Sfengbojiang     return;
3284*572c4311Sfengbojiang 
3285*572c4311Sfengbojiang saveerr:
3286*572c4311Sfengbojiang     io->error = 1;
3287*572c4311Sfengbojiang }
3288*572c4311Sfengbojiang 
3289*572c4311Sfengbojiang /* In the context of the rdb_save method of a module data type, loads back the
3290*572c4311Sfengbojiang  * double value saved by RedisModule_SaveDouble(). */
RM_LoadDouble(RedisModuleIO * io)3291*572c4311Sfengbojiang double RM_LoadDouble(RedisModuleIO *io) {
3292*572c4311Sfengbojiang     if (io->ver == 2) {
3293*572c4311Sfengbojiang         uint64_t opcode = rdbLoadLen(io->rio,NULL);
3294*572c4311Sfengbojiang         if (opcode != RDB_MODULE_OPCODE_DOUBLE) goto loaderr;
3295*572c4311Sfengbojiang     }
3296*572c4311Sfengbojiang     double value;
3297*572c4311Sfengbojiang     int retval = rdbLoadBinaryDoubleValue(io->rio, &value);
3298*572c4311Sfengbojiang     if (retval == -1) goto loaderr;
3299*572c4311Sfengbojiang     return value;
3300*572c4311Sfengbojiang 
3301*572c4311Sfengbojiang loaderr:
3302*572c4311Sfengbojiang     moduleRDBLoadError(io);
3303*572c4311Sfengbojiang     return 0; /* Never reached. */
3304*572c4311Sfengbojiang }
3305*572c4311Sfengbojiang 
3306*572c4311Sfengbojiang /* In the context of the rdb_save method of a module data type, saves a float
3307*572c4311Sfengbojiang  * value to the RDB file. The float can be a valid number, a NaN or infinity.
3308*572c4311Sfengbojiang  * It is possible to load back the value with RedisModule_LoadFloat(). */
RM_SaveFloat(RedisModuleIO * io,float value)3309*572c4311Sfengbojiang void RM_SaveFloat(RedisModuleIO *io, float value) {
3310*572c4311Sfengbojiang     if (io->error) return;
3311*572c4311Sfengbojiang     /* Save opcode. */
3312*572c4311Sfengbojiang     int retval = rdbSaveLen(io->rio, RDB_MODULE_OPCODE_FLOAT);
3313*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3314*572c4311Sfengbojiang     io->bytes += retval;
3315*572c4311Sfengbojiang     /* Save value. */
3316*572c4311Sfengbojiang     retval = rdbSaveBinaryFloatValue(io->rio, value);
3317*572c4311Sfengbojiang     if (retval == -1) goto saveerr;
3318*572c4311Sfengbojiang     io->bytes += retval;
3319*572c4311Sfengbojiang     return;
3320*572c4311Sfengbojiang 
3321*572c4311Sfengbojiang saveerr:
3322*572c4311Sfengbojiang     io->error = 1;
3323*572c4311Sfengbojiang }
3324*572c4311Sfengbojiang 
3325*572c4311Sfengbojiang /* In the context of the rdb_save method of a module data type, loads back the
3326*572c4311Sfengbojiang  * float value saved by RedisModule_SaveFloat(). */
RM_LoadFloat(RedisModuleIO * io)3327*572c4311Sfengbojiang float RM_LoadFloat(RedisModuleIO *io) {
3328*572c4311Sfengbojiang     if (io->ver == 2) {
3329*572c4311Sfengbojiang         uint64_t opcode = rdbLoadLen(io->rio,NULL);
3330*572c4311Sfengbojiang         if (opcode != RDB_MODULE_OPCODE_FLOAT) goto loaderr;
3331*572c4311Sfengbojiang     }
3332*572c4311Sfengbojiang     float value;
3333*572c4311Sfengbojiang     int retval = rdbLoadBinaryFloatValue(io->rio, &value);
3334*572c4311Sfengbojiang     if (retval == -1) goto loaderr;
3335*572c4311Sfengbojiang     return value;
3336*572c4311Sfengbojiang 
3337*572c4311Sfengbojiang loaderr:
3338*572c4311Sfengbojiang     moduleRDBLoadError(io);
3339*572c4311Sfengbojiang     return 0; /* Never reached. */
3340*572c4311Sfengbojiang }
3341*572c4311Sfengbojiang 
3342*572c4311Sfengbojiang /* --------------------------------------------------------------------------
3343*572c4311Sfengbojiang  * Key digest API (DEBUG DIGEST interface for modules types)
3344*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
3345*572c4311Sfengbojiang 
3346*572c4311Sfengbojiang /* Add a new element to the digest. This function can be called multiple times
3347*572c4311Sfengbojiang  * one element after the other, for all the elements that constitute a given
3348*572c4311Sfengbojiang  * data structure. The function call must be followed by the call to
3349*572c4311Sfengbojiang  * `RedisModule_DigestEndSequence` eventually, when all the elements that are
3350*572c4311Sfengbojiang  * always in a given order are added. See the Redis Modules data types
3351*572c4311Sfengbojiang  * documentation for more info. However this is a quick example that uses Redis
3352*572c4311Sfengbojiang  * data types as an example.
3353*572c4311Sfengbojiang  *
3354*572c4311Sfengbojiang  * To add a sequence of unordered elements (for example in the case of a Redis
3355*572c4311Sfengbojiang  * Set), the pattern to use is:
3356*572c4311Sfengbojiang  *
3357*572c4311Sfengbojiang  *     foreach element {
3358*572c4311Sfengbojiang  *         AddElement(element);
3359*572c4311Sfengbojiang  *         EndSequence();
3360*572c4311Sfengbojiang  *     }
3361*572c4311Sfengbojiang  *
3362*572c4311Sfengbojiang  * Because Sets are not ordered, so every element added has a position that
3363*572c4311Sfengbojiang  * does not depend from the other. However if instead our elements are
3364*572c4311Sfengbojiang  * ordered in pairs, like field-value pairs of an Hash, then one should
3365*572c4311Sfengbojiang  * use:
3366*572c4311Sfengbojiang  *
3367*572c4311Sfengbojiang  *     foreach key,value {
3368*572c4311Sfengbojiang  *         AddElement(key);
3369*572c4311Sfengbojiang  *         AddElement(value);
3370*572c4311Sfengbojiang  *         EndSquence();
3371*572c4311Sfengbojiang  *     }
3372*572c4311Sfengbojiang  *
3373*572c4311Sfengbojiang  * Because the key and value will be always in the above order, while instead
3374*572c4311Sfengbojiang  * the single key-value pairs, can appear in any position into a Redis hash.
3375*572c4311Sfengbojiang  *
3376*572c4311Sfengbojiang  * A list of ordered elements would be implemented with:
3377*572c4311Sfengbojiang  *
3378*572c4311Sfengbojiang  *     foreach element {
3379*572c4311Sfengbojiang  *         AddElement(element);
3380*572c4311Sfengbojiang  *     }
3381*572c4311Sfengbojiang  *     EndSequence();
3382*572c4311Sfengbojiang  *
3383*572c4311Sfengbojiang  */
RM_DigestAddStringBuffer(RedisModuleDigest * md,unsigned char * ele,size_t len)3384*572c4311Sfengbojiang void RM_DigestAddStringBuffer(RedisModuleDigest *md, unsigned char *ele, size_t len) {
3385*572c4311Sfengbojiang     mixDigest(md->o,ele,len);
3386*572c4311Sfengbojiang }
3387*572c4311Sfengbojiang 
3388*572c4311Sfengbojiang /* Like `RedisModule_DigestAddStringBuffer()` but takes a long long as input
3389*572c4311Sfengbojiang  * that gets converted into a string before adding it to the digest. */
RM_DigestAddLongLong(RedisModuleDigest * md,long long ll)3390*572c4311Sfengbojiang void RM_DigestAddLongLong(RedisModuleDigest *md, long long ll) {
3391*572c4311Sfengbojiang     char buf[LONG_STR_SIZE];
3392*572c4311Sfengbojiang     size_t len = ll2string(buf,sizeof(buf),ll);
3393*572c4311Sfengbojiang     mixDigest(md->o,buf,len);
3394*572c4311Sfengbojiang }
3395*572c4311Sfengbojiang 
3396*572c4311Sfengbojiang /* See the documentation for `RedisModule_DigestAddElement()`. */
RM_DigestEndSequence(RedisModuleDigest * md)3397*572c4311Sfengbojiang void RM_DigestEndSequence(RedisModuleDigest *md) {
3398*572c4311Sfengbojiang     xorDigest(md->x,md->o,sizeof(md->o));
3399*572c4311Sfengbojiang     memset(md->o,0,sizeof(md->o));
3400*572c4311Sfengbojiang }
3401*572c4311Sfengbojiang 
3402*572c4311Sfengbojiang /* --------------------------------------------------------------------------
3403*572c4311Sfengbojiang  * AOF API for modules data types
3404*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
3405*572c4311Sfengbojiang 
3406*572c4311Sfengbojiang /* Emits a command into the AOF during the AOF rewriting process. This function
3407*572c4311Sfengbojiang  * is only called in the context of the aof_rewrite method of data types exported
3408*572c4311Sfengbojiang  * by a module. The command works exactly like RedisModule_Call() in the way
3409*572c4311Sfengbojiang  * the parameters are passed, but it does not return anything as the error
3410*572c4311Sfengbojiang  * handling is performed by Redis itself. */
RM_EmitAOF(RedisModuleIO * io,const char * cmdname,const char * fmt,...)3411*572c4311Sfengbojiang void RM_EmitAOF(RedisModuleIO *io, const char *cmdname, const char *fmt, ...) {
3412*572c4311Sfengbojiang     if (io->error) return;
3413*572c4311Sfengbojiang     struct redisCommand *cmd;
3414*572c4311Sfengbojiang     robj **argv = NULL;
3415*572c4311Sfengbojiang     int argc = 0, flags = 0, j;
3416*572c4311Sfengbojiang     va_list ap;
3417*572c4311Sfengbojiang 
3418*572c4311Sfengbojiang     cmd = lookupCommandByCString((char*)cmdname);
3419*572c4311Sfengbojiang     if (!cmd) {
3420*572c4311Sfengbojiang         serverLog(LL_WARNING,
3421*572c4311Sfengbojiang             "Fatal: AOF method for module data type '%s' tried to "
3422*572c4311Sfengbojiang             "emit unknown command '%s'",
3423*572c4311Sfengbojiang             io->type->name, cmdname);
3424*572c4311Sfengbojiang         io->error = 1;
3425*572c4311Sfengbojiang         errno = EINVAL;
3426*572c4311Sfengbojiang         return;
3427*572c4311Sfengbojiang     }
3428*572c4311Sfengbojiang 
3429*572c4311Sfengbojiang     /* Emit the arguments into the AOF in Redis protocol format. */
3430*572c4311Sfengbojiang     va_start(ap, fmt);
3431*572c4311Sfengbojiang     argv = moduleCreateArgvFromUserFormat(cmdname,fmt,&argc,&flags,ap);
3432*572c4311Sfengbojiang     va_end(ap);
3433*572c4311Sfengbojiang     if (argv == NULL) {
3434*572c4311Sfengbojiang         serverLog(LL_WARNING,
3435*572c4311Sfengbojiang             "Fatal: AOF method for module data type '%s' tried to "
3436*572c4311Sfengbojiang             "call RedisModule_EmitAOF() with wrong format specifiers '%s'",
3437*572c4311Sfengbojiang             io->type->name, fmt);
3438*572c4311Sfengbojiang         io->error = 1;
3439*572c4311Sfengbojiang         errno = EINVAL;
3440*572c4311Sfengbojiang         return;
3441*572c4311Sfengbojiang     }
3442*572c4311Sfengbojiang 
3443*572c4311Sfengbojiang     /* Bulk count. */
3444*572c4311Sfengbojiang     if (!io->error && rioWriteBulkCount(io->rio,'*',argc) == 0)
3445*572c4311Sfengbojiang         io->error = 1;
3446*572c4311Sfengbojiang 
3447*572c4311Sfengbojiang     /* Arguments. */
3448*572c4311Sfengbojiang     for (j = 0; j < argc; j++) {
3449*572c4311Sfengbojiang         if (!io->error && rioWriteBulkObject(io->rio,argv[j]) == 0)
3450*572c4311Sfengbojiang             io->error = 1;
3451*572c4311Sfengbojiang         decrRefCount(argv[j]);
3452*572c4311Sfengbojiang     }
3453*572c4311Sfengbojiang     zfree(argv);
3454*572c4311Sfengbojiang     return;
3455*572c4311Sfengbojiang }
3456*572c4311Sfengbojiang 
3457*572c4311Sfengbojiang /* --------------------------------------------------------------------------
3458*572c4311Sfengbojiang  * IO context handling
3459*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
3460*572c4311Sfengbojiang 
RM_GetContextFromIO(RedisModuleIO * io)3461*572c4311Sfengbojiang RedisModuleCtx *RM_GetContextFromIO(RedisModuleIO *io) {
3462*572c4311Sfengbojiang     if (io->ctx) return io->ctx; /* Can't have more than one... */
3463*572c4311Sfengbojiang     RedisModuleCtx ctxtemplate = REDISMODULE_CTX_INIT;
3464*572c4311Sfengbojiang     io->ctx = zmalloc(sizeof(RedisModuleCtx));
3465*572c4311Sfengbojiang     *(io->ctx) = ctxtemplate;
3466*572c4311Sfengbojiang     io->ctx->module = io->type->module;
3467*572c4311Sfengbojiang     io->ctx->client = NULL;
3468*572c4311Sfengbojiang     return io->ctx;
3469*572c4311Sfengbojiang }
3470*572c4311Sfengbojiang 
3471*572c4311Sfengbojiang /* Returns a RedisModuleString with the name of the key currently saving or
3472*572c4311Sfengbojiang  * loading, when an IO data type callback is called.  There is no guarantee
3473*572c4311Sfengbojiang  * that the key name is always available, so this may return NULL.
3474*572c4311Sfengbojiang  */
RM_GetKeyNameFromIO(RedisModuleIO * io)3475*572c4311Sfengbojiang const RedisModuleString *RM_GetKeyNameFromIO(RedisModuleIO *io) {
3476*572c4311Sfengbojiang     return io->key;
3477*572c4311Sfengbojiang }
3478*572c4311Sfengbojiang 
3479*572c4311Sfengbojiang /* --------------------------------------------------------------------------
3480*572c4311Sfengbojiang  * Logging
3481*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
3482*572c4311Sfengbojiang 
3483*572c4311Sfengbojiang /* This is the low level function implementing both:
3484*572c4311Sfengbojiang  *
3485*572c4311Sfengbojiang  *      RM_Log()
3486*572c4311Sfengbojiang  *      RM_LogIOError()
3487*572c4311Sfengbojiang  *
3488*572c4311Sfengbojiang  */
RM_LogRaw(RedisModule * module,const char * levelstr,const char * fmt,va_list ap)3489*572c4311Sfengbojiang void RM_LogRaw(RedisModule *module, const char *levelstr, const char *fmt, va_list ap) {
3490*572c4311Sfengbojiang     char msg[LOG_MAX_LEN];
3491*572c4311Sfengbojiang     size_t name_len;
3492*572c4311Sfengbojiang     int level;
3493*572c4311Sfengbojiang 
3494*572c4311Sfengbojiang     if (!strcasecmp(levelstr,"debug")) level = LL_DEBUG;
3495*572c4311Sfengbojiang     else if (!strcasecmp(levelstr,"verbose")) level = LL_VERBOSE;
3496*572c4311Sfengbojiang     else if (!strcasecmp(levelstr,"notice")) level = LL_NOTICE;
3497*572c4311Sfengbojiang     else if (!strcasecmp(levelstr,"warning")) level = LL_WARNING;
3498*572c4311Sfengbojiang     else level = LL_VERBOSE; /* Default. */
3499*572c4311Sfengbojiang 
3500*572c4311Sfengbojiang     if (level < server.verbosity) return;
3501*572c4311Sfengbojiang 
3502*572c4311Sfengbojiang     name_len = snprintf(msg, sizeof(msg),"<%s> ", module->name);
3503*572c4311Sfengbojiang     vsnprintf(msg + name_len, sizeof(msg) - name_len, fmt, ap);
3504*572c4311Sfengbojiang     serverLogRaw(level,msg);
3505*572c4311Sfengbojiang }
3506*572c4311Sfengbojiang 
3507*572c4311Sfengbojiang /* Produces a log message to the standard Redis log, the format accepts
3508*572c4311Sfengbojiang  * printf-alike specifiers, while level is a string describing the log
3509*572c4311Sfengbojiang  * level to use when emitting the log, and must be one of the following:
3510*572c4311Sfengbojiang  *
3511*572c4311Sfengbojiang  * * "debug"
3512*572c4311Sfengbojiang  * * "verbose"
3513*572c4311Sfengbojiang  * * "notice"
3514*572c4311Sfengbojiang  * * "warning"
3515*572c4311Sfengbojiang  *
3516*572c4311Sfengbojiang  * If the specified log level is invalid, verbose is used by default.
3517*572c4311Sfengbojiang  * There is a fixed limit to the length of the log line this function is able
3518*572c4311Sfengbojiang  * to emit, this limit is not specified but is guaranteed to be more than
3519*572c4311Sfengbojiang  * a few lines of text.
3520*572c4311Sfengbojiang  */
RM_Log(RedisModuleCtx * ctx,const char * levelstr,const char * fmt,...)3521*572c4311Sfengbojiang void RM_Log(RedisModuleCtx *ctx, const char *levelstr, const char *fmt, ...) {
3522*572c4311Sfengbojiang     if (!ctx->module) return;   /* Can only log if module is initialized */
3523*572c4311Sfengbojiang 
3524*572c4311Sfengbojiang     va_list ap;
3525*572c4311Sfengbojiang     va_start(ap, fmt);
3526*572c4311Sfengbojiang     RM_LogRaw(ctx->module,levelstr,fmt,ap);
3527*572c4311Sfengbojiang     va_end(ap);
3528*572c4311Sfengbojiang }
3529*572c4311Sfengbojiang 
3530*572c4311Sfengbojiang /* Log errors from RDB / AOF serialization callbacks.
3531*572c4311Sfengbojiang  *
3532*572c4311Sfengbojiang  * This function should be used when a callback is returning a critical
3533*572c4311Sfengbojiang  * error to the caller since cannot load or save the data for some
3534*572c4311Sfengbojiang  * critical reason. */
RM_LogIOError(RedisModuleIO * io,const char * levelstr,const char * fmt,...)3535*572c4311Sfengbojiang void RM_LogIOError(RedisModuleIO *io, const char *levelstr, const char *fmt, ...) {
3536*572c4311Sfengbojiang     va_list ap;
3537*572c4311Sfengbojiang     va_start(ap, fmt);
3538*572c4311Sfengbojiang     RM_LogRaw(io->type->module,levelstr,fmt,ap);
3539*572c4311Sfengbojiang     va_end(ap);
3540*572c4311Sfengbojiang }
3541*572c4311Sfengbojiang 
3542*572c4311Sfengbojiang /* --------------------------------------------------------------------------
3543*572c4311Sfengbojiang  * Blocking clients from modules
3544*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
3545*572c4311Sfengbojiang 
3546*572c4311Sfengbojiang /* Readable handler for the awake pipe. We do nothing here, the awake bytes
3547*572c4311Sfengbojiang  * will be actually read in a more appropriate place in the
3548*572c4311Sfengbojiang  * moduleHandleBlockedClients() function that is where clients are actually
3549*572c4311Sfengbojiang  * served. */
moduleBlockedClientPipeReadable(aeEventLoop * el,int fd,void * privdata,int mask)3550*572c4311Sfengbojiang void moduleBlockedClientPipeReadable(aeEventLoop *el, int fd, void *privdata, int mask) {
3551*572c4311Sfengbojiang     UNUSED(el);
3552*572c4311Sfengbojiang     UNUSED(fd);
3553*572c4311Sfengbojiang     UNUSED(mask);
3554*572c4311Sfengbojiang     UNUSED(privdata);
3555*572c4311Sfengbojiang }
3556*572c4311Sfengbojiang 
3557*572c4311Sfengbojiang /* This is called from blocked.c in order to unblock a client: may be called
3558*572c4311Sfengbojiang  * for multiple reasons while the client is in the middle of being blocked
3559*572c4311Sfengbojiang  * because the client is terminated, but is also called for cleanup when a
3560*572c4311Sfengbojiang  * client is unblocked in a clean way after replaying.
3561*572c4311Sfengbojiang  *
3562*572c4311Sfengbojiang  * What we do here is just to set the client to NULL in the redis module
3563*572c4311Sfengbojiang  * blocked client handle. This way if the client is terminated while there
3564*572c4311Sfengbojiang  * is a pending threaded operation involving the blocked client, we'll know
3565*572c4311Sfengbojiang  * that the client no longer exists and no reply callback should be called.
3566*572c4311Sfengbojiang  *
3567*572c4311Sfengbojiang  * The structure RedisModuleBlockedClient will be always deallocated when
3568*572c4311Sfengbojiang  * running the list of clients blocked by a module that need to be unblocked. */
unblockClientFromModule(client * c)3569*572c4311Sfengbojiang void unblockClientFromModule(client *c) {
3570*572c4311Sfengbojiang     RedisModuleBlockedClient *bc = c->bpop.module_blocked_handle;
3571*572c4311Sfengbojiang 
3572*572c4311Sfengbojiang     /* Call the disconnection callback if any. */
3573*572c4311Sfengbojiang     if (bc->disconnect_callback) {
3574*572c4311Sfengbojiang         RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
3575*572c4311Sfengbojiang         ctx.blocked_privdata = bc->privdata;
3576*572c4311Sfengbojiang         ctx.module = bc->module;
3577*572c4311Sfengbojiang         ctx.client = bc->client;
3578*572c4311Sfengbojiang         bc->disconnect_callback(&ctx,bc);
3579*572c4311Sfengbojiang         moduleFreeContext(&ctx);
3580*572c4311Sfengbojiang     }
3581*572c4311Sfengbojiang 
3582*572c4311Sfengbojiang     bc->client = NULL;
3583*572c4311Sfengbojiang     /* Reset the client for a new query since, for blocking commands implemented
3584*572c4311Sfengbojiang      * into modules, we do not it immediately after the command returns (and
3585*572c4311Sfengbojiang      * the client blocks) in order to be still able to access the argument
3586*572c4311Sfengbojiang      * vector from callbacks. */
3587*572c4311Sfengbojiang     resetClient(c);
3588*572c4311Sfengbojiang }
3589*572c4311Sfengbojiang 
3590*572c4311Sfengbojiang /* Block a client in the context of a blocking command, returning an handle
3591*572c4311Sfengbojiang  * which will be used, later, in order to unblock the client with a call to
3592*572c4311Sfengbojiang  * RedisModule_UnblockClient(). The arguments specify callback functions
3593*572c4311Sfengbojiang  * and a timeout after which the client is unblocked.
3594*572c4311Sfengbojiang  *
3595*572c4311Sfengbojiang  * The callbacks are called in the following contexts:
3596*572c4311Sfengbojiang  *
3597*572c4311Sfengbojiang  *     reply_callback:  called after a successful RedisModule_UnblockClient()
3598*572c4311Sfengbojiang  *                      call in order to reply to the client and unblock it.
3599*572c4311Sfengbojiang  *
3600*572c4311Sfengbojiang  *     reply_timeout:   called when the timeout is reached in order to send an
3601*572c4311Sfengbojiang  *                      error to the client.
3602*572c4311Sfengbojiang  *
3603*572c4311Sfengbojiang  *     free_privdata:   called in order to free the private data that is passed
3604*572c4311Sfengbojiang  *                      by RedisModule_UnblockClient() call.
3605*572c4311Sfengbojiang  */
RM_BlockClient(RedisModuleCtx * ctx,RedisModuleCmdFunc reply_callback,RedisModuleCmdFunc timeout_callback,void (* free_privdata)(RedisModuleCtx *,void *),long long timeout_ms)3606*572c4311Sfengbojiang RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms) {
3607*572c4311Sfengbojiang     client *c = ctx->client;
3608*572c4311Sfengbojiang     int islua = c->flags & CLIENT_LUA;
3609*572c4311Sfengbojiang     int ismulti = c->flags & CLIENT_MULTI;
3610*572c4311Sfengbojiang 
3611*572c4311Sfengbojiang     c->bpop.module_blocked_handle = zmalloc(sizeof(RedisModuleBlockedClient));
3612*572c4311Sfengbojiang     RedisModuleBlockedClient *bc = c->bpop.module_blocked_handle;
3613*572c4311Sfengbojiang 
3614*572c4311Sfengbojiang     /* We need to handle the invalid operation of calling modules blocking
3615*572c4311Sfengbojiang      * commands from Lua or MULTI. We actually create an already aborted
3616*572c4311Sfengbojiang      * (client set to NULL) blocked client handle, and actually reply with
3617*572c4311Sfengbojiang      * an error. */
3618*572c4311Sfengbojiang     bc->client = (islua || ismulti) ? NULL : c;
3619*572c4311Sfengbojiang     bc->module = ctx->module;
3620*572c4311Sfengbojiang     bc->reply_callback = reply_callback;
3621*572c4311Sfengbojiang     bc->timeout_callback = timeout_callback;
3622*572c4311Sfengbojiang     bc->disconnect_callback = NULL; /* Set by RM_SetDisconnectCallback() */
3623*572c4311Sfengbojiang     bc->free_privdata = free_privdata;
3624*572c4311Sfengbojiang     bc->privdata = NULL;
3625*572c4311Sfengbojiang     bc->reply_client = createClient(-1);
3626*572c4311Sfengbojiang     bc->reply_client->flags |= CLIENT_MODULE;
3627*572c4311Sfengbojiang     bc->dbid = c->db->id;
3628*572c4311Sfengbojiang     c->bpop.timeout = timeout_ms ? (mstime()+timeout_ms) : 0;
3629*572c4311Sfengbojiang 
3630*572c4311Sfengbojiang     if (islua || ismulti) {
3631*572c4311Sfengbojiang         c->bpop.module_blocked_handle = NULL;
3632*572c4311Sfengbojiang         addReplyError(c, islua ?
3633*572c4311Sfengbojiang             "Blocking module command called from Lua script" :
3634*572c4311Sfengbojiang             "Blocking module command called from transaction");
3635*572c4311Sfengbojiang     } else {
3636*572c4311Sfengbojiang         blockClient(c,BLOCKED_MODULE);
3637*572c4311Sfengbojiang     }
3638*572c4311Sfengbojiang     return bc;
3639*572c4311Sfengbojiang }
3640*572c4311Sfengbojiang 
3641*572c4311Sfengbojiang /* Unblock a client blocked by `RedisModule_BlockedClient`. This will trigger
3642*572c4311Sfengbojiang  * the reply callbacks to be called in order to reply to the client.
3643*572c4311Sfengbojiang  * The 'privdata' argument will be accessible by the reply callback, so
3644*572c4311Sfengbojiang  * the caller of this function can pass any value that is needed in order to
3645*572c4311Sfengbojiang  * actually reply to the client.
3646*572c4311Sfengbojiang  *
3647*572c4311Sfengbojiang  * A common usage for 'privdata' is a thread that computes something that
3648*572c4311Sfengbojiang  * needs to be passed to the client, included but not limited some slow
3649*572c4311Sfengbojiang  * to compute reply or some reply obtained via networking.
3650*572c4311Sfengbojiang  *
3651*572c4311Sfengbojiang  * Note: this function can be called from threads spawned by the module. */
RM_UnblockClient(RedisModuleBlockedClient * bc,void * privdata)3652*572c4311Sfengbojiang int RM_UnblockClient(RedisModuleBlockedClient *bc, void *privdata) {
3653*572c4311Sfengbojiang     pthread_mutex_lock(&moduleUnblockedClientsMutex);
3654*572c4311Sfengbojiang     bc->privdata = privdata;
3655*572c4311Sfengbojiang     listAddNodeTail(moduleUnblockedClients,bc);
3656*572c4311Sfengbojiang     if (write(server.module_blocked_pipe[1],"A",1) != 1) {
3657*572c4311Sfengbojiang         /* Ignore the error, this is best-effort. */
3658*572c4311Sfengbojiang     }
3659*572c4311Sfengbojiang     pthread_mutex_unlock(&moduleUnblockedClientsMutex);
3660*572c4311Sfengbojiang     return REDISMODULE_OK;
3661*572c4311Sfengbojiang }
3662*572c4311Sfengbojiang 
3663*572c4311Sfengbojiang /* Abort a blocked client blocking operation: the client will be unblocked
3664*572c4311Sfengbojiang  * without firing any callback. */
RM_AbortBlock(RedisModuleBlockedClient * bc)3665*572c4311Sfengbojiang int RM_AbortBlock(RedisModuleBlockedClient *bc) {
3666*572c4311Sfengbojiang     bc->reply_callback = NULL;
3667*572c4311Sfengbojiang     bc->disconnect_callback = NULL;
3668*572c4311Sfengbojiang     return RM_UnblockClient(bc,NULL);
3669*572c4311Sfengbojiang }
3670*572c4311Sfengbojiang 
3671*572c4311Sfengbojiang /* Set a callback that will be called if a blocked client disconnects
3672*572c4311Sfengbojiang  * before the module has a chance to call RedisModule_UnblockClient()
3673*572c4311Sfengbojiang  *
3674*572c4311Sfengbojiang  * Usually what you want to do there, is to cleanup your module state
3675*572c4311Sfengbojiang  * so that you can call RedisModule_UnblockClient() safely, otherwise
3676*572c4311Sfengbojiang  * the client will remain blocked forever if the timeout is large.
3677*572c4311Sfengbojiang  *
3678*572c4311Sfengbojiang  * Notes:
3679*572c4311Sfengbojiang  *
3680*572c4311Sfengbojiang  * 1. It is not safe to call Reply* family functions here, it is also
3681*572c4311Sfengbojiang  *    useless since the client is gone.
3682*572c4311Sfengbojiang  *
3683*572c4311Sfengbojiang  * 2. This callback is not called if the client disconnects because of
3684*572c4311Sfengbojiang  *    a timeout. In such a case, the client is unblocked automatically
3685*572c4311Sfengbojiang  *    and the timeout callback is called.
3686*572c4311Sfengbojiang  */
RM_SetDisconnectCallback(RedisModuleBlockedClient * bc,RedisModuleDisconnectFunc callback)3687*572c4311Sfengbojiang void RM_SetDisconnectCallback(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback) {
3688*572c4311Sfengbojiang     bc->disconnect_callback = callback;
3689*572c4311Sfengbojiang }
3690*572c4311Sfengbojiang 
3691*572c4311Sfengbojiang /* This function will check the moduleUnblockedClients queue in order to
3692*572c4311Sfengbojiang  * call the reply callback and really unblock the client.
3693*572c4311Sfengbojiang  *
3694*572c4311Sfengbojiang  * Clients end into this list because of calls to RM_UnblockClient(),
3695*572c4311Sfengbojiang  * however it is possible that while the module was doing work for the
3696*572c4311Sfengbojiang  * blocked client, it was terminated by Redis (for timeout or other reasons).
3697*572c4311Sfengbojiang  * When this happens the RedisModuleBlockedClient structure in the queue
3698*572c4311Sfengbojiang  * will have the 'client' field set to NULL. */
moduleHandleBlockedClients(void)3699*572c4311Sfengbojiang void moduleHandleBlockedClients(void) {
3700*572c4311Sfengbojiang     listNode *ln;
3701*572c4311Sfengbojiang     RedisModuleBlockedClient *bc;
3702*572c4311Sfengbojiang 
3703*572c4311Sfengbojiang     pthread_mutex_lock(&moduleUnblockedClientsMutex);
3704*572c4311Sfengbojiang     /* Here we unblock all the pending clients blocked in modules operations
3705*572c4311Sfengbojiang      * so we can read every pending "awake byte" in the pipe. */
3706*572c4311Sfengbojiang     char buf[1];
3707*572c4311Sfengbojiang     while (read(server.module_blocked_pipe[0],buf,1) == 1);
3708*572c4311Sfengbojiang     while (listLength(moduleUnblockedClients)) {
3709*572c4311Sfengbojiang         ln = listFirst(moduleUnblockedClients);
3710*572c4311Sfengbojiang         bc = ln->value;
3711*572c4311Sfengbojiang         client *c = bc->client;
3712*572c4311Sfengbojiang         listDelNode(moduleUnblockedClients,ln);
3713*572c4311Sfengbojiang         pthread_mutex_unlock(&moduleUnblockedClientsMutex);
3714*572c4311Sfengbojiang 
3715*572c4311Sfengbojiang         /* Release the lock during the loop, as long as we don't
3716*572c4311Sfengbojiang          * touch the shared list. */
3717*572c4311Sfengbojiang 
3718*572c4311Sfengbojiang         /* Call the reply callback if the client is valid and we have
3719*572c4311Sfengbojiang          * any callback. */
3720*572c4311Sfengbojiang         if (c && bc->reply_callback) {
3721*572c4311Sfengbojiang             RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
3722*572c4311Sfengbojiang             ctx.flags |= REDISMODULE_CTX_BLOCKED_REPLY;
3723*572c4311Sfengbojiang             ctx.blocked_privdata = bc->privdata;
3724*572c4311Sfengbojiang             ctx.module = bc->module;
3725*572c4311Sfengbojiang             ctx.client = bc->client;
3726*572c4311Sfengbojiang             ctx.blocked_client = bc;
3727*572c4311Sfengbojiang             bc->reply_callback(&ctx,(void**)c->argv,c->argc);
3728*572c4311Sfengbojiang             moduleHandlePropagationAfterCommandCallback(&ctx);
3729*572c4311Sfengbojiang             moduleFreeContext(&ctx);
3730*572c4311Sfengbojiang         }
3731*572c4311Sfengbojiang 
3732*572c4311Sfengbojiang         /* Free privdata if any. */
3733*572c4311Sfengbojiang         if (bc->privdata && bc->free_privdata) {
3734*572c4311Sfengbojiang             RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
3735*572c4311Sfengbojiang             if (c == NULL)
3736*572c4311Sfengbojiang                 ctx.flags |= REDISMODULE_CTX_BLOCKED_DISCONNECTED;
3737*572c4311Sfengbojiang             ctx.blocked_privdata = bc->privdata;
3738*572c4311Sfengbojiang             ctx.module = bc->module;
3739*572c4311Sfengbojiang             ctx.client = bc->client;
3740*572c4311Sfengbojiang             bc->free_privdata(&ctx,bc->privdata);
3741*572c4311Sfengbojiang             moduleFreeContext(&ctx);
3742*572c4311Sfengbojiang         }
3743*572c4311Sfengbojiang 
3744*572c4311Sfengbojiang         /* It is possible that this blocked client object accumulated
3745*572c4311Sfengbojiang          * replies to send to the client in a thread safe context.
3746*572c4311Sfengbojiang          * We need to glue such replies to the client output buffer and
3747*572c4311Sfengbojiang          * free the temporary client we just used for the replies. */
3748*572c4311Sfengbojiang         if (c) AddReplyFromClient(c, bc->reply_client);
3749*572c4311Sfengbojiang         freeClient(bc->reply_client);
3750*572c4311Sfengbojiang 
3751*572c4311Sfengbojiang         if (c != NULL) {
3752*572c4311Sfengbojiang             /* Before unblocking the client, set the disconnect callback
3753*572c4311Sfengbojiang              * to NULL, because if we reached this point, the client was
3754*572c4311Sfengbojiang              * properly unblocked by the module. */
3755*572c4311Sfengbojiang             bc->disconnect_callback = NULL;
3756*572c4311Sfengbojiang             unblockClient(c);
3757*572c4311Sfengbojiang             /* Put the client in the list of clients that need to write
3758*572c4311Sfengbojiang              * if there are pending replies here. This is needed since
3759*572c4311Sfengbojiang              * during a non blocking command the client may receive output. */
3760*572c4311Sfengbojiang             if (clientHasPendingReplies(c) &&
3761*572c4311Sfengbojiang                 !(c->flags & CLIENT_PENDING_WRITE))
3762*572c4311Sfengbojiang             {
3763*572c4311Sfengbojiang                 c->flags |= CLIENT_PENDING_WRITE;
3764*572c4311Sfengbojiang                 listAddNodeHead(server.clients_pending_write,c);
3765*572c4311Sfengbojiang             }
3766*572c4311Sfengbojiang         }
3767*572c4311Sfengbojiang 
3768*572c4311Sfengbojiang         /* Free 'bc' only after unblocking the client, since it is
3769*572c4311Sfengbojiang          * referenced in the client blocking context, and must be valid
3770*572c4311Sfengbojiang          * when calling unblockClient(). */
3771*572c4311Sfengbojiang         zfree(bc);
3772*572c4311Sfengbojiang 
3773*572c4311Sfengbojiang         /* Lock again before to iterate the loop. */
3774*572c4311Sfengbojiang         pthread_mutex_lock(&moduleUnblockedClientsMutex);
3775*572c4311Sfengbojiang     }
3776*572c4311Sfengbojiang     pthread_mutex_unlock(&moduleUnblockedClientsMutex);
3777*572c4311Sfengbojiang }
3778*572c4311Sfengbojiang 
3779*572c4311Sfengbojiang /* Called when our client timed out. After this function unblockClient()
3780*572c4311Sfengbojiang  * is called, and it will invalidate the blocked client. So this function
3781*572c4311Sfengbojiang  * does not need to do any cleanup. Eventually the module will call the
3782*572c4311Sfengbojiang  * API to unblock the client and the memory will be released. */
moduleBlockedClientTimedOut(client * c)3783*572c4311Sfengbojiang void moduleBlockedClientTimedOut(client *c) {
3784*572c4311Sfengbojiang     RedisModuleBlockedClient *bc = c->bpop.module_blocked_handle;
3785*572c4311Sfengbojiang     RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
3786*572c4311Sfengbojiang     ctx.flags |= REDISMODULE_CTX_BLOCKED_TIMEOUT;
3787*572c4311Sfengbojiang     ctx.module = bc->module;
3788*572c4311Sfengbojiang     ctx.client = bc->client;
3789*572c4311Sfengbojiang     ctx.blocked_client = bc;
3790*572c4311Sfengbojiang     bc->timeout_callback(&ctx,(void**)c->argv,c->argc);
3791*572c4311Sfengbojiang     moduleFreeContext(&ctx);
3792*572c4311Sfengbojiang     /* For timeout events, we do not want to call the disconnect callback,
3793*572c4311Sfengbojiang      * because the blocked client will be automatically disconnected in
3794*572c4311Sfengbojiang      * this case, and the user can still hook using the timeout callback. */
3795*572c4311Sfengbojiang     bc->disconnect_callback = NULL;
3796*572c4311Sfengbojiang }
3797*572c4311Sfengbojiang 
3798*572c4311Sfengbojiang /* Return non-zero if a module command was called in order to fill the
3799*572c4311Sfengbojiang  * reply for a blocked client. */
RM_IsBlockedReplyRequest(RedisModuleCtx * ctx)3800*572c4311Sfengbojiang int RM_IsBlockedReplyRequest(RedisModuleCtx *ctx) {
3801*572c4311Sfengbojiang     return (ctx->flags & REDISMODULE_CTX_BLOCKED_REPLY) != 0;
3802*572c4311Sfengbojiang }
3803*572c4311Sfengbojiang 
3804*572c4311Sfengbojiang /* Return non-zero if a module command was called in order to fill the
3805*572c4311Sfengbojiang  * reply for a blocked client that timed out. */
RM_IsBlockedTimeoutRequest(RedisModuleCtx * ctx)3806*572c4311Sfengbojiang int RM_IsBlockedTimeoutRequest(RedisModuleCtx *ctx) {
3807*572c4311Sfengbojiang     return (ctx->flags & REDISMODULE_CTX_BLOCKED_TIMEOUT) != 0;
3808*572c4311Sfengbojiang }
3809*572c4311Sfengbojiang 
3810*572c4311Sfengbojiang /* Get the private data set by RedisModule_UnblockClient() */
RM_GetBlockedClientPrivateData(RedisModuleCtx * ctx)3811*572c4311Sfengbojiang void *RM_GetBlockedClientPrivateData(RedisModuleCtx *ctx) {
3812*572c4311Sfengbojiang     return ctx->blocked_privdata;
3813*572c4311Sfengbojiang }
3814*572c4311Sfengbojiang 
3815*572c4311Sfengbojiang /* Get the blocked client associated with a given context.
3816*572c4311Sfengbojiang  * This is useful in the reply and timeout callbacks of blocked clients,
3817*572c4311Sfengbojiang  * before sometimes the module has the blocked client handle references
3818*572c4311Sfengbojiang  * around, and wants to cleanup it. */
RM_GetBlockedClientHandle(RedisModuleCtx * ctx)3819*572c4311Sfengbojiang RedisModuleBlockedClient *RM_GetBlockedClientHandle(RedisModuleCtx *ctx) {
3820*572c4311Sfengbojiang     return ctx->blocked_client;
3821*572c4311Sfengbojiang }
3822*572c4311Sfengbojiang 
3823*572c4311Sfengbojiang /* Return true if when the free callback of a blocked client is called,
3824*572c4311Sfengbojiang  * the reason for the client to be unblocked is that it disconnected
3825*572c4311Sfengbojiang  * while it was blocked. */
RM_BlockedClientDisconnected(RedisModuleCtx * ctx)3826*572c4311Sfengbojiang int RM_BlockedClientDisconnected(RedisModuleCtx *ctx) {
3827*572c4311Sfengbojiang     return (ctx->flags & REDISMODULE_CTX_BLOCKED_DISCONNECTED) != 0;
3828*572c4311Sfengbojiang }
3829*572c4311Sfengbojiang 
3830*572c4311Sfengbojiang /* --------------------------------------------------------------------------
3831*572c4311Sfengbojiang  * Thread Safe Contexts
3832*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
3833*572c4311Sfengbojiang 
3834*572c4311Sfengbojiang /* Return a context which can be used inside threads to make Redis context
3835*572c4311Sfengbojiang  * calls with certain modules APIs. If 'bc' is not NULL then the module will
3836*572c4311Sfengbojiang  * be bound to a blocked client, and it will be possible to use the
3837*572c4311Sfengbojiang  * `RedisModule_Reply*` family of functions to accumulate a reply for when the
3838*572c4311Sfengbojiang  * client will be unblocked. Otherwise the thread safe context will be
3839*572c4311Sfengbojiang  * detached by a specific client.
3840*572c4311Sfengbojiang  *
3841*572c4311Sfengbojiang  * To call non-reply APIs, the thread safe context must be prepared with:
3842*572c4311Sfengbojiang  *
3843*572c4311Sfengbojiang  *     RedisModule_ThreadSafeCallStart(ctx);
3844*572c4311Sfengbojiang  *     ... make your call here ...
3845*572c4311Sfengbojiang  *     RedisModule_ThreadSafeCallStop(ctx);
3846*572c4311Sfengbojiang  *
3847*572c4311Sfengbojiang  * This is not needed when using `RedisModule_Reply*` functions, assuming
3848*572c4311Sfengbojiang  * that a blocked client was used when the context was created, otherwise
3849*572c4311Sfengbojiang  * no RedisModule_Reply* call should be made at all.
3850*572c4311Sfengbojiang  *
3851*572c4311Sfengbojiang  * TODO: thread safe contexts do not inherit the blocked client
3852*572c4311Sfengbojiang  * selected database. */
RM_GetThreadSafeContext(RedisModuleBlockedClient * bc)3853*572c4311Sfengbojiang RedisModuleCtx *RM_GetThreadSafeContext(RedisModuleBlockedClient *bc) {
3854*572c4311Sfengbojiang     RedisModuleCtx *ctx = zmalloc(sizeof(*ctx));
3855*572c4311Sfengbojiang     RedisModuleCtx empty = REDISMODULE_CTX_INIT;
3856*572c4311Sfengbojiang     memcpy(ctx,&empty,sizeof(empty));
3857*572c4311Sfengbojiang     if (bc) {
3858*572c4311Sfengbojiang         ctx->blocked_client = bc;
3859*572c4311Sfengbojiang         ctx->module = bc->module;
3860*572c4311Sfengbojiang     }
3861*572c4311Sfengbojiang     ctx->flags |= REDISMODULE_CTX_THREAD_SAFE;
3862*572c4311Sfengbojiang     /* Even when the context is associated with a blocked client, we can't
3863*572c4311Sfengbojiang      * access it safely from another thread, so we create a fake client here
3864*572c4311Sfengbojiang      * in order to keep things like the currently selected database and similar
3865*572c4311Sfengbojiang      * things. */
3866*572c4311Sfengbojiang     ctx->client = createClient(-1);
3867*572c4311Sfengbojiang     if (bc) {
3868*572c4311Sfengbojiang         selectDb(ctx->client,bc->dbid);
3869*572c4311Sfengbojiang         ctx->client->id = bc->client->id;
3870*572c4311Sfengbojiang     }
3871*572c4311Sfengbojiang     return ctx;
3872*572c4311Sfengbojiang }
3873*572c4311Sfengbojiang 
3874*572c4311Sfengbojiang /* Release a thread safe context. */
RM_FreeThreadSafeContext(RedisModuleCtx * ctx)3875*572c4311Sfengbojiang void RM_FreeThreadSafeContext(RedisModuleCtx *ctx) {
3876*572c4311Sfengbojiang     moduleFreeContext(ctx);
3877*572c4311Sfengbojiang     zfree(ctx);
3878*572c4311Sfengbojiang }
3879*572c4311Sfengbojiang 
3880*572c4311Sfengbojiang /* Acquire the server lock before executing a thread safe API call.
3881*572c4311Sfengbojiang  * This is not needed for `RedisModule_Reply*` calls when there is
3882*572c4311Sfengbojiang  * a blocked client connected to the thread safe context. */
RM_ThreadSafeContextLock(RedisModuleCtx * ctx)3883*572c4311Sfengbojiang void RM_ThreadSafeContextLock(RedisModuleCtx *ctx) {
3884*572c4311Sfengbojiang     UNUSED(ctx);
3885*572c4311Sfengbojiang     moduleAcquireGIL();
3886*572c4311Sfengbojiang }
3887*572c4311Sfengbojiang 
3888*572c4311Sfengbojiang /* Release the server lock after a thread safe API call was executed. */
RM_ThreadSafeContextUnlock(RedisModuleCtx * ctx)3889*572c4311Sfengbojiang void RM_ThreadSafeContextUnlock(RedisModuleCtx *ctx) {
3890*572c4311Sfengbojiang     UNUSED(ctx);
3891*572c4311Sfengbojiang     moduleReleaseGIL();
3892*572c4311Sfengbojiang }
3893*572c4311Sfengbojiang 
moduleAcquireGIL(void)3894*572c4311Sfengbojiang void moduleAcquireGIL(void) {
3895*572c4311Sfengbojiang     pthread_mutex_lock(&moduleGIL);
3896*572c4311Sfengbojiang }
3897*572c4311Sfengbojiang 
moduleReleaseGIL(void)3898*572c4311Sfengbojiang void moduleReleaseGIL(void) {
3899*572c4311Sfengbojiang     pthread_mutex_unlock(&moduleGIL);
3900*572c4311Sfengbojiang }
3901*572c4311Sfengbojiang 
3902*572c4311Sfengbojiang 
3903*572c4311Sfengbojiang /* --------------------------------------------------------------------------
3904*572c4311Sfengbojiang  * Module Keyspace Notifications API
3905*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
3906*572c4311Sfengbojiang 
3907*572c4311Sfengbojiang /* Subscribe to keyspace notifications. This is a low-level version of the
3908*572c4311Sfengbojiang  * keyspace-notifications API. A module can register callbacks to be notified
3909*572c4311Sfengbojiang  * when keyspce events occur.
3910*572c4311Sfengbojiang  *
3911*572c4311Sfengbojiang  * Notification events are filtered by their type (string events, set events,
3912*572c4311Sfengbojiang  * etc), and the subscriber callback receives only events that match a specific
3913*572c4311Sfengbojiang  * mask of event types.
3914*572c4311Sfengbojiang  *
3915*572c4311Sfengbojiang  * When subscribing to notifications with RedisModule_SubscribeToKeyspaceEvents
3916*572c4311Sfengbojiang  * the module must provide an event type-mask, denoting the events the subscriber
3917*572c4311Sfengbojiang  * is interested in. This can be an ORed mask of any of the following flags:
3918*572c4311Sfengbojiang  *
3919*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_GENERIC: Generic commands like DEL, EXPIRE, RENAME
3920*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_STRING: String events
3921*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_LIST: List events
3922*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_SET: Set events
3923*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_HASH: Hash events
3924*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_ZSET: Sorted Set events
3925*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_EXPIRED: Expiration events
3926*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_EVICTED: Eviction events
3927*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_STREAM: Stream events
3928*572c4311Sfengbojiang  *  - REDISMODULE_NOTIFY_ALL: All events
3929*572c4311Sfengbojiang  *
3930*572c4311Sfengbojiang  * We do not distinguish between key events and keyspace events, and it is up
3931*572c4311Sfengbojiang  * to the module to filter the actions taken based on the key.
3932*572c4311Sfengbojiang  *
3933*572c4311Sfengbojiang  * The subscriber signature is:
3934*572c4311Sfengbojiang  *
3935*572c4311Sfengbojiang  *   int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type,
3936*572c4311Sfengbojiang  *                                       const char *event,
3937*572c4311Sfengbojiang  *                                       RedisModuleString *key);
3938*572c4311Sfengbojiang  *
3939*572c4311Sfengbojiang  * `type` is the event type bit, that must match the mask given at registration
3940*572c4311Sfengbojiang  * time. The event string is the actual command being executed, and key is the
3941*572c4311Sfengbojiang  * relevant Redis key.
3942*572c4311Sfengbojiang  *
3943*572c4311Sfengbojiang  * Notification callback gets executed with a redis context that can not be
3944*572c4311Sfengbojiang  * used to send anything to the client, and has the db number where the event
3945*572c4311Sfengbojiang  * occurred as its selected db number.
3946*572c4311Sfengbojiang  *
3947*572c4311Sfengbojiang  * Notice that it is not necessary to enable notifications in redis.conf for
3948*572c4311Sfengbojiang  * module notifications to work.
3949*572c4311Sfengbojiang  *
3950*572c4311Sfengbojiang  * Warning: the notification callbacks are performed in a synchronous manner,
3951*572c4311Sfengbojiang  * so notification callbacks must to be fast, or they would slow Redis down.
3952*572c4311Sfengbojiang  * If you need to take long actions, use threads to offload them.
3953*572c4311Sfengbojiang  *
3954*572c4311Sfengbojiang  * See https://redis.io/topics/notifications for more information.
3955*572c4311Sfengbojiang  */
RM_SubscribeToKeyspaceEvents(RedisModuleCtx * ctx,int types,RedisModuleNotificationFunc callback)3956*572c4311Sfengbojiang int RM_SubscribeToKeyspaceEvents(RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc callback) {
3957*572c4311Sfengbojiang     RedisModuleKeyspaceSubscriber *sub = zmalloc(sizeof(*sub));
3958*572c4311Sfengbojiang     sub->module = ctx->module;
3959*572c4311Sfengbojiang     sub->event_mask = types;
3960*572c4311Sfengbojiang     sub->notify_callback = callback;
3961*572c4311Sfengbojiang     sub->active = 0;
3962*572c4311Sfengbojiang 
3963*572c4311Sfengbojiang     listAddNodeTail(moduleKeyspaceSubscribers, sub);
3964*572c4311Sfengbojiang     return REDISMODULE_OK;
3965*572c4311Sfengbojiang }
3966*572c4311Sfengbojiang 
3967*572c4311Sfengbojiang /* Dispatcher for keyspace notifications to module subscriber functions.
3968*572c4311Sfengbojiang  * This gets called  only if at least one module requested to be notified on
3969*572c4311Sfengbojiang  * keyspace notifications */
moduleNotifyKeyspaceEvent(int type,const char * event,robj * key,int dbid)3970*572c4311Sfengbojiang void moduleNotifyKeyspaceEvent(int type, const char *event, robj *key, int dbid) {
3971*572c4311Sfengbojiang     /* Don't do anything if there aren't any subscribers */
3972*572c4311Sfengbojiang     if (listLength(moduleKeyspaceSubscribers) == 0) return;
3973*572c4311Sfengbojiang 
3974*572c4311Sfengbojiang     listIter li;
3975*572c4311Sfengbojiang     listNode *ln;
3976*572c4311Sfengbojiang     listRewind(moduleKeyspaceSubscribers,&li);
3977*572c4311Sfengbojiang 
3978*572c4311Sfengbojiang     /* Remove irrelevant flags from the type mask */
3979*572c4311Sfengbojiang     type &= ~(NOTIFY_KEYEVENT | NOTIFY_KEYSPACE);
3980*572c4311Sfengbojiang 
3981*572c4311Sfengbojiang     while((ln = listNext(&li))) {
3982*572c4311Sfengbojiang         RedisModuleKeyspaceSubscriber *sub = ln->value;
3983*572c4311Sfengbojiang         /* Only notify subscribers on events matching they registration,
3984*572c4311Sfengbojiang          * and avoid subscribers triggering themselves */
3985*572c4311Sfengbojiang         if ((sub->event_mask & type) && sub->active == 0) {
3986*572c4311Sfengbojiang             RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
3987*572c4311Sfengbojiang             ctx.module = sub->module;
3988*572c4311Sfengbojiang             ctx.client = moduleFreeContextReusedClient;
3989*572c4311Sfengbojiang             selectDb(ctx.client, dbid);
3990*572c4311Sfengbojiang 
3991*572c4311Sfengbojiang             /* mark the handler as active to avoid reentrant loops.
3992*572c4311Sfengbojiang              * If the subscriber performs an action triggering itself,
3993*572c4311Sfengbojiang              * it will not be notified about it. */
3994*572c4311Sfengbojiang             sub->active = 1;
3995*572c4311Sfengbojiang             sub->notify_callback(&ctx, type, event, key);
3996*572c4311Sfengbojiang             sub->active = 0;
3997*572c4311Sfengbojiang             moduleFreeContext(&ctx);
3998*572c4311Sfengbojiang         }
3999*572c4311Sfengbojiang     }
4000*572c4311Sfengbojiang }
4001*572c4311Sfengbojiang 
4002*572c4311Sfengbojiang /* Unsubscribe any notification subscribers this module has upon unloading */
moduleUnsubscribeNotifications(RedisModule * module)4003*572c4311Sfengbojiang void moduleUnsubscribeNotifications(RedisModule *module) {
4004*572c4311Sfengbojiang     listIter li;
4005*572c4311Sfengbojiang     listNode *ln;
4006*572c4311Sfengbojiang     listRewind(moduleKeyspaceSubscribers,&li);
4007*572c4311Sfengbojiang     while((ln = listNext(&li))) {
4008*572c4311Sfengbojiang         RedisModuleKeyspaceSubscriber *sub = ln->value;
4009*572c4311Sfengbojiang         if (sub->module == module) {
4010*572c4311Sfengbojiang             listDelNode(moduleKeyspaceSubscribers, ln);
4011*572c4311Sfengbojiang             zfree(sub);
4012*572c4311Sfengbojiang         }
4013*572c4311Sfengbojiang     }
4014*572c4311Sfengbojiang }
4015*572c4311Sfengbojiang 
4016*572c4311Sfengbojiang /* --------------------------------------------------------------------------
4017*572c4311Sfengbojiang  * Modules Cluster API
4018*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
4019*572c4311Sfengbojiang 
4020*572c4311Sfengbojiang /* The Cluster message callback function pointer type. */
4021*572c4311Sfengbojiang typedef void (*RedisModuleClusterMessageReceiver)(RedisModuleCtx *ctx, const char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len);
4022*572c4311Sfengbojiang 
4023*572c4311Sfengbojiang /* This structure identifies a registered caller: it must match a given module
4024*572c4311Sfengbojiang  * ID, for a given message type. The callback function is just the function
4025*572c4311Sfengbojiang  * that was registered as receiver. */
4026*572c4311Sfengbojiang typedef struct moduleClusterReceiver {
4027*572c4311Sfengbojiang     uint64_t module_id;
4028*572c4311Sfengbojiang     RedisModuleClusterMessageReceiver callback;
4029*572c4311Sfengbojiang     struct RedisModule *module;
4030*572c4311Sfengbojiang     struct moduleClusterReceiver *next;
4031*572c4311Sfengbojiang } moduleClusterReceiver;
4032*572c4311Sfengbojiang 
4033*572c4311Sfengbojiang typedef struct moduleClusterNodeInfo {
4034*572c4311Sfengbojiang     int flags;
4035*572c4311Sfengbojiang     char ip[NET_IP_STR_LEN];
4036*572c4311Sfengbojiang     int port;
4037*572c4311Sfengbojiang     char master_id[40]; /* Only if flags & REDISMODULE_NODE_MASTER is true. */
4038*572c4311Sfengbojiang } mdouleClusterNodeInfo;
4039*572c4311Sfengbojiang 
4040*572c4311Sfengbojiang /* We have an array of message types: each bucket is a linked list of
4041*572c4311Sfengbojiang  * configured receivers. */
4042*572c4311Sfengbojiang static moduleClusterReceiver *clusterReceivers[UINT8_MAX];
4043*572c4311Sfengbojiang 
4044*572c4311Sfengbojiang /* Dispatch the message to the right module receiver. */
moduleCallClusterReceivers(const char * sender_id,uint64_t module_id,uint8_t type,const unsigned char * payload,uint32_t len)4045*572c4311Sfengbojiang void moduleCallClusterReceivers(const char *sender_id, uint64_t module_id, uint8_t type, const unsigned char *payload, uint32_t len) {
4046*572c4311Sfengbojiang     moduleClusterReceiver *r = clusterReceivers[type];
4047*572c4311Sfengbojiang     while(r) {
4048*572c4311Sfengbojiang         if (r->module_id == module_id) {
4049*572c4311Sfengbojiang             RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
4050*572c4311Sfengbojiang             ctx.module = r->module;
4051*572c4311Sfengbojiang             ctx.client = moduleFreeContextReusedClient;
4052*572c4311Sfengbojiang             selectDb(ctx.client, 0);
4053*572c4311Sfengbojiang             r->callback(&ctx,sender_id,type,payload,len);
4054*572c4311Sfengbojiang             moduleFreeContext(&ctx);
4055*572c4311Sfengbojiang             return;
4056*572c4311Sfengbojiang         }
4057*572c4311Sfengbojiang         r = r->next;
4058*572c4311Sfengbojiang     }
4059*572c4311Sfengbojiang }
4060*572c4311Sfengbojiang 
4061*572c4311Sfengbojiang /* Register a callback receiver for cluster messages of type 'type'. If there
4062*572c4311Sfengbojiang  * was already a registered callback, this will replace the callback function
4063*572c4311Sfengbojiang  * with the one provided, otherwise if the callback is set to NULL and there
4064*572c4311Sfengbojiang  * is already a callback for this function, the callback is unregistered
4065*572c4311Sfengbojiang  * (so this API call is also used in order to delete the receiver). */
RM_RegisterClusterMessageReceiver(RedisModuleCtx * ctx,uint8_t type,RedisModuleClusterMessageReceiver callback)4066*572c4311Sfengbojiang void RM_RegisterClusterMessageReceiver(RedisModuleCtx *ctx, uint8_t type, RedisModuleClusterMessageReceiver callback) {
4067*572c4311Sfengbojiang     if (!server.cluster_enabled) return;
4068*572c4311Sfengbojiang 
4069*572c4311Sfengbojiang     uint64_t module_id = moduleTypeEncodeId(ctx->module->name,0);
4070*572c4311Sfengbojiang     moduleClusterReceiver *r = clusterReceivers[type], *prev = NULL;
4071*572c4311Sfengbojiang     while(r) {
4072*572c4311Sfengbojiang         if (r->module_id == module_id) {
4073*572c4311Sfengbojiang             /* Found! Set or delete. */
4074*572c4311Sfengbojiang             if (callback) {
4075*572c4311Sfengbojiang                 r->callback = callback;
4076*572c4311Sfengbojiang             } else {
4077*572c4311Sfengbojiang                 /* Delete the receiver entry if the user is setting
4078*572c4311Sfengbojiang                  * it to NULL. Just unlink the receiver node from the
4079*572c4311Sfengbojiang                  * linked list. */
4080*572c4311Sfengbojiang                 if (prev)
4081*572c4311Sfengbojiang                     prev->next = r->next;
4082*572c4311Sfengbojiang                 else
4083*572c4311Sfengbojiang                     clusterReceivers[type]->next = r->next;
4084*572c4311Sfengbojiang                 zfree(r);
4085*572c4311Sfengbojiang             }
4086*572c4311Sfengbojiang             return;
4087*572c4311Sfengbojiang         }
4088*572c4311Sfengbojiang         prev = r;
4089*572c4311Sfengbojiang         r = r->next;
4090*572c4311Sfengbojiang     }
4091*572c4311Sfengbojiang 
4092*572c4311Sfengbojiang     /* Not found, let's add it. */
4093*572c4311Sfengbojiang     if (callback) {
4094*572c4311Sfengbojiang         r = zmalloc(sizeof(*r));
4095*572c4311Sfengbojiang         r->module_id = module_id;
4096*572c4311Sfengbojiang         r->module = ctx->module;
4097*572c4311Sfengbojiang         r->callback = callback;
4098*572c4311Sfengbojiang         r->next = clusterReceivers[type];
4099*572c4311Sfengbojiang         clusterReceivers[type] = r;
4100*572c4311Sfengbojiang     }
4101*572c4311Sfengbojiang }
4102*572c4311Sfengbojiang 
4103*572c4311Sfengbojiang /* Send a message to all the nodes in the cluster if `target` is NULL, otherwise
4104*572c4311Sfengbojiang  * at the specified target, which is a REDISMODULE_NODE_ID_LEN bytes node ID, as
4105*572c4311Sfengbojiang  * returned by the receiver callback or by the nodes iteration functions.
4106*572c4311Sfengbojiang  *
4107*572c4311Sfengbojiang  * The function returns REDISMODULE_OK if the message was successfully sent,
4108*572c4311Sfengbojiang  * otherwise if the node is not connected or such node ID does not map to any
4109*572c4311Sfengbojiang  * known cluster node, REDISMODULE_ERR is returned. */
RM_SendClusterMessage(RedisModuleCtx * ctx,char * target_id,uint8_t type,unsigned char * msg,uint32_t len)4110*572c4311Sfengbojiang int RM_SendClusterMessage(RedisModuleCtx *ctx, char *target_id, uint8_t type, unsigned char *msg, uint32_t len) {
4111*572c4311Sfengbojiang     if (!server.cluster_enabled) return REDISMODULE_ERR;
4112*572c4311Sfengbojiang     uint64_t module_id = moduleTypeEncodeId(ctx->module->name,0);
4113*572c4311Sfengbojiang     if (clusterSendModuleMessageToTarget(target_id,module_id,type,msg,len) == C_OK)
4114*572c4311Sfengbojiang         return REDISMODULE_OK;
4115*572c4311Sfengbojiang     else
4116*572c4311Sfengbojiang         return REDISMODULE_ERR;
4117*572c4311Sfengbojiang }
4118*572c4311Sfengbojiang 
4119*572c4311Sfengbojiang /* Return an array of string pointers, each string pointer points to a cluster
4120*572c4311Sfengbojiang  * node ID of exactly REDISMODULE_NODE_ID_SIZE bytes (without any null term).
4121*572c4311Sfengbojiang  * The number of returned node IDs is stored into `*numnodes`.
4122*572c4311Sfengbojiang  * However if this function is called by a module not running an a Redis
4123*572c4311Sfengbojiang  * instance with Redis Cluster enabled, NULL is returned instead.
4124*572c4311Sfengbojiang  *
4125*572c4311Sfengbojiang  * The IDs returned can be used with RedisModule_GetClusterNodeInfo() in order
4126*572c4311Sfengbojiang  * to get more information about single nodes.
4127*572c4311Sfengbojiang  *
4128*572c4311Sfengbojiang  * The array returned by this function must be freed using the function
4129*572c4311Sfengbojiang  * RedisModule_FreeClusterNodesList().
4130*572c4311Sfengbojiang  *
4131*572c4311Sfengbojiang  * Example:
4132*572c4311Sfengbojiang  *
4133*572c4311Sfengbojiang  *     size_t count, j;
4134*572c4311Sfengbojiang  *     char **ids = RedisModule_GetClusterNodesList(ctx,&count);
4135*572c4311Sfengbojiang  *     for (j = 0; j < count; j++) {
4136*572c4311Sfengbojiang  *         RedisModule_Log("notice","Node %.*s",
4137*572c4311Sfengbojiang  *             REDISMODULE_NODE_ID_LEN,ids[j]);
4138*572c4311Sfengbojiang  *     }
4139*572c4311Sfengbojiang  *     RedisModule_FreeClusterNodesList(ids);
4140*572c4311Sfengbojiang  */
RM_GetClusterNodesList(RedisModuleCtx * ctx,size_t * numnodes)4141*572c4311Sfengbojiang char **RM_GetClusterNodesList(RedisModuleCtx *ctx, size_t *numnodes) {
4142*572c4311Sfengbojiang     UNUSED(ctx);
4143*572c4311Sfengbojiang 
4144*572c4311Sfengbojiang     if (!server.cluster_enabled) return NULL;
4145*572c4311Sfengbojiang     size_t count = dictSize(server.cluster->nodes);
4146*572c4311Sfengbojiang     char **ids = zmalloc((count+1)*REDISMODULE_NODE_ID_LEN);
4147*572c4311Sfengbojiang     dictIterator *di = dictGetIterator(server.cluster->nodes);
4148*572c4311Sfengbojiang     dictEntry *de;
4149*572c4311Sfengbojiang     int j = 0;
4150*572c4311Sfengbojiang     while((de = dictNext(di)) != NULL) {
4151*572c4311Sfengbojiang         clusterNode *node = dictGetVal(de);
4152*572c4311Sfengbojiang         if (node->flags & (CLUSTER_NODE_NOADDR|CLUSTER_NODE_HANDSHAKE)) continue;
4153*572c4311Sfengbojiang         ids[j] = zmalloc(REDISMODULE_NODE_ID_LEN);
4154*572c4311Sfengbojiang         memcpy(ids[j],node->name,REDISMODULE_NODE_ID_LEN);
4155*572c4311Sfengbojiang         j++;
4156*572c4311Sfengbojiang     }
4157*572c4311Sfengbojiang     *numnodes = j;
4158*572c4311Sfengbojiang     ids[j] = NULL; /* Null term so that FreeClusterNodesList does not need
4159*572c4311Sfengbojiang                     * to also get the count argument. */
4160*572c4311Sfengbojiang     dictReleaseIterator(di);
4161*572c4311Sfengbojiang     return ids;
4162*572c4311Sfengbojiang }
4163*572c4311Sfengbojiang 
4164*572c4311Sfengbojiang /* Free the node list obtained with RedisModule_GetClusterNodesList. */
RM_FreeClusterNodesList(char ** ids)4165*572c4311Sfengbojiang void RM_FreeClusterNodesList(char **ids) {
4166*572c4311Sfengbojiang     if (ids == NULL) return;
4167*572c4311Sfengbojiang     for (int j = 0; ids[j]; j++) zfree(ids[j]);
4168*572c4311Sfengbojiang     zfree(ids);
4169*572c4311Sfengbojiang }
4170*572c4311Sfengbojiang 
4171*572c4311Sfengbojiang /* Return this node ID (REDISMODULE_CLUSTER_ID_LEN bytes) or NULL if the cluster
4172*572c4311Sfengbojiang  * is disabled. */
RM_GetMyClusterID(void)4173*572c4311Sfengbojiang const char *RM_GetMyClusterID(void) {
4174*572c4311Sfengbojiang     if (!server.cluster_enabled) return NULL;
4175*572c4311Sfengbojiang     return server.cluster->myself->name;
4176*572c4311Sfengbojiang }
4177*572c4311Sfengbojiang 
4178*572c4311Sfengbojiang /* Return the number of nodes in the cluster, regardless of their state
4179*572c4311Sfengbojiang  * (handshake, noaddress, ...) so that the number of active nodes may actually
4180*572c4311Sfengbojiang  * be smaller, but not greater than this number. If the instance is not in
4181*572c4311Sfengbojiang  * cluster mode, zero is returned. */
RM_GetClusterSize(void)4182*572c4311Sfengbojiang size_t RM_GetClusterSize(void) {
4183*572c4311Sfengbojiang     if (!server.cluster_enabled) return 0;
4184*572c4311Sfengbojiang     return dictSize(server.cluster->nodes);
4185*572c4311Sfengbojiang }
4186*572c4311Sfengbojiang 
4187*572c4311Sfengbojiang /* Populate the specified info for the node having as ID the specified 'id',
4188*572c4311Sfengbojiang  * then returns REDISMODULE_OK. Otherwise if the node ID does not exist from
4189*572c4311Sfengbojiang  * the POV of this local node, REDISMODULE_ERR is returned.
4190*572c4311Sfengbojiang  *
4191*572c4311Sfengbojiang  * The arguments ip, master_id, port and flags can be NULL in case we don't
4192*572c4311Sfengbojiang  * need to populate back certain info. If an ip and master_id (only populated
4193*572c4311Sfengbojiang  * if the instance is a slave) are specified, they point to buffers holding
4194*572c4311Sfengbojiang  * at least REDISMODULE_NODE_ID_LEN bytes. The strings written back as ip
4195*572c4311Sfengbojiang  * and master_id are not null terminated.
4196*572c4311Sfengbojiang  *
4197*572c4311Sfengbojiang  * The list of flags reported is the following:
4198*572c4311Sfengbojiang  *
4199*572c4311Sfengbojiang  * * REDISMODULE_NODE_MYSELF        This node
4200*572c4311Sfengbojiang  * * REDISMODULE_NODE_MASTER        The node is a master
4201*572c4311Sfengbojiang  * * REDISMODULE_NODE_SLAVE         The node is a replica
4202*572c4311Sfengbojiang  * * REDISMODULE_NODE_PFAIL         We see the node as failing
4203*572c4311Sfengbojiang  * * REDISMODULE_NODE_FAIL          The cluster agrees the node is failing
4204*572c4311Sfengbojiang  * * REDISMODULE_NODE_NOFAILOVER    The slave is configured to never failover
4205*572c4311Sfengbojiang  */
4206*572c4311Sfengbojiang 
4207*572c4311Sfengbojiang clusterNode *clusterLookupNode(const char *name); /* We need access to internals */
4208*572c4311Sfengbojiang 
RM_GetClusterNodeInfo(RedisModuleCtx * ctx,const char * id,char * ip,char * master_id,int * port,int * flags)4209*572c4311Sfengbojiang int RM_GetClusterNodeInfo(RedisModuleCtx *ctx, const char *id, char *ip, char *master_id, int *port, int *flags) {
4210*572c4311Sfengbojiang     UNUSED(ctx);
4211*572c4311Sfengbojiang 
4212*572c4311Sfengbojiang     clusterNode *node = clusterLookupNode(id);
4213*572c4311Sfengbojiang     if (node->flags & (CLUSTER_NODE_NOADDR|CLUSTER_NODE_HANDSHAKE))
4214*572c4311Sfengbojiang         return REDISMODULE_ERR;
4215*572c4311Sfengbojiang 
4216*572c4311Sfengbojiang     if (ip) memcpy(ip,node->name,REDISMODULE_NODE_ID_LEN);
4217*572c4311Sfengbojiang 
4218*572c4311Sfengbojiang     if (master_id) {
4219*572c4311Sfengbojiang         /* If the information is not available, the function will set the
4220*572c4311Sfengbojiang          * field to zero bytes, so that when the field can't be populated the
4221*572c4311Sfengbojiang          * function kinda remains predictable. */
4222*572c4311Sfengbojiang         if (node->flags & CLUSTER_NODE_MASTER && node->slaveof)
4223*572c4311Sfengbojiang             memcpy(master_id,node->slaveof->name,REDISMODULE_NODE_ID_LEN);
4224*572c4311Sfengbojiang         else
4225*572c4311Sfengbojiang             memset(master_id,0,REDISMODULE_NODE_ID_LEN);
4226*572c4311Sfengbojiang     }
4227*572c4311Sfengbojiang     if (port) *port = node->port;
4228*572c4311Sfengbojiang 
4229*572c4311Sfengbojiang     /* As usually we have to remap flags for modules, in order to ensure
4230*572c4311Sfengbojiang      * we can provide binary compatibility. */
4231*572c4311Sfengbojiang     if (flags) {
4232*572c4311Sfengbojiang         *flags = 0;
4233*572c4311Sfengbojiang         if (node->flags & CLUSTER_NODE_MYSELF) *flags |= REDISMODULE_NODE_MYSELF;
4234*572c4311Sfengbojiang         if (node->flags & CLUSTER_NODE_MASTER) *flags |= REDISMODULE_NODE_MASTER;
4235*572c4311Sfengbojiang         if (node->flags & CLUSTER_NODE_SLAVE) *flags |= REDISMODULE_NODE_SLAVE;
4236*572c4311Sfengbojiang         if (node->flags & CLUSTER_NODE_PFAIL) *flags |= REDISMODULE_NODE_PFAIL;
4237*572c4311Sfengbojiang         if (node->flags & CLUSTER_NODE_FAIL) *flags |= REDISMODULE_NODE_FAIL;
4238*572c4311Sfengbojiang         if (node->flags & CLUSTER_NODE_NOFAILOVER) *flags |= REDISMODULE_NODE_NOFAILOVER;
4239*572c4311Sfengbojiang     }
4240*572c4311Sfengbojiang     return REDISMODULE_OK;
4241*572c4311Sfengbojiang }
4242*572c4311Sfengbojiang 
4243*572c4311Sfengbojiang /* Set Redis Cluster flags in order to change the normal behavior of
4244*572c4311Sfengbojiang  * Redis Cluster, especially with the goal of disabling certain functions.
4245*572c4311Sfengbojiang  * This is useful for modules that use the Cluster API in order to create
4246*572c4311Sfengbojiang  * a different distributed system, but still want to use the Redis Cluster
4247*572c4311Sfengbojiang  * message bus. Flags that can be set:
4248*572c4311Sfengbojiang  *
4249*572c4311Sfengbojiang  *  CLUSTER_MODULE_FLAG_NO_FAILOVER
4250*572c4311Sfengbojiang  *  CLUSTER_MODULE_FLAG_NO_REDIRECTION
4251*572c4311Sfengbojiang  *
4252*572c4311Sfengbojiang  * With the following effects:
4253*572c4311Sfengbojiang  *
4254*572c4311Sfengbojiang  *  NO_FAILOVER: prevent Redis Cluster slaves to failover a failing master.
4255*572c4311Sfengbojiang  *               Also disables the replica migration feature.
4256*572c4311Sfengbojiang  *
4257*572c4311Sfengbojiang  *  NO_REDIRECTION: Every node will accept any key, without trying to perform
4258*572c4311Sfengbojiang  *                  partitioning according to the user Redis Cluster algorithm.
4259*572c4311Sfengbojiang  *                  Slots informations will still be propagated across the
4260*572c4311Sfengbojiang  *                  cluster, but without effects. */
RM_SetClusterFlags(RedisModuleCtx * ctx,uint64_t flags)4261*572c4311Sfengbojiang void RM_SetClusterFlags(RedisModuleCtx *ctx, uint64_t flags) {
4262*572c4311Sfengbojiang     UNUSED(ctx);
4263*572c4311Sfengbojiang     if (flags & REDISMODULE_CLUSTER_FLAG_NO_FAILOVER)
4264*572c4311Sfengbojiang         server.cluster_module_flags |= CLUSTER_MODULE_FLAG_NO_FAILOVER;
4265*572c4311Sfengbojiang     if (flags & REDISMODULE_CLUSTER_FLAG_NO_REDIRECTION)
4266*572c4311Sfengbojiang         server.cluster_module_flags |= CLUSTER_MODULE_FLAG_NO_REDIRECTION;
4267*572c4311Sfengbojiang }
4268*572c4311Sfengbojiang 
4269*572c4311Sfengbojiang /* --------------------------------------------------------------------------
4270*572c4311Sfengbojiang  * Modules Timers API
4271*572c4311Sfengbojiang  *
4272*572c4311Sfengbojiang  * Module timers are an high precision "green timers" abstraction where
4273*572c4311Sfengbojiang  * every module can register even millions of timers without problems, even if
4274*572c4311Sfengbojiang  * the actual event loop will just have a single timer that is used to awake the
4275*572c4311Sfengbojiang  * module timers subsystem in order to process the next event.
4276*572c4311Sfengbojiang  *
4277*572c4311Sfengbojiang  * All the timers are stored into a radix tree, ordered by expire time, when
4278*572c4311Sfengbojiang  * the main Redis event loop timer callback is called, we try to process all
4279*572c4311Sfengbojiang  * the timers already expired one after the other. Then we re-enter the event
4280*572c4311Sfengbojiang  * loop registering a timer that will expire when the next to process module
4281*572c4311Sfengbojiang  * timer will expire.
4282*572c4311Sfengbojiang  *
4283*572c4311Sfengbojiang  * Every time the list of active timers drops to zero, we unregister the
4284*572c4311Sfengbojiang  * main event loop timer, so that there is no overhead when such feature is
4285*572c4311Sfengbojiang  * not used.
4286*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
4287*572c4311Sfengbojiang 
4288*572c4311Sfengbojiang static rax *Timers;     /* The radix tree of all the timers sorted by expire. */
4289*572c4311Sfengbojiang long long aeTimer = -1; /* Main event loop (ae.c) timer identifier. */
4290*572c4311Sfengbojiang 
4291*572c4311Sfengbojiang typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data);
4292*572c4311Sfengbojiang 
4293*572c4311Sfengbojiang /* The timer descriptor, stored as value in the radix tree. */
4294*572c4311Sfengbojiang typedef struct RedisModuleTimer {
4295*572c4311Sfengbojiang     RedisModule *module;                /* Module reference. */
4296*572c4311Sfengbojiang     RedisModuleTimerProc callback;      /* The callback to invoke on expire. */
4297*572c4311Sfengbojiang     void *data;                         /* Private data for the callback. */
4298*572c4311Sfengbojiang     int dbid;                           /* Database number selected by the original client. */
4299*572c4311Sfengbojiang } RedisModuleTimer;
4300*572c4311Sfengbojiang 
4301*572c4311Sfengbojiang /* This is the timer handler that is called by the main event loop. We schedule
4302*572c4311Sfengbojiang  * this timer to be called when the nearest of our module timers will expire. */
moduleTimerHandler(struct aeEventLoop * eventLoop,long long id,void * clientData)4303*572c4311Sfengbojiang int moduleTimerHandler(struct aeEventLoop *eventLoop, long long id, void *clientData) {
4304*572c4311Sfengbojiang     UNUSED(eventLoop);
4305*572c4311Sfengbojiang     UNUSED(id);
4306*572c4311Sfengbojiang     UNUSED(clientData);
4307*572c4311Sfengbojiang 
4308*572c4311Sfengbojiang     /* To start let's try to fire all the timers already expired. */
4309*572c4311Sfengbojiang     raxIterator ri;
4310*572c4311Sfengbojiang     raxStart(&ri,Timers);
4311*572c4311Sfengbojiang     uint64_t now = ustime();
4312*572c4311Sfengbojiang     long long next_period = 0;
4313*572c4311Sfengbojiang     while(1) {
4314*572c4311Sfengbojiang         raxSeek(&ri,"^",NULL,0);
4315*572c4311Sfengbojiang         if (!raxNext(&ri)) break;
4316*572c4311Sfengbojiang         uint64_t expiretime;
4317*572c4311Sfengbojiang         memcpy(&expiretime,ri.key,sizeof(expiretime));
4318*572c4311Sfengbojiang         expiretime = ntohu64(expiretime);
4319*572c4311Sfengbojiang         if (now >= expiretime) {
4320*572c4311Sfengbojiang             RedisModuleTimer *timer = ri.data;
4321*572c4311Sfengbojiang             RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
4322*572c4311Sfengbojiang 
4323*572c4311Sfengbojiang             ctx.module = timer->module;
4324*572c4311Sfengbojiang             ctx.client = moduleFreeContextReusedClient;
4325*572c4311Sfengbojiang             selectDb(ctx.client, timer->dbid);
4326*572c4311Sfengbojiang             timer->callback(&ctx,timer->data);
4327*572c4311Sfengbojiang             moduleFreeContext(&ctx);
4328*572c4311Sfengbojiang             raxRemove(Timers,(unsigned char*)ri.key,ri.key_len,NULL);
4329*572c4311Sfengbojiang             zfree(timer);
4330*572c4311Sfengbojiang         } else {
4331*572c4311Sfengbojiang             next_period = (expiretime-now)/1000; /* Scale to milliseconds. */
4332*572c4311Sfengbojiang             break;
4333*572c4311Sfengbojiang         }
4334*572c4311Sfengbojiang     }
4335*572c4311Sfengbojiang     raxStop(&ri);
4336*572c4311Sfengbojiang 
4337*572c4311Sfengbojiang     /* Reschedule the next timer or cancel it. */
4338*572c4311Sfengbojiang     if (next_period <= 0) next_period = 1;
4339*572c4311Sfengbojiang     return (raxSize(Timers) > 0) ? next_period : AE_NOMORE;
4340*572c4311Sfengbojiang }
4341*572c4311Sfengbojiang 
4342*572c4311Sfengbojiang /* Create a new timer that will fire after `period` milliseconds, and will call
4343*572c4311Sfengbojiang  * the specified function using `data` as argument. The returned timer ID can be
4344*572c4311Sfengbojiang  * used to get information from the timer or to stop it before it fires. */
RM_CreateTimer(RedisModuleCtx * ctx,mstime_t period,RedisModuleTimerProc callback,void * data)4345*572c4311Sfengbojiang RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data) {
4346*572c4311Sfengbojiang     RedisModuleTimer *timer = zmalloc(sizeof(*timer));
4347*572c4311Sfengbojiang     timer->module = ctx->module;
4348*572c4311Sfengbojiang     timer->callback = callback;
4349*572c4311Sfengbojiang     timer->data = data;
4350*572c4311Sfengbojiang     timer->dbid = ctx->client->db->id;
4351*572c4311Sfengbojiang     uint64_t expiretime = ustime()+period*1000;
4352*572c4311Sfengbojiang     uint64_t key;
4353*572c4311Sfengbojiang 
4354*572c4311Sfengbojiang     while(1) {
4355*572c4311Sfengbojiang         key = htonu64(expiretime);
4356*572c4311Sfengbojiang         if (raxFind(Timers, (unsigned char*)&key,sizeof(key)) == raxNotFound) {
4357*572c4311Sfengbojiang             raxInsert(Timers,(unsigned char*)&key,sizeof(key),timer,NULL);
4358*572c4311Sfengbojiang             break;
4359*572c4311Sfengbojiang         } else {
4360*572c4311Sfengbojiang             expiretime++;
4361*572c4311Sfengbojiang         }
4362*572c4311Sfengbojiang     }
4363*572c4311Sfengbojiang 
4364*572c4311Sfengbojiang     /* We need to install the main event loop timer if it's not already
4365*572c4311Sfengbojiang      * installed, or we may need to refresh its period if we just installed
4366*572c4311Sfengbojiang      * a timer that will expire sooner than any other else. */
4367*572c4311Sfengbojiang     if (aeTimer != -1) {
4368*572c4311Sfengbojiang         raxIterator ri;
4369*572c4311Sfengbojiang         raxStart(&ri,Timers);
4370*572c4311Sfengbojiang         raxSeek(&ri,"^",NULL,0);
4371*572c4311Sfengbojiang         raxNext(&ri);
4372*572c4311Sfengbojiang         if (memcmp(ri.key,&key,sizeof(key)) == 0) {
4373*572c4311Sfengbojiang             /* This is the first key, we need to re-install the timer according
4374*572c4311Sfengbojiang              * to the just added event. */
4375*572c4311Sfengbojiang             aeDeleteTimeEvent(server.el,aeTimer);
4376*572c4311Sfengbojiang             aeTimer = -1;
4377*572c4311Sfengbojiang         }
4378*572c4311Sfengbojiang         raxStop(&ri);
4379*572c4311Sfengbojiang     }
4380*572c4311Sfengbojiang 
4381*572c4311Sfengbojiang     /* If we have no main timer (the old one was invalidated, or this is the
4382*572c4311Sfengbojiang      * first module timer we have), install one. */
4383*572c4311Sfengbojiang     if (aeTimer == -1)
4384*572c4311Sfengbojiang         aeTimer = aeCreateTimeEvent(server.el,period,moduleTimerHandler,NULL,NULL);
4385*572c4311Sfengbojiang 
4386*572c4311Sfengbojiang     return key;
4387*572c4311Sfengbojiang }
4388*572c4311Sfengbojiang 
4389*572c4311Sfengbojiang /* Stop a timer, returns REDISMODULE_OK if the timer was found, belonged to the
4390*572c4311Sfengbojiang  * calling module, and was stopped, otherwise REDISMODULE_ERR is returned.
4391*572c4311Sfengbojiang  * If not NULL, the data pointer is set to the value of the data argument when
4392*572c4311Sfengbojiang  * the timer was created. */
RM_StopTimer(RedisModuleCtx * ctx,RedisModuleTimerID id,void ** data)4393*572c4311Sfengbojiang int RM_StopTimer(RedisModuleCtx *ctx, RedisModuleTimerID id, void **data) {
4394*572c4311Sfengbojiang     RedisModuleTimer *timer = raxFind(Timers,(unsigned char*)&id,sizeof(id));
4395*572c4311Sfengbojiang     if (timer == raxNotFound || timer->module != ctx->module)
4396*572c4311Sfengbojiang         return REDISMODULE_ERR;
4397*572c4311Sfengbojiang     if (data) *data = timer->data;
4398*572c4311Sfengbojiang     raxRemove(Timers,(unsigned char*)&id,sizeof(id),NULL);
4399*572c4311Sfengbojiang     zfree(timer);
4400*572c4311Sfengbojiang     return REDISMODULE_OK;
4401*572c4311Sfengbojiang }
4402*572c4311Sfengbojiang 
4403*572c4311Sfengbojiang /* Obtain information about a timer: its remaining time before firing
4404*572c4311Sfengbojiang  * (in milliseconds), and the private data pointer associated with the timer.
4405*572c4311Sfengbojiang  * If the timer specified does not exist or belongs to a different module
4406*572c4311Sfengbojiang  * no information is returned and the function returns REDISMODULE_ERR, otherwise
4407*572c4311Sfengbojiang  * REDISMODULE_OK is returned. The arguments remaining or data can be NULL if
4408*572c4311Sfengbojiang  * the caller does not need certain information. */
RM_GetTimerInfo(RedisModuleCtx * ctx,RedisModuleTimerID id,uint64_t * remaining,void ** data)4409*572c4311Sfengbojiang int RM_GetTimerInfo(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remaining, void **data) {
4410*572c4311Sfengbojiang     RedisModuleTimer *timer = raxFind(Timers,(unsigned char*)&id,sizeof(id));
4411*572c4311Sfengbojiang     if (timer == raxNotFound || timer->module != ctx->module)
4412*572c4311Sfengbojiang         return REDISMODULE_ERR;
4413*572c4311Sfengbojiang     if (remaining) {
4414*572c4311Sfengbojiang         int64_t rem = ntohu64(id)-ustime();
4415*572c4311Sfengbojiang         if (rem < 0) rem = 0;
4416*572c4311Sfengbojiang         *remaining = rem/1000; /* Scale to milliseconds. */
4417*572c4311Sfengbojiang     }
4418*572c4311Sfengbojiang     if (data) *data = timer->data;
4419*572c4311Sfengbojiang     return REDISMODULE_OK;
4420*572c4311Sfengbojiang }
4421*572c4311Sfengbojiang 
4422*572c4311Sfengbojiang /* --------------------------------------------------------------------------
4423*572c4311Sfengbojiang  * Modules Dictionary API
4424*572c4311Sfengbojiang  *
4425*572c4311Sfengbojiang  * Implements a sorted dictionary (actually backed by a radix tree) with
4426*572c4311Sfengbojiang  * the usual get / set / del / num-items API, together with an iterator
4427*572c4311Sfengbojiang  * capable of going back and forth.
4428*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
4429*572c4311Sfengbojiang 
4430*572c4311Sfengbojiang /* Create a new dictionary. The 'ctx' pointer can be the current module context
4431*572c4311Sfengbojiang  * or NULL, depending on what you want. Please follow the following rules:
4432*572c4311Sfengbojiang  *
4433*572c4311Sfengbojiang  * 1. Use a NULL context if you plan to retain a reference to this dictionary
4434*572c4311Sfengbojiang  *    that will survive the time of the module callback where you created it.
4435*572c4311Sfengbojiang  * 2. Use a NULL context if no context is available at the time you are creating
4436*572c4311Sfengbojiang  *    the dictionary (of course...).
4437*572c4311Sfengbojiang  * 3. However use the current callback context as 'ctx' argument if the
4438*572c4311Sfengbojiang  *    dictionary time to live is just limited to the callback scope. In this
4439*572c4311Sfengbojiang  *    case, if enabled, you can enjoy the automatic memory management that will
4440*572c4311Sfengbojiang  *    reclaim the dictionary memory, as well as the strings returned by the
4441*572c4311Sfengbojiang  *    Next / Prev dictionary iterator calls.
4442*572c4311Sfengbojiang  */
RM_CreateDict(RedisModuleCtx * ctx)4443*572c4311Sfengbojiang RedisModuleDict *RM_CreateDict(RedisModuleCtx *ctx) {
4444*572c4311Sfengbojiang     struct RedisModuleDict *d = zmalloc(sizeof(*d));
4445*572c4311Sfengbojiang     d->rax = raxNew();
4446*572c4311Sfengbojiang     if (ctx != NULL) autoMemoryAdd(ctx,REDISMODULE_AM_DICT,d);
4447*572c4311Sfengbojiang     return d;
4448*572c4311Sfengbojiang }
4449*572c4311Sfengbojiang 
4450*572c4311Sfengbojiang /* Free a dictionary created with RM_CreateDict(). You need to pass the
4451*572c4311Sfengbojiang  * context pointer 'ctx' only if the dictionary was created using the
4452*572c4311Sfengbojiang  * context instead of passing NULL. */
RM_FreeDict(RedisModuleCtx * ctx,RedisModuleDict * d)4453*572c4311Sfengbojiang void RM_FreeDict(RedisModuleCtx *ctx, RedisModuleDict *d) {
4454*572c4311Sfengbojiang     if (ctx != NULL) autoMemoryFreed(ctx,REDISMODULE_AM_DICT,d);
4455*572c4311Sfengbojiang     raxFree(d->rax);
4456*572c4311Sfengbojiang     zfree(d);
4457*572c4311Sfengbojiang }
4458*572c4311Sfengbojiang 
4459*572c4311Sfengbojiang /* Return the size of the dictionary (number of keys). */
RM_DictSize(RedisModuleDict * d)4460*572c4311Sfengbojiang uint64_t RM_DictSize(RedisModuleDict *d) {
4461*572c4311Sfengbojiang     return raxSize(d->rax);
4462*572c4311Sfengbojiang }
4463*572c4311Sfengbojiang 
4464*572c4311Sfengbojiang /* Store the specified key into the dictionary, setting its value to the
4465*572c4311Sfengbojiang  * pointer 'ptr'. If the key was added with success, since it did not
4466*572c4311Sfengbojiang  * already exist, REDISMODULE_OK is returned. Otherwise if the key already
4467*572c4311Sfengbojiang  * exists the function returns REDISMODULE_ERR. */
RM_DictSetC(RedisModuleDict * d,void * key,size_t keylen,void * ptr)4468*572c4311Sfengbojiang int RM_DictSetC(RedisModuleDict *d, void *key, size_t keylen, void *ptr) {
4469*572c4311Sfengbojiang     int retval = raxTryInsert(d->rax,key,keylen,ptr,NULL);
4470*572c4311Sfengbojiang     return (retval == 1) ? REDISMODULE_OK : REDISMODULE_ERR;
4471*572c4311Sfengbojiang }
4472*572c4311Sfengbojiang 
4473*572c4311Sfengbojiang /* Like RedisModule_DictSetC() but will replace the key with the new
4474*572c4311Sfengbojiang  * value if the key already exists. */
RM_DictReplaceC(RedisModuleDict * d,void * key,size_t keylen,void * ptr)4475*572c4311Sfengbojiang int RM_DictReplaceC(RedisModuleDict *d, void *key, size_t keylen, void *ptr) {
4476*572c4311Sfengbojiang     int retval = raxInsert(d->rax,key,keylen,ptr,NULL);
4477*572c4311Sfengbojiang     return (retval == 1) ? REDISMODULE_OK : REDISMODULE_ERR;
4478*572c4311Sfengbojiang }
4479*572c4311Sfengbojiang 
4480*572c4311Sfengbojiang /* Like RedisModule_DictSetC() but takes the key as a RedisModuleString. */
RM_DictSet(RedisModuleDict * d,RedisModuleString * key,void * ptr)4481*572c4311Sfengbojiang int RM_DictSet(RedisModuleDict *d, RedisModuleString *key, void *ptr) {
4482*572c4311Sfengbojiang     return RM_DictSetC(d,key->ptr,sdslen(key->ptr),ptr);
4483*572c4311Sfengbojiang }
4484*572c4311Sfengbojiang 
4485*572c4311Sfengbojiang /* Like RedisModule_DictReplaceC() but takes the key as a RedisModuleString. */
RM_DictReplace(RedisModuleDict * d,RedisModuleString * key,void * ptr)4486*572c4311Sfengbojiang int RM_DictReplace(RedisModuleDict *d, RedisModuleString *key, void *ptr) {
4487*572c4311Sfengbojiang     return RM_DictReplaceC(d,key->ptr,sdslen(key->ptr),ptr);
4488*572c4311Sfengbojiang }
4489*572c4311Sfengbojiang 
4490*572c4311Sfengbojiang /* Return the value stored at the specified key. The function returns NULL
4491*572c4311Sfengbojiang  * both in the case the key does not exist, or if you actually stored
4492*572c4311Sfengbojiang  * NULL at key. So, optionally, if the 'nokey' pointer is not NULL, it will
4493*572c4311Sfengbojiang  * be set by reference to 1 if the key does not exist, or to 0 if the key
4494*572c4311Sfengbojiang  * exists. */
RM_DictGetC(RedisModuleDict * d,void * key,size_t keylen,int * nokey)4495*572c4311Sfengbojiang void *RM_DictGetC(RedisModuleDict *d, void *key, size_t keylen, int *nokey) {
4496*572c4311Sfengbojiang     void *res = raxFind(d->rax,key,keylen);
4497*572c4311Sfengbojiang     if (nokey) *nokey = (res == raxNotFound);
4498*572c4311Sfengbojiang     return (res == raxNotFound) ? NULL : res;
4499*572c4311Sfengbojiang }
4500*572c4311Sfengbojiang 
4501*572c4311Sfengbojiang /* Like RedisModule_DictGetC() but takes the key as a RedisModuleString. */
RM_DictGet(RedisModuleDict * d,RedisModuleString * key,int * nokey)4502*572c4311Sfengbojiang void *RM_DictGet(RedisModuleDict *d, RedisModuleString *key, int *nokey) {
4503*572c4311Sfengbojiang     return RM_DictGetC(d,key->ptr,sdslen(key->ptr),nokey);
4504*572c4311Sfengbojiang }
4505*572c4311Sfengbojiang 
4506*572c4311Sfengbojiang /* Remove the specified key from the dictionary, returning REDISMODULE_OK if
4507*572c4311Sfengbojiang  * the key was found and delted, or REDISMODULE_ERR if instead there was
4508*572c4311Sfengbojiang  * no such key in the dictionary. When the operation is successful, if
4509*572c4311Sfengbojiang  * 'oldval' is not NULL, then '*oldval' is set to the value stored at the
4510*572c4311Sfengbojiang  * key before it was deleted. Using this feature it is possible to get
4511*572c4311Sfengbojiang  * a pointer to the value (for instance in order to release it), without
4512*572c4311Sfengbojiang  * having to call RedisModule_DictGet() before deleting the key. */
RM_DictDelC(RedisModuleDict * d,void * key,size_t keylen,void * oldval)4513*572c4311Sfengbojiang int RM_DictDelC(RedisModuleDict *d, void *key, size_t keylen, void *oldval) {
4514*572c4311Sfengbojiang     int retval = raxRemove(d->rax,key,keylen,oldval);
4515*572c4311Sfengbojiang     return retval ? REDISMODULE_OK : REDISMODULE_ERR;
4516*572c4311Sfengbojiang }
4517*572c4311Sfengbojiang 
4518*572c4311Sfengbojiang /* Like RedisModule_DictDelC() but gets the key as a RedisModuleString. */
RM_DictDel(RedisModuleDict * d,RedisModuleString * key,void * oldval)4519*572c4311Sfengbojiang int RM_DictDel(RedisModuleDict *d, RedisModuleString *key, void *oldval) {
4520*572c4311Sfengbojiang     return RM_DictDelC(d,key->ptr,sdslen(key->ptr),oldval);
4521*572c4311Sfengbojiang }
4522*572c4311Sfengbojiang 
4523*572c4311Sfengbojiang /* Return an interator, setup in order to start iterating from the specified
4524*572c4311Sfengbojiang  * key by applying the operator 'op', which is just a string specifying the
4525*572c4311Sfengbojiang  * comparison operator to use in order to seek the first element. The
4526*572c4311Sfengbojiang  * operators avalable are:
4527*572c4311Sfengbojiang  *
4528*572c4311Sfengbojiang  * "^"   -- Seek the first (lexicographically smaller) key.
4529*572c4311Sfengbojiang  * "$"   -- Seek the last  (lexicographically biffer) key.
4530*572c4311Sfengbojiang  * ">"   -- Seek the first element greter than the specified key.
4531*572c4311Sfengbojiang  * ">="  -- Seek the first element greater or equal than the specified key.
4532*572c4311Sfengbojiang  * "<"   -- Seek the first element smaller than the specified key.
4533*572c4311Sfengbojiang  * "<="  -- Seek the first element smaller or equal than the specified key.
4534*572c4311Sfengbojiang  * "=="  -- Seek the first element matching exactly the specified key.
4535*572c4311Sfengbojiang  *
4536*572c4311Sfengbojiang  * Note that for "^" and "$" the passed key is not used, and the user may
4537*572c4311Sfengbojiang  * just pass NULL with a length of 0.
4538*572c4311Sfengbojiang  *
4539*572c4311Sfengbojiang  * If the element to start the iteration cannot be seeked based on the
4540*572c4311Sfengbojiang  * key and operator passed, RedisModule_DictNext() / Prev() will just return
4541*572c4311Sfengbojiang  * REDISMODULE_ERR at the first call, otherwise they'll produce elements.
4542*572c4311Sfengbojiang  */
RM_DictIteratorStartC(RedisModuleDict * d,const char * op,void * key,size_t keylen)4543*572c4311Sfengbojiang RedisModuleDictIter *RM_DictIteratorStartC(RedisModuleDict *d, const char *op, void *key, size_t keylen) {
4544*572c4311Sfengbojiang     RedisModuleDictIter *di = zmalloc(sizeof(*di));
4545*572c4311Sfengbojiang     di->dict = d;
4546*572c4311Sfengbojiang     raxStart(&di->ri,d->rax);
4547*572c4311Sfengbojiang     raxSeek(&di->ri,op,key,keylen);
4548*572c4311Sfengbojiang     return di;
4549*572c4311Sfengbojiang }
4550*572c4311Sfengbojiang 
4551*572c4311Sfengbojiang /* Exactly like RedisModule_DictIteratorStartC, but the key is passed as a
4552*572c4311Sfengbojiang  * RedisModuleString. */
RM_DictIteratorStart(RedisModuleDict * d,const char * op,RedisModuleString * key)4553*572c4311Sfengbojiang RedisModuleDictIter *RM_DictIteratorStart(RedisModuleDict *d, const char *op, RedisModuleString *key) {
4554*572c4311Sfengbojiang     return RM_DictIteratorStartC(d,op,key->ptr,sdslen(key->ptr));
4555*572c4311Sfengbojiang }
4556*572c4311Sfengbojiang 
4557*572c4311Sfengbojiang /* Release the iterator created with RedisModule_DictIteratorStart(). This call
4558*572c4311Sfengbojiang  * is mandatory otherwise a memory leak is introduced in the module. */
RM_DictIteratorStop(RedisModuleDictIter * di)4559*572c4311Sfengbojiang void RM_DictIteratorStop(RedisModuleDictIter *di) {
4560*572c4311Sfengbojiang     raxStop(&di->ri);
4561*572c4311Sfengbojiang     zfree(di);
4562*572c4311Sfengbojiang }
4563*572c4311Sfengbojiang 
4564*572c4311Sfengbojiang /* After its creation with RedisModule_DictIteratorStart(), it is possible to
4565*572c4311Sfengbojiang  * change the currently selected element of the iterator by using this
4566*572c4311Sfengbojiang  * API call. The result based on the operator and key is exactly like
4567*572c4311Sfengbojiang  * the function RedisModule_DictIteratorStart(), however in this case the
4568*572c4311Sfengbojiang  * return value is just REDISMODULE_OK in case the seeked element was found,
4569*572c4311Sfengbojiang  * or REDISMODULE_ERR in case it was not possible to seek the specified
4570*572c4311Sfengbojiang  * element. It is possible to reseek an iterator as many times as you want. */
RM_DictIteratorReseekC(RedisModuleDictIter * di,const char * op,void * key,size_t keylen)4571*572c4311Sfengbojiang int RM_DictIteratorReseekC(RedisModuleDictIter *di, const char *op, void *key, size_t keylen) {
4572*572c4311Sfengbojiang     return raxSeek(&di->ri,op,key,keylen);
4573*572c4311Sfengbojiang }
4574*572c4311Sfengbojiang 
4575*572c4311Sfengbojiang /* Like RedisModule_DictIteratorReseekC() but takes the key as as a
4576*572c4311Sfengbojiang  * RedisModuleString. */
RM_DictIteratorReseek(RedisModuleDictIter * di,const char * op,RedisModuleString * key)4577*572c4311Sfengbojiang int RM_DictIteratorReseek(RedisModuleDictIter *di, const char *op, RedisModuleString *key) {
4578*572c4311Sfengbojiang     return RM_DictIteratorReseekC(di,op,key->ptr,sdslen(key->ptr));
4579*572c4311Sfengbojiang }
4580*572c4311Sfengbojiang 
4581*572c4311Sfengbojiang /* Return the current item of the dictionary iterator 'di' and steps to the
4582*572c4311Sfengbojiang  * next element. If the iterator already yield the last element and there
4583*572c4311Sfengbojiang  * are no other elements to return, NULL is returned, otherwise a pointer
4584*572c4311Sfengbojiang  * to a string representing the key is provided, and the '*keylen' length
4585*572c4311Sfengbojiang  * is set by reference (if keylen is not NULL). The '*dataptr', if not NULL
4586*572c4311Sfengbojiang  * is set to the value of the pointer stored at the returned key as auxiliary
4587*572c4311Sfengbojiang  * data (as set by the RedisModule_DictSet API).
4588*572c4311Sfengbojiang  *
4589*572c4311Sfengbojiang  * Usage example:
4590*572c4311Sfengbojiang  *
4591*572c4311Sfengbojiang  *      ... create the iterator here ...
4592*572c4311Sfengbojiang  *      char *key;
4593*572c4311Sfengbojiang  *      void *data;
4594*572c4311Sfengbojiang  *      while((key = RedisModule_DictNextC(iter,&keylen,&data)) != NULL) {
4595*572c4311Sfengbojiang  *          printf("%.*s %p\n", (int)keylen, key, data);
4596*572c4311Sfengbojiang  *      }
4597*572c4311Sfengbojiang  *
4598*572c4311Sfengbojiang  * The returned pointer is of type void because sometimes it makes sense
4599*572c4311Sfengbojiang  * to cast it to a char* sometimes to an unsigned char* depending on the
4600*572c4311Sfengbojiang  * fact it contains or not binary data, so this API ends being more
4601*572c4311Sfengbojiang  * comfortable to use.
4602*572c4311Sfengbojiang  *
4603*572c4311Sfengbojiang  * The validity of the returned pointer is until the next call to the
4604*572c4311Sfengbojiang  * next/prev iterator step. Also the pointer is no longer valid once the
4605*572c4311Sfengbojiang  * iterator is released. */
RM_DictNextC(RedisModuleDictIter * di,size_t * keylen,void ** dataptr)4606*572c4311Sfengbojiang void *RM_DictNextC(RedisModuleDictIter *di, size_t *keylen, void **dataptr) {
4607*572c4311Sfengbojiang     if (!raxNext(&di->ri)) return NULL;
4608*572c4311Sfengbojiang     if (keylen) *keylen = di->ri.key_len;
4609*572c4311Sfengbojiang     if (dataptr) *dataptr = di->ri.data;
4610*572c4311Sfengbojiang     return di->ri.key;
4611*572c4311Sfengbojiang }
4612*572c4311Sfengbojiang 
4613*572c4311Sfengbojiang /* This function is exactly like RedisModule_DictNext() but after returning
4614*572c4311Sfengbojiang  * the currently selected element in the iterator, it selects the previous
4615*572c4311Sfengbojiang  * element (laxicographically smaller) instead of the next one. */
RM_DictPrevC(RedisModuleDictIter * di,size_t * keylen,void ** dataptr)4616*572c4311Sfengbojiang void *RM_DictPrevC(RedisModuleDictIter *di, size_t *keylen, void **dataptr) {
4617*572c4311Sfengbojiang     if (!raxPrev(&di->ri)) return NULL;
4618*572c4311Sfengbojiang     if (keylen) *keylen = di->ri.key_len;
4619*572c4311Sfengbojiang     if (dataptr) *dataptr = di->ri.data;
4620*572c4311Sfengbojiang     return di->ri.key;
4621*572c4311Sfengbojiang }
4622*572c4311Sfengbojiang 
4623*572c4311Sfengbojiang /* Like RedisModuleNextC(), but instead of returning an internally allocated
4624*572c4311Sfengbojiang  * buffer and key length, it returns directly a module string object allocated
4625*572c4311Sfengbojiang  * in the specified context 'ctx' (that may be NULL exactly like for the main
4626*572c4311Sfengbojiang  * API RedisModule_CreateString).
4627*572c4311Sfengbojiang  *
4628*572c4311Sfengbojiang  * The returned string object should be deallocated after use, either manually
4629*572c4311Sfengbojiang  * or by using a context that has automatic memory management active. */
RM_DictNext(RedisModuleCtx * ctx,RedisModuleDictIter * di,void ** dataptr)4630*572c4311Sfengbojiang RedisModuleString *RM_DictNext(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr) {
4631*572c4311Sfengbojiang     size_t keylen;
4632*572c4311Sfengbojiang     void *key = RM_DictNextC(di,&keylen,dataptr);
4633*572c4311Sfengbojiang     if (key == NULL) return NULL;
4634*572c4311Sfengbojiang     return RM_CreateString(ctx,key,keylen);
4635*572c4311Sfengbojiang }
4636*572c4311Sfengbojiang 
4637*572c4311Sfengbojiang /* Like RedisModule_DictNext() but after returning the currently selected
4638*572c4311Sfengbojiang  * element in the iterator, it selects the previous element (laxicographically
4639*572c4311Sfengbojiang  * smaller) instead of the next one. */
RM_DictPrev(RedisModuleCtx * ctx,RedisModuleDictIter * di,void ** dataptr)4640*572c4311Sfengbojiang RedisModuleString *RM_DictPrev(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr) {
4641*572c4311Sfengbojiang     size_t keylen;
4642*572c4311Sfengbojiang     void *key = RM_DictPrevC(di,&keylen,dataptr);
4643*572c4311Sfengbojiang     if (key == NULL) return NULL;
4644*572c4311Sfengbojiang     return RM_CreateString(ctx,key,keylen);
4645*572c4311Sfengbojiang }
4646*572c4311Sfengbojiang 
4647*572c4311Sfengbojiang /* Compare the element currently pointed by the iterator to the specified
4648*572c4311Sfengbojiang  * element given by key/keylen, according to the operator 'op' (the set of
4649*572c4311Sfengbojiang  * valid operators are the same valid for RedisModule_DictIteratorStart).
4650*572c4311Sfengbojiang  * If the comparision is successful the command returns REDISMODULE_OK
4651*572c4311Sfengbojiang  * otherwise REDISMODULE_ERR is returned.
4652*572c4311Sfengbojiang  *
4653*572c4311Sfengbojiang  * This is useful when we want to just emit a lexicographical range, so
4654*572c4311Sfengbojiang  * in the loop, as we iterate elements, we can also check if we are still
4655*572c4311Sfengbojiang  * on range.
4656*572c4311Sfengbojiang  *
4657*572c4311Sfengbojiang  * The function returne REDISMODULE_ERR if the iterator reached the
4658*572c4311Sfengbojiang  * end of elements condition as well. */
RM_DictCompareC(RedisModuleDictIter * di,const char * op,void * key,size_t keylen)4659*572c4311Sfengbojiang int RM_DictCompareC(RedisModuleDictIter *di, const char *op, void *key, size_t keylen) {
4660*572c4311Sfengbojiang     if (raxEOF(&di->ri)) return REDISMODULE_ERR;
4661*572c4311Sfengbojiang     int res = raxCompare(&di->ri,op,key,keylen);
4662*572c4311Sfengbojiang     return res ? REDISMODULE_OK : REDISMODULE_ERR;
4663*572c4311Sfengbojiang }
4664*572c4311Sfengbojiang 
4665*572c4311Sfengbojiang /* Like RedisModule_DictCompareC but gets the key to compare with the current
4666*572c4311Sfengbojiang  * iterator key as a RedisModuleString. */
RM_DictCompare(RedisModuleDictIter * di,const char * op,RedisModuleString * key)4667*572c4311Sfengbojiang int RM_DictCompare(RedisModuleDictIter *di, const char *op, RedisModuleString *key) {
4668*572c4311Sfengbojiang     if (raxEOF(&di->ri)) return REDISMODULE_ERR;
4669*572c4311Sfengbojiang     int res = raxCompare(&di->ri,op,key->ptr,sdslen(key->ptr));
4670*572c4311Sfengbojiang     return res ? REDISMODULE_OK : REDISMODULE_ERR;
4671*572c4311Sfengbojiang }
4672*572c4311Sfengbojiang 
4673*572c4311Sfengbojiang /* --------------------------------------------------------------------------
4674*572c4311Sfengbojiang  * Modules utility APIs
4675*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
4676*572c4311Sfengbojiang 
4677*572c4311Sfengbojiang /* Return random bytes using SHA1 in counter mode with a /dev/urandom
4678*572c4311Sfengbojiang  * initialized seed. This function is fast so can be used to generate
4679*572c4311Sfengbojiang  * many bytes without any effect on the operating system entropy pool.
4680*572c4311Sfengbojiang  * Currently this function is not thread safe. */
RM_GetRandomBytes(unsigned char * dst,size_t len)4681*572c4311Sfengbojiang void RM_GetRandomBytes(unsigned char *dst, size_t len) {
4682*572c4311Sfengbojiang     getRandomBytes(dst,len);
4683*572c4311Sfengbojiang }
4684*572c4311Sfengbojiang 
4685*572c4311Sfengbojiang /* Like RedisModule_GetRandomBytes() but instead of setting the string to
4686*572c4311Sfengbojiang  * random bytes the string is set to random characters in the in the
4687*572c4311Sfengbojiang  * hex charset [0-9a-f]. */
RM_GetRandomHexChars(char * dst,size_t len)4688*572c4311Sfengbojiang void RM_GetRandomHexChars(char *dst, size_t len) {
4689*572c4311Sfengbojiang     getRandomHexChars(dst,len);
4690*572c4311Sfengbojiang }
4691*572c4311Sfengbojiang 
4692*572c4311Sfengbojiang /* --------------------------------------------------------------------------
4693*572c4311Sfengbojiang  * Modules API exporting / importing
4694*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
4695*572c4311Sfengbojiang 
4696*572c4311Sfengbojiang /* This function is called by a module in order to export some API with a
4697*572c4311Sfengbojiang  * given name. Other modules will be able to use this API by calling the
4698*572c4311Sfengbojiang  * symmetrical function RM_GetSharedAPI() and casting the return value to
4699*572c4311Sfengbojiang  * the right function pointer.
4700*572c4311Sfengbojiang  *
4701*572c4311Sfengbojiang  * The function will return REDISMODULE_OK if the name is not already taken,
4702*572c4311Sfengbojiang  * otherwise REDISMODULE_ERR will be returned and no operation will be
4703*572c4311Sfengbojiang  * performed.
4704*572c4311Sfengbojiang  *
4705*572c4311Sfengbojiang  * IMPORTANT: the apiname argument should be a string literal with static
4706*572c4311Sfengbojiang  * lifetime. The API relies on the fact that it will always be valid in
4707*572c4311Sfengbojiang  * the future. */
RM_ExportSharedAPI(RedisModuleCtx * ctx,const char * apiname,void * func)4708*572c4311Sfengbojiang int RM_ExportSharedAPI(RedisModuleCtx *ctx, const char *apiname, void *func) {
4709*572c4311Sfengbojiang     RedisModuleSharedAPI *sapi = zmalloc(sizeof(*sapi));
4710*572c4311Sfengbojiang     sapi->module = ctx->module;
4711*572c4311Sfengbojiang     sapi->func = func;
4712*572c4311Sfengbojiang     if (dictAdd(server.sharedapi, (char*)apiname, sapi) != DICT_OK) {
4713*572c4311Sfengbojiang         zfree(sapi);
4714*572c4311Sfengbojiang         return REDISMODULE_ERR;
4715*572c4311Sfengbojiang     }
4716*572c4311Sfengbojiang     return REDISMODULE_OK;
4717*572c4311Sfengbojiang }
4718*572c4311Sfengbojiang 
4719*572c4311Sfengbojiang /* Request an exported API pointer. The return value is just a void pointer
4720*572c4311Sfengbojiang  * that the caller of this function will be required to cast to the right
4721*572c4311Sfengbojiang  * function pointer, so this is a private contract between modules.
4722*572c4311Sfengbojiang  *
4723*572c4311Sfengbojiang  * If the requested API is not available then NULL is returned. Because
4724*572c4311Sfengbojiang  * modules can be loaded at different times with different order, this
4725*572c4311Sfengbojiang  * function calls should be put inside some module generic API registering
4726*572c4311Sfengbojiang  * step, that is called every time a module attempts to execute a
4727*572c4311Sfengbojiang  * command that requires external APIs: if some API cannot be resolved, the
4728*572c4311Sfengbojiang  * command should return an error.
4729*572c4311Sfengbojiang  *
4730*572c4311Sfengbojiang  * Here is an exmaple:
4731*572c4311Sfengbojiang  *
4732*572c4311Sfengbojiang  *     int ... myCommandImplementation() {
4733*572c4311Sfengbojiang  *        if (getExternalAPIs() == 0) {
4734*572c4311Sfengbojiang  *             reply with an error here if we cannot have the APIs
4735*572c4311Sfengbojiang  *        }
4736*572c4311Sfengbojiang  *        // Use the API:
4737*572c4311Sfengbojiang  *        myFunctionPointer(foo);
4738*572c4311Sfengbojiang  *     }
4739*572c4311Sfengbojiang  *
4740*572c4311Sfengbojiang  * And the function registerAPI() is:
4741*572c4311Sfengbojiang  *
4742*572c4311Sfengbojiang  *     int getExternalAPIs(void) {
4743*572c4311Sfengbojiang  *         static int api_loaded = 0;
4744*572c4311Sfengbojiang  *         if (api_loaded != 0) return 1; // APIs already resolved.
4745*572c4311Sfengbojiang  *
4746*572c4311Sfengbojiang  *         myFunctionPointer = RedisModule_GetOtherModuleAPI("...");
4747*572c4311Sfengbojiang  *         if (myFunctionPointer == NULL) return 0;
4748*572c4311Sfengbojiang  *
4749*572c4311Sfengbojiang  *         return 1;
4750*572c4311Sfengbojiang  *     }
4751*572c4311Sfengbojiang  */
RM_GetSharedAPI(RedisModuleCtx * ctx,const char * apiname)4752*572c4311Sfengbojiang void *RM_GetSharedAPI(RedisModuleCtx *ctx, const char *apiname) {
4753*572c4311Sfengbojiang     dictEntry *de = dictFind(server.sharedapi, apiname);
4754*572c4311Sfengbojiang     if (de == NULL) return NULL;
4755*572c4311Sfengbojiang     RedisModuleSharedAPI *sapi = dictGetVal(de);
4756*572c4311Sfengbojiang     if (listSearchKey(sapi->module->usedby,ctx->module) == NULL) {
4757*572c4311Sfengbojiang         listAddNodeTail(sapi->module->usedby,ctx->module);
4758*572c4311Sfengbojiang         listAddNodeTail(ctx->module->using,sapi->module);
4759*572c4311Sfengbojiang     }
4760*572c4311Sfengbojiang     return sapi->func;
4761*572c4311Sfengbojiang }
4762*572c4311Sfengbojiang 
4763*572c4311Sfengbojiang /* Remove all the APIs registered by the specified module. Usually you
4764*572c4311Sfengbojiang  * want this when the module is going to be unloaded. This function
4765*572c4311Sfengbojiang  * assumes that's caller responsibility to make sure the APIs are not
4766*572c4311Sfengbojiang  * used by other modules.
4767*572c4311Sfengbojiang  *
4768*572c4311Sfengbojiang  * The number of unregistered APIs is returned. */
moduleUnregisterSharedAPI(RedisModule * module)4769*572c4311Sfengbojiang int moduleUnregisterSharedAPI(RedisModule *module) {
4770*572c4311Sfengbojiang     int count = 0;
4771*572c4311Sfengbojiang     dictIterator *di = dictGetSafeIterator(server.sharedapi);
4772*572c4311Sfengbojiang     dictEntry *de;
4773*572c4311Sfengbojiang     while ((de = dictNext(di)) != NULL) {
4774*572c4311Sfengbojiang         const char *apiname = dictGetKey(de);
4775*572c4311Sfengbojiang         RedisModuleSharedAPI *sapi = dictGetVal(de);
4776*572c4311Sfengbojiang         if (sapi->module == module) {
4777*572c4311Sfengbojiang             dictDelete(server.sharedapi,apiname);
4778*572c4311Sfengbojiang             zfree(sapi);
4779*572c4311Sfengbojiang             count++;
4780*572c4311Sfengbojiang         }
4781*572c4311Sfengbojiang     }
4782*572c4311Sfengbojiang     dictReleaseIterator(di);
4783*572c4311Sfengbojiang     return count;
4784*572c4311Sfengbojiang }
4785*572c4311Sfengbojiang 
4786*572c4311Sfengbojiang /* Remove the specified module as an user of APIs of ever other module.
4787*572c4311Sfengbojiang  * This is usually called when a module is unloaded.
4788*572c4311Sfengbojiang  *
4789*572c4311Sfengbojiang  * Returns the number of modules this module was using APIs from. */
moduleUnregisterUsedAPI(RedisModule * module)4790*572c4311Sfengbojiang int moduleUnregisterUsedAPI(RedisModule *module) {
4791*572c4311Sfengbojiang     listIter li;
4792*572c4311Sfengbojiang     listNode *ln;
4793*572c4311Sfengbojiang     int count = 0;
4794*572c4311Sfengbojiang 
4795*572c4311Sfengbojiang     listRewind(module->using,&li);
4796*572c4311Sfengbojiang     while((ln = listNext(&li))) {
4797*572c4311Sfengbojiang         RedisModule *used = ln->value;
4798*572c4311Sfengbojiang         listNode *ln = listSearchKey(used->usedby,module);
4799*572c4311Sfengbojiang         if (ln) {
4800*572c4311Sfengbojiang             listDelNode(module->using,ln);
4801*572c4311Sfengbojiang             count++;
4802*572c4311Sfengbojiang         }
4803*572c4311Sfengbojiang     }
4804*572c4311Sfengbojiang     return count;
4805*572c4311Sfengbojiang }
4806*572c4311Sfengbojiang 
4807*572c4311Sfengbojiang /* Unregister all filters registered by a module.
4808*572c4311Sfengbojiang  * This is called when a module is being unloaded.
4809*572c4311Sfengbojiang  *
4810*572c4311Sfengbojiang  * Returns the number of filters unregistered. */
moduleUnregisterFilters(RedisModule * module)4811*572c4311Sfengbojiang int moduleUnregisterFilters(RedisModule *module) {
4812*572c4311Sfengbojiang     listIter li;
4813*572c4311Sfengbojiang     listNode *ln;
4814*572c4311Sfengbojiang     int count = 0;
4815*572c4311Sfengbojiang 
4816*572c4311Sfengbojiang     listRewind(module->filters,&li);
4817*572c4311Sfengbojiang     while((ln = listNext(&li))) {
4818*572c4311Sfengbojiang         RedisModuleCommandFilter *filter = ln->value;
4819*572c4311Sfengbojiang         listNode *ln = listSearchKey(moduleCommandFilters,filter);
4820*572c4311Sfengbojiang         if (ln) {
4821*572c4311Sfengbojiang             listDelNode(moduleCommandFilters,ln);
4822*572c4311Sfengbojiang             count++;
4823*572c4311Sfengbojiang         }
4824*572c4311Sfengbojiang         zfree(filter);
4825*572c4311Sfengbojiang     }
4826*572c4311Sfengbojiang     return count;
4827*572c4311Sfengbojiang }
4828*572c4311Sfengbojiang 
4829*572c4311Sfengbojiang /* --------------------------------------------------------------------------
4830*572c4311Sfengbojiang  * Module Command Filter API
4831*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
4832*572c4311Sfengbojiang 
4833*572c4311Sfengbojiang /* Register a new command filter function.
4834*572c4311Sfengbojiang  *
4835*572c4311Sfengbojiang  * Command filtering makes it possible for modules to extend Redis by plugging
4836*572c4311Sfengbojiang  * into the execution flow of all commands.
4837*572c4311Sfengbojiang  *
4838*572c4311Sfengbojiang  * A registered filter gets called before Redis executes *any* command.  This
4839*572c4311Sfengbojiang  * includes both core Redis commands and commands registered by any module.  The
4840*572c4311Sfengbojiang  * filter applies in all execution paths including:
4841*572c4311Sfengbojiang  *
4842*572c4311Sfengbojiang  * 1. Invocation by a client.
4843*572c4311Sfengbojiang  * 2. Invocation through `RedisModule_Call()` by any module.
4844*572c4311Sfengbojiang  * 3. Invocation through Lua 'redis.call()`.
4845*572c4311Sfengbojiang  * 4. Replication of a command from a master.
4846*572c4311Sfengbojiang  *
4847*572c4311Sfengbojiang  * The filter executes in a special filter context, which is different and more
4848*572c4311Sfengbojiang  * limited than a RedisModuleCtx.  Because the filter affects any command, it
4849*572c4311Sfengbojiang  * must be implemented in a very efficient way to reduce the performance impact
4850*572c4311Sfengbojiang  * on Redis.  All Redis Module API calls that require a valid context (such as
4851*572c4311Sfengbojiang  * `RedisModule_Call()`, `RedisModule_OpenKey()`, etc.) are not supported in a
4852*572c4311Sfengbojiang  * filter context.
4853*572c4311Sfengbojiang  *
4854*572c4311Sfengbojiang  * The `RedisModuleCommandFilterCtx` can be used to inspect or modify the
4855*572c4311Sfengbojiang  * executed command and its arguments.  As the filter executes before Redis
4856*572c4311Sfengbojiang  * begins processing the command, any change will affect the way the command is
4857*572c4311Sfengbojiang  * processed.  For example, a module can override Redis commands this way:
4858*572c4311Sfengbojiang  *
4859*572c4311Sfengbojiang  * 1. Register a `MODULE.SET` command which implements an extended version of
4860*572c4311Sfengbojiang  *    the Redis `SET` command.
4861*572c4311Sfengbojiang  * 2. Register a command filter which detects invocation of `SET` on a specific
4862*572c4311Sfengbojiang  *    pattern of keys.  Once detected, the filter will replace the first
4863*572c4311Sfengbojiang  *    argument from `SET` to `MODULE.SET`.
4864*572c4311Sfengbojiang  * 3. When filter execution is complete, Redis considers the new command name
4865*572c4311Sfengbojiang  *    and therefore executes the module's own command.
4866*572c4311Sfengbojiang  *
4867*572c4311Sfengbojiang  * Note that in the above use case, if `MODULE.SET` itself uses
4868*572c4311Sfengbojiang  * `RedisModule_Call()` the filter will be applied on that call as well.  If
4869*572c4311Sfengbojiang  * that is not desired, the `REDISMODULE_CMDFILTER_NOSELF` flag can be set when
4870*572c4311Sfengbojiang  * registering the filter.
4871*572c4311Sfengbojiang  *
4872*572c4311Sfengbojiang  * The `REDISMODULE_CMDFILTER_NOSELF` flag prevents execution flows that
4873*572c4311Sfengbojiang  * originate from the module's own `RM_Call()` from reaching the filter.  This
4874*572c4311Sfengbojiang  * flag is effective for all execution flows, including nested ones, as long as
4875*572c4311Sfengbojiang  * the execution begins from the module's command context or a thread-safe
4876*572c4311Sfengbojiang  * context that is associated with a blocking command.
4877*572c4311Sfengbojiang  *
4878*572c4311Sfengbojiang  * Detached thread-safe contexts are *not* associated with the module and cannot
4879*572c4311Sfengbojiang  * be protected by this flag.
4880*572c4311Sfengbojiang  *
4881*572c4311Sfengbojiang  * If multiple filters are registered (by the same or different modules), they
4882*572c4311Sfengbojiang  * are executed in the order of registration.
4883*572c4311Sfengbojiang  */
4884*572c4311Sfengbojiang 
RM_RegisterCommandFilter(RedisModuleCtx * ctx,RedisModuleCommandFilterFunc callback,int flags)4885*572c4311Sfengbojiang RedisModuleCommandFilter *RM_RegisterCommandFilter(RedisModuleCtx *ctx, RedisModuleCommandFilterFunc callback, int flags) {
4886*572c4311Sfengbojiang     RedisModuleCommandFilter *filter = zmalloc(sizeof(*filter));
4887*572c4311Sfengbojiang     filter->module = ctx->module;
4888*572c4311Sfengbojiang     filter->callback = callback;
4889*572c4311Sfengbojiang     filter->flags = flags;
4890*572c4311Sfengbojiang 
4891*572c4311Sfengbojiang     listAddNodeTail(moduleCommandFilters, filter);
4892*572c4311Sfengbojiang     listAddNodeTail(ctx->module->filters, filter);
4893*572c4311Sfengbojiang     return filter;
4894*572c4311Sfengbojiang }
4895*572c4311Sfengbojiang 
4896*572c4311Sfengbojiang /* Unregister a command filter.
4897*572c4311Sfengbojiang  */
RM_UnregisterCommandFilter(RedisModuleCtx * ctx,RedisModuleCommandFilter * filter)4898*572c4311Sfengbojiang int RM_UnregisterCommandFilter(RedisModuleCtx *ctx, RedisModuleCommandFilter *filter) {
4899*572c4311Sfengbojiang     listNode *ln;
4900*572c4311Sfengbojiang 
4901*572c4311Sfengbojiang     /* A module can only remove its own filters */
4902*572c4311Sfengbojiang     if (filter->module != ctx->module) return REDISMODULE_ERR;
4903*572c4311Sfengbojiang 
4904*572c4311Sfengbojiang     ln = listSearchKey(moduleCommandFilters,filter);
4905*572c4311Sfengbojiang     if (!ln) return REDISMODULE_ERR;
4906*572c4311Sfengbojiang     listDelNode(moduleCommandFilters,ln);
4907*572c4311Sfengbojiang 
4908*572c4311Sfengbojiang     ln = listSearchKey(ctx->module->filters,filter);
4909*572c4311Sfengbojiang     if (!ln) return REDISMODULE_ERR;    /* Shouldn't happen */
4910*572c4311Sfengbojiang     listDelNode(ctx->module->filters,ln);
4911*572c4311Sfengbojiang 
4912*572c4311Sfengbojiang     return REDISMODULE_OK;
4913*572c4311Sfengbojiang }
4914*572c4311Sfengbojiang 
moduleCallCommandFilters(client * c)4915*572c4311Sfengbojiang void moduleCallCommandFilters(client *c) {
4916*572c4311Sfengbojiang     if (listLength(moduleCommandFilters) == 0) return;
4917*572c4311Sfengbojiang 
4918*572c4311Sfengbojiang     listIter li;
4919*572c4311Sfengbojiang     listNode *ln;
4920*572c4311Sfengbojiang     listRewind(moduleCommandFilters,&li);
4921*572c4311Sfengbojiang 
4922*572c4311Sfengbojiang     RedisModuleCommandFilterCtx filter = {
4923*572c4311Sfengbojiang         .argv = c->argv,
4924*572c4311Sfengbojiang         .argc = c->argc
4925*572c4311Sfengbojiang     };
4926*572c4311Sfengbojiang 
4927*572c4311Sfengbojiang     while((ln = listNext(&li))) {
4928*572c4311Sfengbojiang         RedisModuleCommandFilter *f = ln->value;
4929*572c4311Sfengbojiang 
4930*572c4311Sfengbojiang         /* Skip filter if REDISMODULE_CMDFILTER_NOSELF is set and module is
4931*572c4311Sfengbojiang          * currently processing a command.
4932*572c4311Sfengbojiang          */
4933*572c4311Sfengbojiang         if ((f->flags & REDISMODULE_CMDFILTER_NOSELF) && f->module->in_call) continue;
4934*572c4311Sfengbojiang 
4935*572c4311Sfengbojiang         /* Call filter */
4936*572c4311Sfengbojiang         f->callback(&filter);
4937*572c4311Sfengbojiang     }
4938*572c4311Sfengbojiang 
4939*572c4311Sfengbojiang     c->argv = filter.argv;
4940*572c4311Sfengbojiang     c->argc = filter.argc;
4941*572c4311Sfengbojiang }
4942*572c4311Sfengbojiang 
4943*572c4311Sfengbojiang /* Return the number of arguments a filtered command has.  The number of
4944*572c4311Sfengbojiang  * arguments include the command itself.
4945*572c4311Sfengbojiang  */
RM_CommandFilterArgsCount(RedisModuleCommandFilterCtx * fctx)4946*572c4311Sfengbojiang int RM_CommandFilterArgsCount(RedisModuleCommandFilterCtx *fctx)
4947*572c4311Sfengbojiang {
4948*572c4311Sfengbojiang     return fctx->argc;
4949*572c4311Sfengbojiang }
4950*572c4311Sfengbojiang 
4951*572c4311Sfengbojiang /* Return the specified command argument.  The first argument (position 0) is
4952*572c4311Sfengbojiang  * the command itself, and the rest are user-provided args.
4953*572c4311Sfengbojiang  */
RM_CommandFilterArgGet(RedisModuleCommandFilterCtx * fctx,int pos)4954*572c4311Sfengbojiang const RedisModuleString *RM_CommandFilterArgGet(RedisModuleCommandFilterCtx *fctx, int pos)
4955*572c4311Sfengbojiang {
4956*572c4311Sfengbojiang     if (pos < 0 || pos >= fctx->argc) return NULL;
4957*572c4311Sfengbojiang     return fctx->argv[pos];
4958*572c4311Sfengbojiang }
4959*572c4311Sfengbojiang 
4960*572c4311Sfengbojiang /* Modify the filtered command by inserting a new argument at the specified
4961*572c4311Sfengbojiang  * position.  The specified RedisModuleString argument may be used by Redis
4962*572c4311Sfengbojiang  * after the filter context is destroyed, so it must not be auto-memory
4963*572c4311Sfengbojiang  * allocated, freed or used elsewhere.
4964*572c4311Sfengbojiang  */
4965*572c4311Sfengbojiang 
RM_CommandFilterArgInsert(RedisModuleCommandFilterCtx * fctx,int pos,RedisModuleString * arg)4966*572c4311Sfengbojiang int RM_CommandFilterArgInsert(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg)
4967*572c4311Sfengbojiang {
4968*572c4311Sfengbojiang     int i;
4969*572c4311Sfengbojiang 
4970*572c4311Sfengbojiang     if (pos < 0 || pos > fctx->argc) return REDISMODULE_ERR;
4971*572c4311Sfengbojiang 
4972*572c4311Sfengbojiang     fctx->argv = zrealloc(fctx->argv, (fctx->argc+1)*sizeof(RedisModuleString *));
4973*572c4311Sfengbojiang     for (i = fctx->argc; i > pos; i--) {
4974*572c4311Sfengbojiang         fctx->argv[i] = fctx->argv[i-1];
4975*572c4311Sfengbojiang     }
4976*572c4311Sfengbojiang     fctx->argv[pos] = arg;
4977*572c4311Sfengbojiang     fctx->argc++;
4978*572c4311Sfengbojiang 
4979*572c4311Sfengbojiang     return REDISMODULE_OK;
4980*572c4311Sfengbojiang }
4981*572c4311Sfengbojiang 
4982*572c4311Sfengbojiang /* Modify the filtered command by replacing an existing argument with a new one.
4983*572c4311Sfengbojiang  * The specified RedisModuleString argument may be used by Redis after the
4984*572c4311Sfengbojiang  * filter context is destroyed, so it must not be auto-memory allocated, freed
4985*572c4311Sfengbojiang  * or used elsewhere.
4986*572c4311Sfengbojiang  */
4987*572c4311Sfengbojiang 
RM_CommandFilterArgReplace(RedisModuleCommandFilterCtx * fctx,int pos,RedisModuleString * arg)4988*572c4311Sfengbojiang int RM_CommandFilterArgReplace(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg)
4989*572c4311Sfengbojiang {
4990*572c4311Sfengbojiang     if (pos < 0 || pos >= fctx->argc) return REDISMODULE_ERR;
4991*572c4311Sfengbojiang 
4992*572c4311Sfengbojiang     decrRefCount(fctx->argv[pos]);
4993*572c4311Sfengbojiang     fctx->argv[pos] = arg;
4994*572c4311Sfengbojiang 
4995*572c4311Sfengbojiang     return REDISMODULE_OK;
4996*572c4311Sfengbojiang }
4997*572c4311Sfengbojiang 
4998*572c4311Sfengbojiang /* Modify the filtered command by deleting an argument at the specified
4999*572c4311Sfengbojiang  * position.
5000*572c4311Sfengbojiang  */
RM_CommandFilterArgDelete(RedisModuleCommandFilterCtx * fctx,int pos)5001*572c4311Sfengbojiang int RM_CommandFilterArgDelete(RedisModuleCommandFilterCtx *fctx, int pos)
5002*572c4311Sfengbojiang {
5003*572c4311Sfengbojiang     int i;
5004*572c4311Sfengbojiang     if (pos < 0 || pos >= fctx->argc) return REDISMODULE_ERR;
5005*572c4311Sfengbojiang 
5006*572c4311Sfengbojiang     decrRefCount(fctx->argv[pos]);
5007*572c4311Sfengbojiang     for (i = pos; i < fctx->argc-1; i++) {
5008*572c4311Sfengbojiang         fctx->argv[i] = fctx->argv[i+1];
5009*572c4311Sfengbojiang     }
5010*572c4311Sfengbojiang     fctx->argc--;
5011*572c4311Sfengbojiang 
5012*572c4311Sfengbojiang     return REDISMODULE_OK;
5013*572c4311Sfengbojiang }
5014*572c4311Sfengbojiang 
5015*572c4311Sfengbojiang /* --------------------------------------------------------------------------
5016*572c4311Sfengbojiang  * Modules API internals
5017*572c4311Sfengbojiang  * -------------------------------------------------------------------------- */
5018*572c4311Sfengbojiang 
5019*572c4311Sfengbojiang /* server.moduleapi dictionary type. Only uses plain C strings since
5020*572c4311Sfengbojiang  * this gets queries from modules. */
5021*572c4311Sfengbojiang 
dictCStringKeyHash(const void * key)5022*572c4311Sfengbojiang uint64_t dictCStringKeyHash(const void *key) {
5023*572c4311Sfengbojiang     return dictGenHashFunction((unsigned char*)key, strlen((char*)key));
5024*572c4311Sfengbojiang }
5025*572c4311Sfengbojiang 
dictCStringKeyCompare(void * privdata,const void * key1,const void * key2)5026*572c4311Sfengbojiang int dictCStringKeyCompare(void *privdata, const void *key1, const void *key2) {
5027*572c4311Sfengbojiang     UNUSED(privdata);
5028*572c4311Sfengbojiang     return strcmp(key1,key2) == 0;
5029*572c4311Sfengbojiang }
5030*572c4311Sfengbojiang 
5031*572c4311Sfengbojiang dictType moduleAPIDictType = {
5032*572c4311Sfengbojiang     dictCStringKeyHash,        /* hash function */
5033*572c4311Sfengbojiang     NULL,                      /* key dup */
5034*572c4311Sfengbojiang     NULL,                      /* val dup */
5035*572c4311Sfengbojiang     dictCStringKeyCompare,     /* key compare */
5036*572c4311Sfengbojiang     NULL,                      /* key destructor */
5037*572c4311Sfengbojiang     NULL                       /* val destructor */
5038*572c4311Sfengbojiang };
5039*572c4311Sfengbojiang 
moduleRegisterApi(const char * funcname,void * funcptr)5040*572c4311Sfengbojiang int moduleRegisterApi(const char *funcname, void *funcptr) {
5041*572c4311Sfengbojiang     return dictAdd(server.moduleapi, (char*)funcname, funcptr);
5042*572c4311Sfengbojiang }
5043*572c4311Sfengbojiang 
5044*572c4311Sfengbojiang #define REGISTER_API(name) \
5045*572c4311Sfengbojiang     moduleRegisterApi("RedisModule_" #name, (void *)(unsigned long)RM_ ## name)
5046*572c4311Sfengbojiang 
5047*572c4311Sfengbojiang /* Global initialization at Redis startup. */
5048*572c4311Sfengbojiang void moduleRegisterCoreAPI(void);
5049*572c4311Sfengbojiang 
moduleInitModulesSystem(void)5050*572c4311Sfengbojiang void moduleInitModulesSystem(void) {
5051*572c4311Sfengbojiang     moduleUnblockedClients = listCreate();
5052*572c4311Sfengbojiang     server.loadmodule_queue = listCreate();
5053*572c4311Sfengbojiang     modules = dictCreate(&modulesDictType,NULL);
5054*572c4311Sfengbojiang 
5055*572c4311Sfengbojiang     /* Set up the keyspace notification susbscriber list and static client */
5056*572c4311Sfengbojiang     moduleKeyspaceSubscribers = listCreate();
5057*572c4311Sfengbojiang     moduleFreeContextReusedClient = createClient(-1);
5058*572c4311Sfengbojiang     moduleFreeContextReusedClient->flags |= CLIENT_MODULE;
5059*572c4311Sfengbojiang 
5060*572c4311Sfengbojiang     /* Set up filter list */
5061*572c4311Sfengbojiang     moduleCommandFilters = listCreate();
5062*572c4311Sfengbojiang 
5063*572c4311Sfengbojiang     moduleRegisterCoreAPI();
5064*572c4311Sfengbojiang     if (pipe(server.module_blocked_pipe) == -1) {
5065*572c4311Sfengbojiang         serverLog(LL_WARNING,
5066*572c4311Sfengbojiang             "Can't create the pipe for module blocking commands: %s",
5067*572c4311Sfengbojiang             strerror(errno));
5068*572c4311Sfengbojiang         exit(1);
5069*572c4311Sfengbojiang     }
5070*572c4311Sfengbojiang     /* Make the pipe non blocking. This is just a best effort aware mechanism
5071*572c4311Sfengbojiang      * and we do not want to block not in the read nor in the write half. */
5072*572c4311Sfengbojiang     anetNonBlock(NULL,server.module_blocked_pipe[0]);
5073*572c4311Sfengbojiang     anetNonBlock(NULL,server.module_blocked_pipe[1]);
5074*572c4311Sfengbojiang 
5075*572c4311Sfengbojiang     /* Create the timers radix tree. */
5076*572c4311Sfengbojiang     Timers = raxNew();
5077*572c4311Sfengbojiang 
5078*572c4311Sfengbojiang     /* Our thread-safe contexts GIL must start with already locked:
5079*572c4311Sfengbojiang      * it is just unlocked when it's safe. */
5080*572c4311Sfengbojiang     pthread_mutex_lock(&moduleGIL);
5081*572c4311Sfengbojiang }
5082*572c4311Sfengbojiang 
5083*572c4311Sfengbojiang /* Load all the modules in the server.loadmodule_queue list, which is
5084*572c4311Sfengbojiang  * populated by `loadmodule` directives in the configuration file.
5085*572c4311Sfengbojiang  * We can't load modules directly when processing the configuration file
5086*572c4311Sfengbojiang  * because the server must be fully initialized before loading modules.
5087*572c4311Sfengbojiang  *
5088*572c4311Sfengbojiang  * The function aborts the server on errors, since to start with missing
5089*572c4311Sfengbojiang  * modules is not considered sane: clients may rely on the existence of
5090*572c4311Sfengbojiang  * given commands, loading AOF also may need some modules to exist, and
5091*572c4311Sfengbojiang  * if this instance is a slave, it must understand commands from master. */
moduleLoadFromQueue(void)5092*572c4311Sfengbojiang void moduleLoadFromQueue(void) {
5093*572c4311Sfengbojiang     listIter li;
5094*572c4311Sfengbojiang     listNode *ln;
5095*572c4311Sfengbojiang 
5096*572c4311Sfengbojiang     listRewind(server.loadmodule_queue,&li);
5097*572c4311Sfengbojiang     while((ln = listNext(&li))) {
5098*572c4311Sfengbojiang         struct moduleLoadQueueEntry *loadmod = ln->value;
5099*572c4311Sfengbojiang         if (moduleLoad(loadmod->path,(void **)loadmod->argv,loadmod->argc)
5100*572c4311Sfengbojiang             == C_ERR)
5101*572c4311Sfengbojiang         {
5102*572c4311Sfengbojiang             serverLog(LL_WARNING,
5103*572c4311Sfengbojiang                 "Can't load module from %s: server aborting",
5104*572c4311Sfengbojiang                 loadmod->path);
5105*572c4311Sfengbojiang             exit(1);
5106*572c4311Sfengbojiang         }
5107*572c4311Sfengbojiang     }
5108*572c4311Sfengbojiang }
5109*572c4311Sfengbojiang 
moduleFreeModuleStructure(struct RedisModule * module)5110*572c4311Sfengbojiang void moduleFreeModuleStructure(struct RedisModule *module) {
5111*572c4311Sfengbojiang     listRelease(module->types);
5112*572c4311Sfengbojiang     listRelease(module->filters);
5113*572c4311Sfengbojiang     sdsfree(module->name);
5114*572c4311Sfengbojiang     zfree(module);
5115*572c4311Sfengbojiang }
5116*572c4311Sfengbojiang 
moduleUnregisterCommands(struct RedisModule * module)5117*572c4311Sfengbojiang void moduleUnregisterCommands(struct RedisModule *module) {
5118*572c4311Sfengbojiang     /* Unregister all the commands registered by this module. */
5119*572c4311Sfengbojiang     dictIterator *di = dictGetSafeIterator(server.commands);
5120*572c4311Sfengbojiang     dictEntry *de;
5121*572c4311Sfengbojiang     while ((de = dictNext(di)) != NULL) {
5122*572c4311Sfengbojiang         struct redisCommand *cmd = dictGetVal(de);
5123*572c4311Sfengbojiang         if (cmd->proc == RedisModuleCommandDispatcher) {
5124*572c4311Sfengbojiang             RedisModuleCommandProxy *cp =
5125*572c4311Sfengbojiang                 (void*)(unsigned long)cmd->getkeys_proc;
5126*572c4311Sfengbojiang             sds cmdname = cp->rediscmd->name;
5127*572c4311Sfengbojiang             if (cp->module == module) {
5128*572c4311Sfengbojiang                 dictDelete(server.commands,cmdname);
5129*572c4311Sfengbojiang                 dictDelete(server.orig_commands,cmdname);
5130*572c4311Sfengbojiang                 sdsfree(cmdname);
5131*572c4311Sfengbojiang                 zfree(cp->rediscmd);
5132*572c4311Sfengbojiang                 zfree(cp);
5133*572c4311Sfengbojiang             }
5134*572c4311Sfengbojiang         }
5135*572c4311Sfengbojiang     }
5136*572c4311Sfengbojiang     dictReleaseIterator(di);
5137*572c4311Sfengbojiang }
5138*572c4311Sfengbojiang 
5139*572c4311Sfengbojiang /* Load a module and initialize it. On success C_OK is returned, otherwise
5140*572c4311Sfengbojiang  * C_ERR is returned. */
moduleLoad(const char * path,void ** module_argv,int module_argc)5141*572c4311Sfengbojiang int moduleLoad(const char *path, void **module_argv, int module_argc) {
5142*572c4311Sfengbojiang     int (*onload)(void *, void **, int);
5143*572c4311Sfengbojiang     void *handle;
5144*572c4311Sfengbojiang     RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
5145*572c4311Sfengbojiang 
5146*572c4311Sfengbojiang     handle = dlopen(path,RTLD_NOW|RTLD_LOCAL);
5147*572c4311Sfengbojiang     if (handle == NULL) {
5148*572c4311Sfengbojiang         serverLog(LL_WARNING, "Module %s failed to load: %s", path, dlerror());
5149*572c4311Sfengbojiang         return C_ERR;
5150*572c4311Sfengbojiang     }
5151*572c4311Sfengbojiang     onload = (int (*)(void *, void **, int))(unsigned long) dlsym(handle,"RedisModule_OnLoad");
5152*572c4311Sfengbojiang     if (onload == NULL) {
5153*572c4311Sfengbojiang         dlclose(handle);
5154*572c4311Sfengbojiang         serverLog(LL_WARNING,
5155*572c4311Sfengbojiang             "Module %s does not export RedisModule_OnLoad() "
5156*572c4311Sfengbojiang             "symbol. Module not loaded.",path);
5157*572c4311Sfengbojiang         return C_ERR;
5158*572c4311Sfengbojiang     }
5159*572c4311Sfengbojiang     if (onload((void*)&ctx,module_argv,module_argc) == REDISMODULE_ERR) {
5160*572c4311Sfengbojiang         if (ctx.module) {
5161*572c4311Sfengbojiang             moduleUnregisterCommands(ctx.module);
5162*572c4311Sfengbojiang             moduleUnregisterSharedAPI(ctx.module);
5163*572c4311Sfengbojiang             moduleUnregisterUsedAPI(ctx.module);
5164*572c4311Sfengbojiang             moduleFreeModuleStructure(ctx.module);
5165*572c4311Sfengbojiang         }
5166*572c4311Sfengbojiang         dlclose(handle);
5167*572c4311Sfengbojiang         serverLog(LL_WARNING,
5168*572c4311Sfengbojiang             "Module %s initialization failed. Module not loaded",path);
5169*572c4311Sfengbojiang         return C_ERR;
5170*572c4311Sfengbojiang     }
5171*572c4311Sfengbojiang 
5172*572c4311Sfengbojiang     /* Redis module loaded! Register it. */
5173*572c4311Sfengbojiang     dictAdd(modules,ctx.module->name,ctx.module);
5174*572c4311Sfengbojiang     ctx.module->handle = handle;
5175*572c4311Sfengbojiang     serverLog(LL_NOTICE,"Module '%s' loaded from %s",ctx.module->name,path);
5176*572c4311Sfengbojiang     moduleFreeContext(&ctx);
5177*572c4311Sfengbojiang     return C_OK;
5178*572c4311Sfengbojiang }
5179*572c4311Sfengbojiang 
5180*572c4311Sfengbojiang 
5181*572c4311Sfengbojiang /* Unload the module registered with the specified name. On success
5182*572c4311Sfengbojiang  * C_OK is returned, otherwise C_ERR is returned and errno is set
5183*572c4311Sfengbojiang  * to the following values depending on the type of error:
5184*572c4311Sfengbojiang  *
5185*572c4311Sfengbojiang  * * ENONET: No such module having the specified name.
5186*572c4311Sfengbojiang  * * EBUSY: The module exports a new data type and can only be reloaded. */
moduleUnload(sds name)5187*572c4311Sfengbojiang int moduleUnload(sds name) {
5188*572c4311Sfengbojiang     struct RedisModule *module = dictFetchValue(modules,name);
5189*572c4311Sfengbojiang 
5190*572c4311Sfengbojiang     if (module == NULL) {
5191*572c4311Sfengbojiang         errno = ENOENT;
5192*572c4311Sfengbojiang         return REDISMODULE_ERR;
5193*572c4311Sfengbojiang     } else if (listLength(module->types)) {
5194*572c4311Sfengbojiang         errno = EBUSY;
5195*572c4311Sfengbojiang         return REDISMODULE_ERR;
5196*572c4311Sfengbojiang     } else if (listLength(module->usedby)) {
5197*572c4311Sfengbojiang         errno = EPERM;
5198*572c4311Sfengbojiang         return REDISMODULE_ERR;
5199*572c4311Sfengbojiang     }
5200*572c4311Sfengbojiang 
5201*572c4311Sfengbojiang     moduleUnregisterCommands(module);
5202*572c4311Sfengbojiang     moduleUnregisterSharedAPI(module);
5203*572c4311Sfengbojiang     moduleUnregisterUsedAPI(module);
5204*572c4311Sfengbojiang     moduleUnregisterFilters(module);
5205*572c4311Sfengbojiang 
5206*572c4311Sfengbojiang     /* Remove any notification subscribers this module might have */
5207*572c4311Sfengbojiang     moduleUnsubscribeNotifications(module);
5208*572c4311Sfengbojiang 
5209*572c4311Sfengbojiang     /* Unregister all the hooks. TODO: Yet no hooks support here. */
5210*572c4311Sfengbojiang 
5211*572c4311Sfengbojiang     /* Unload the dynamic library. */
5212*572c4311Sfengbojiang     if (dlclose(module->handle) == -1) {
5213*572c4311Sfengbojiang         char *error = dlerror();
5214*572c4311Sfengbojiang         if (error == NULL) error = "Unknown error";
5215*572c4311Sfengbojiang         serverLog(LL_WARNING,"Error when trying to close the %s module: %s",
5216*572c4311Sfengbojiang             module->name, error);
5217*572c4311Sfengbojiang     }
5218*572c4311Sfengbojiang 
5219*572c4311Sfengbojiang     /* Remove from list of modules. */
5220*572c4311Sfengbojiang     serverLog(LL_NOTICE,"Module %s unloaded",module->name);
5221*572c4311Sfengbojiang     dictDelete(modules,module->name);
5222*572c4311Sfengbojiang     module->name = NULL; /* The name was already freed by dictDelete(). */
5223*572c4311Sfengbojiang     moduleFreeModuleStructure(module);
5224*572c4311Sfengbojiang 
5225*572c4311Sfengbojiang     return REDISMODULE_OK;
5226*572c4311Sfengbojiang }
5227*572c4311Sfengbojiang 
5228*572c4311Sfengbojiang /* Redis MODULE command.
5229*572c4311Sfengbojiang  *
5230*572c4311Sfengbojiang  * MODULE LOAD <path> [args...] */
moduleCommand(client * c)5231*572c4311Sfengbojiang void moduleCommand(client *c) {
5232*572c4311Sfengbojiang     char *subcmd = c->argv[1]->ptr;
5233*572c4311Sfengbojiang     if (c->argc == 2 && !strcasecmp(subcmd,"help")) {
5234*572c4311Sfengbojiang         const char *help[] = {
5235*572c4311Sfengbojiang "LIST -- Return a list of loaded modules.",
5236*572c4311Sfengbojiang "LOAD <path> [arg ...] -- Load a module library from <path>.",
5237*572c4311Sfengbojiang "UNLOAD <name> -- Unload a module.",
5238*572c4311Sfengbojiang NULL
5239*572c4311Sfengbojiang         };
5240*572c4311Sfengbojiang         addReplyHelp(c, help);
5241*572c4311Sfengbojiang     } else
5242*572c4311Sfengbojiang     if (!strcasecmp(subcmd,"load") && c->argc >= 3) {
5243*572c4311Sfengbojiang         robj **argv = NULL;
5244*572c4311Sfengbojiang         int argc = 0;
5245*572c4311Sfengbojiang 
5246*572c4311Sfengbojiang         if (c->argc > 3) {
5247*572c4311Sfengbojiang             argc = c->argc - 3;
5248*572c4311Sfengbojiang             argv = &c->argv[3];
5249*572c4311Sfengbojiang         }
5250*572c4311Sfengbojiang 
5251*572c4311Sfengbojiang         if (moduleLoad(c->argv[2]->ptr,(void **)argv,argc) == C_OK)
5252*572c4311Sfengbojiang             addReply(c,shared.ok);
5253*572c4311Sfengbojiang         else
5254*572c4311Sfengbojiang             addReplyError(c,
5255*572c4311Sfengbojiang                 "Error loading the extension. Please check the server logs.");
5256*572c4311Sfengbojiang     } else if (!strcasecmp(subcmd,"unload") && c->argc == 3) {
5257*572c4311Sfengbojiang         if (moduleUnload(c->argv[2]->ptr) == C_OK)
5258*572c4311Sfengbojiang             addReply(c,shared.ok);
5259*572c4311Sfengbojiang         else {
5260*572c4311Sfengbojiang             char *errmsg;
5261*572c4311Sfengbojiang             switch(errno) {
5262*572c4311Sfengbojiang             case ENOENT:
5263*572c4311Sfengbojiang                 errmsg = "no such module with that name";
5264*572c4311Sfengbojiang                 break;
5265*572c4311Sfengbojiang             case EBUSY:
5266*572c4311Sfengbojiang                 errmsg = "the module exports one or more module-side data "
5267*572c4311Sfengbojiang                          "types, can't unload";
5268*572c4311Sfengbojiang                 break;
5269*572c4311Sfengbojiang             case EPERM:
5270*572c4311Sfengbojiang                 errmsg = "the module exports APIs used by other modules. "
5271*572c4311Sfengbojiang                          "Please unload them first and try again";
5272*572c4311Sfengbojiang                 break;
5273*572c4311Sfengbojiang             default:
5274*572c4311Sfengbojiang                 errmsg = "operation not possible.";
5275*572c4311Sfengbojiang                 break;
5276*572c4311Sfengbojiang             }
5277*572c4311Sfengbojiang             addReplyErrorFormat(c,"Error unloading module: %s",errmsg);
5278*572c4311Sfengbojiang         }
5279*572c4311Sfengbojiang     } else if (!strcasecmp(subcmd,"list") && c->argc == 2) {
5280*572c4311Sfengbojiang         dictIterator *di = dictGetIterator(modules);
5281*572c4311Sfengbojiang         dictEntry *de;
5282*572c4311Sfengbojiang 
5283*572c4311Sfengbojiang         addReplyMultiBulkLen(c,dictSize(modules));
5284*572c4311Sfengbojiang         while ((de = dictNext(di)) != NULL) {
5285*572c4311Sfengbojiang             sds name = dictGetKey(de);
5286*572c4311Sfengbojiang             struct RedisModule *module = dictGetVal(de);
5287*572c4311Sfengbojiang             addReplyMultiBulkLen(c,4);
5288*572c4311Sfengbojiang             addReplyBulkCString(c,"name");
5289*572c4311Sfengbojiang             addReplyBulkCBuffer(c,name,sdslen(name));
5290*572c4311Sfengbojiang             addReplyBulkCString(c,"ver");
5291*572c4311Sfengbojiang             addReplyLongLong(c,module->ver);
5292*572c4311Sfengbojiang         }
5293*572c4311Sfengbojiang         dictReleaseIterator(di);
5294*572c4311Sfengbojiang     } else {
5295*572c4311Sfengbojiang         addReplySubcommandSyntaxError(c);
5296*572c4311Sfengbojiang         return;
5297*572c4311Sfengbojiang     }
5298*572c4311Sfengbojiang }
5299*572c4311Sfengbojiang 
5300*572c4311Sfengbojiang /* Return the number of registered modules. */
moduleCount(void)5301*572c4311Sfengbojiang size_t moduleCount(void) {
5302*572c4311Sfengbojiang     return dictSize(modules);
5303*572c4311Sfengbojiang }
5304*572c4311Sfengbojiang 
5305*572c4311Sfengbojiang /* Register all the APIs we export. Keep this function at the end of the
5306*572c4311Sfengbojiang  * file so that's easy to seek it to add new entries. */
moduleRegisterCoreAPI(void)5307*572c4311Sfengbojiang void moduleRegisterCoreAPI(void) {
5308*572c4311Sfengbojiang     server.moduleapi = dictCreate(&moduleAPIDictType,NULL);
5309*572c4311Sfengbojiang     server.sharedapi = dictCreate(&moduleAPIDictType,NULL);
5310*572c4311Sfengbojiang     REGISTER_API(Alloc);
5311*572c4311Sfengbojiang     REGISTER_API(Calloc);
5312*572c4311Sfengbojiang     REGISTER_API(Realloc);
5313*572c4311Sfengbojiang     REGISTER_API(Free);
5314*572c4311Sfengbojiang     REGISTER_API(Strdup);
5315*572c4311Sfengbojiang     REGISTER_API(CreateCommand);
5316*572c4311Sfengbojiang     REGISTER_API(SetModuleAttribs);
5317*572c4311Sfengbojiang     REGISTER_API(IsModuleNameBusy);
5318*572c4311Sfengbojiang     REGISTER_API(WrongArity);
5319*572c4311Sfengbojiang     REGISTER_API(ReplyWithLongLong);
5320*572c4311Sfengbojiang     REGISTER_API(ReplyWithError);
5321*572c4311Sfengbojiang     REGISTER_API(ReplyWithSimpleString);
5322*572c4311Sfengbojiang     REGISTER_API(ReplyWithArray);
5323*572c4311Sfengbojiang     REGISTER_API(ReplySetArrayLength);
5324*572c4311Sfengbojiang     REGISTER_API(ReplyWithString);
5325*572c4311Sfengbojiang     REGISTER_API(ReplyWithStringBuffer);
5326*572c4311Sfengbojiang     REGISTER_API(ReplyWithNull);
5327*572c4311Sfengbojiang     REGISTER_API(ReplyWithCallReply);
5328*572c4311Sfengbojiang     REGISTER_API(ReplyWithDouble);
5329*572c4311Sfengbojiang     REGISTER_API(GetSelectedDb);
5330*572c4311Sfengbojiang     REGISTER_API(SelectDb);
5331*572c4311Sfengbojiang     REGISTER_API(OpenKey);
5332*572c4311Sfengbojiang     REGISTER_API(CloseKey);
5333*572c4311Sfengbojiang     REGISTER_API(KeyType);
5334*572c4311Sfengbojiang     REGISTER_API(ValueLength);
5335*572c4311Sfengbojiang     REGISTER_API(ListPush);
5336*572c4311Sfengbojiang     REGISTER_API(ListPop);
5337*572c4311Sfengbojiang     REGISTER_API(StringToLongLong);
5338*572c4311Sfengbojiang     REGISTER_API(StringToDouble);
5339*572c4311Sfengbojiang     REGISTER_API(Call);
5340*572c4311Sfengbojiang     REGISTER_API(CallReplyProto);
5341*572c4311Sfengbojiang     REGISTER_API(FreeCallReply);
5342*572c4311Sfengbojiang     REGISTER_API(CallReplyInteger);
5343*572c4311Sfengbojiang     REGISTER_API(CallReplyType);
5344*572c4311Sfengbojiang     REGISTER_API(CallReplyLength);
5345*572c4311Sfengbojiang     REGISTER_API(CallReplyArrayElement);
5346*572c4311Sfengbojiang     REGISTER_API(CallReplyStringPtr);
5347*572c4311Sfengbojiang     REGISTER_API(CreateStringFromCallReply);
5348*572c4311Sfengbojiang     REGISTER_API(CreateString);
5349*572c4311Sfengbojiang     REGISTER_API(CreateStringFromLongLong);
5350*572c4311Sfengbojiang     REGISTER_API(CreateStringFromString);
5351*572c4311Sfengbojiang     REGISTER_API(CreateStringPrintf);
5352*572c4311Sfengbojiang     REGISTER_API(FreeString);
5353*572c4311Sfengbojiang     REGISTER_API(StringPtrLen);
5354*572c4311Sfengbojiang     REGISTER_API(AutoMemory);
5355*572c4311Sfengbojiang     REGISTER_API(Replicate);
5356*572c4311Sfengbojiang     REGISTER_API(ReplicateVerbatim);
5357*572c4311Sfengbojiang     REGISTER_API(DeleteKey);
5358*572c4311Sfengbojiang     REGISTER_API(UnlinkKey);
5359*572c4311Sfengbojiang     REGISTER_API(StringSet);
5360*572c4311Sfengbojiang     REGISTER_API(StringDMA);
5361*572c4311Sfengbojiang     REGISTER_API(StringTruncate);
5362*572c4311Sfengbojiang     REGISTER_API(SetExpire);
5363*572c4311Sfengbojiang     REGISTER_API(GetExpire);
5364*572c4311Sfengbojiang     REGISTER_API(ZsetAdd);
5365*572c4311Sfengbojiang     REGISTER_API(ZsetIncrby);
5366*572c4311Sfengbojiang     REGISTER_API(ZsetScore);
5367*572c4311Sfengbojiang     REGISTER_API(ZsetRem);
5368*572c4311Sfengbojiang     REGISTER_API(ZsetRangeStop);
5369*572c4311Sfengbojiang     REGISTER_API(ZsetFirstInScoreRange);
5370*572c4311Sfengbojiang     REGISTER_API(ZsetLastInScoreRange);
5371*572c4311Sfengbojiang     REGISTER_API(ZsetFirstInLexRange);
5372*572c4311Sfengbojiang     REGISTER_API(ZsetLastInLexRange);
5373*572c4311Sfengbojiang     REGISTER_API(ZsetRangeCurrentElement);
5374*572c4311Sfengbojiang     REGISTER_API(ZsetRangeNext);
5375*572c4311Sfengbojiang     REGISTER_API(ZsetRangePrev);
5376*572c4311Sfengbojiang     REGISTER_API(ZsetRangeEndReached);
5377*572c4311Sfengbojiang     REGISTER_API(HashSet);
5378*572c4311Sfengbojiang     REGISTER_API(HashGet);
5379*572c4311Sfengbojiang     REGISTER_API(IsKeysPositionRequest);
5380*572c4311Sfengbojiang     REGISTER_API(KeyAtPos);
5381*572c4311Sfengbojiang     REGISTER_API(GetClientId);
5382*572c4311Sfengbojiang     REGISTER_API(GetContextFlags);
5383*572c4311Sfengbojiang     REGISTER_API(PoolAlloc);
5384*572c4311Sfengbojiang     REGISTER_API(CreateDataType);
5385*572c4311Sfengbojiang     REGISTER_API(ModuleTypeSetValue);
5386*572c4311Sfengbojiang     REGISTER_API(ModuleTypeGetType);
5387*572c4311Sfengbojiang     REGISTER_API(ModuleTypeGetValue);
5388*572c4311Sfengbojiang     REGISTER_API(SaveUnsigned);
5389*572c4311Sfengbojiang     REGISTER_API(LoadUnsigned);
5390*572c4311Sfengbojiang     REGISTER_API(SaveSigned);
5391*572c4311Sfengbojiang     REGISTER_API(LoadSigned);
5392*572c4311Sfengbojiang     REGISTER_API(SaveString);
5393*572c4311Sfengbojiang     REGISTER_API(SaveStringBuffer);
5394*572c4311Sfengbojiang     REGISTER_API(LoadString);
5395*572c4311Sfengbojiang     REGISTER_API(LoadStringBuffer);
5396*572c4311Sfengbojiang     REGISTER_API(SaveDouble);
5397*572c4311Sfengbojiang     REGISTER_API(LoadDouble);
5398*572c4311Sfengbojiang     REGISTER_API(SaveFloat);
5399*572c4311Sfengbojiang     REGISTER_API(LoadFloat);
5400*572c4311Sfengbojiang     REGISTER_API(EmitAOF);
5401*572c4311Sfengbojiang     REGISTER_API(Log);
5402*572c4311Sfengbojiang     REGISTER_API(LogIOError);
5403*572c4311Sfengbojiang     REGISTER_API(StringAppendBuffer);
5404*572c4311Sfengbojiang     REGISTER_API(RetainString);
5405*572c4311Sfengbojiang     REGISTER_API(StringCompare);
5406*572c4311Sfengbojiang     REGISTER_API(GetContextFromIO);
5407*572c4311Sfengbojiang     REGISTER_API(GetKeyNameFromIO);
5408*572c4311Sfengbojiang     REGISTER_API(BlockClient);
5409*572c4311Sfengbojiang     REGISTER_API(UnblockClient);
5410*572c4311Sfengbojiang     REGISTER_API(IsBlockedReplyRequest);
5411*572c4311Sfengbojiang     REGISTER_API(IsBlockedTimeoutRequest);
5412*572c4311Sfengbojiang     REGISTER_API(GetBlockedClientPrivateData);
5413*572c4311Sfengbojiang     REGISTER_API(AbortBlock);
5414*572c4311Sfengbojiang     REGISTER_API(Milliseconds);
5415*572c4311Sfengbojiang     REGISTER_API(GetThreadSafeContext);
5416*572c4311Sfengbojiang     REGISTER_API(FreeThreadSafeContext);
5417*572c4311Sfengbojiang     REGISTER_API(ThreadSafeContextLock);
5418*572c4311Sfengbojiang     REGISTER_API(ThreadSafeContextUnlock);
5419*572c4311Sfengbojiang     REGISTER_API(DigestAddStringBuffer);
5420*572c4311Sfengbojiang     REGISTER_API(DigestAddLongLong);
5421*572c4311Sfengbojiang     REGISTER_API(DigestEndSequence);
5422*572c4311Sfengbojiang     REGISTER_API(SubscribeToKeyspaceEvents);
5423*572c4311Sfengbojiang     REGISTER_API(RegisterClusterMessageReceiver);
5424*572c4311Sfengbojiang     REGISTER_API(SendClusterMessage);
5425*572c4311Sfengbojiang     REGISTER_API(GetClusterNodeInfo);
5426*572c4311Sfengbojiang     REGISTER_API(GetClusterNodesList);
5427*572c4311Sfengbojiang     REGISTER_API(FreeClusterNodesList);
5428*572c4311Sfengbojiang     REGISTER_API(CreateTimer);
5429*572c4311Sfengbojiang     REGISTER_API(StopTimer);
5430*572c4311Sfengbojiang     REGISTER_API(GetTimerInfo);
5431*572c4311Sfengbojiang     REGISTER_API(GetMyClusterID);
5432*572c4311Sfengbojiang     REGISTER_API(GetClusterSize);
5433*572c4311Sfengbojiang     REGISTER_API(GetRandomBytes);
5434*572c4311Sfengbojiang     REGISTER_API(GetRandomHexChars);
5435*572c4311Sfengbojiang     REGISTER_API(BlockedClientDisconnected);
5436*572c4311Sfengbojiang     REGISTER_API(SetDisconnectCallback);
5437*572c4311Sfengbojiang     REGISTER_API(GetBlockedClientHandle);
5438*572c4311Sfengbojiang     REGISTER_API(SetClusterFlags);
5439*572c4311Sfengbojiang     REGISTER_API(CreateDict);
5440*572c4311Sfengbojiang     REGISTER_API(FreeDict);
5441*572c4311Sfengbojiang     REGISTER_API(DictSize);
5442*572c4311Sfengbojiang     REGISTER_API(DictSetC);
5443*572c4311Sfengbojiang     REGISTER_API(DictReplaceC);
5444*572c4311Sfengbojiang     REGISTER_API(DictSet);
5445*572c4311Sfengbojiang     REGISTER_API(DictReplace);
5446*572c4311Sfengbojiang     REGISTER_API(DictGetC);
5447*572c4311Sfengbojiang     REGISTER_API(DictGet);
5448*572c4311Sfengbojiang     REGISTER_API(DictDelC);
5449*572c4311Sfengbojiang     REGISTER_API(DictDel);
5450*572c4311Sfengbojiang     REGISTER_API(DictIteratorStartC);
5451*572c4311Sfengbojiang     REGISTER_API(DictIteratorStart);
5452*572c4311Sfengbojiang     REGISTER_API(DictIteratorStop);
5453*572c4311Sfengbojiang     REGISTER_API(DictIteratorReseekC);
5454*572c4311Sfengbojiang     REGISTER_API(DictIteratorReseek);
5455*572c4311Sfengbojiang     REGISTER_API(DictNextC);
5456*572c4311Sfengbojiang     REGISTER_API(DictPrevC);
5457*572c4311Sfengbojiang     REGISTER_API(DictNext);
5458*572c4311Sfengbojiang     REGISTER_API(DictPrev);
5459*572c4311Sfengbojiang     REGISTER_API(DictCompareC);
5460*572c4311Sfengbojiang     REGISTER_API(DictCompare);
5461*572c4311Sfengbojiang     REGISTER_API(ExportSharedAPI);
5462*572c4311Sfengbojiang     REGISTER_API(GetSharedAPI);
5463*572c4311Sfengbojiang     REGISTER_API(RegisterCommandFilter);
5464*572c4311Sfengbojiang     REGISTER_API(UnregisterCommandFilter);
5465*572c4311Sfengbojiang     REGISTER_API(CommandFilterArgsCount);
5466*572c4311Sfengbojiang     REGISTER_API(CommandFilterArgGet);
5467*572c4311Sfengbojiang     REGISTER_API(CommandFilterArgInsert);
5468*572c4311Sfengbojiang     REGISTER_API(CommandFilterArgReplace);
5469*572c4311Sfengbojiang     REGISTER_API(CommandFilterArgDelete);
5470*572c4311Sfengbojiang }
5471