1 
2 #ifndef REDISMODULE_H
3 #define REDISMODULE_H
4 
5 #include <sys/types.h>
6 #include <stdint.h>
7 #include <stdio.h>
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /* ---------------- Defines common between core and modules --------------- */
14 
15 /* Error status return values. */
16 #define REDISMODULE_OK 0
17 #define REDISMODULE_ERR 1
18 
19 /* API versions. */
20 #define REDISMODULE_APIVER_1 1
21 
22 /* API flags and constants */
23 #define REDISMODULE_READ  (1<<0)
24 #define REDISMODULE_WRITE (1<<1)
25 
26 #define REDISMODULE_LIST_HEAD 0
27 #define REDISMODULE_LIST_TAIL 1
28 
29 /* Key types. */
30 #define REDISMODULE_KEYTYPE_EMPTY  0
31 #define REDISMODULE_KEYTYPE_STRING 1
32 #define REDISMODULE_KEYTYPE_LIST   2
33 #define REDISMODULE_KEYTYPE_HASH   3
34 #define REDISMODULE_KEYTYPE_SET    4
35 #define REDISMODULE_KEYTYPE_ZSET   5
36 #define REDISMODULE_KEYTYPE_MODULE 6
37 
38 /* Reply types. */
39 #define REDISMODULE_REPLY_UNKNOWN (-1)
40 #define REDISMODULE_REPLY_STRING    0
41 #define REDISMODULE_REPLY_ERROR     1
42 #define REDISMODULE_REPLY_INTEGER   2
43 #define REDISMODULE_REPLY_ARRAY     3
44 #define REDISMODULE_REPLY_NULL      4
45 
46 /* Postponed array length. */
47 #define REDISMODULE_POSTPONED_ARRAY_LEN -1
48 
49 /* Expire */
50 #define REDISMODULE_NO_EXPIRE -1
51 
52 /* Sorted set API flags. */
53 #define REDISMODULE_ZADD_XX      (1<<0)
54 #define REDISMODULE_ZADD_NX      (1<<1)
55 #define REDISMODULE_ZADD_ADDED   (1<<2)
56 #define REDISMODULE_ZADD_UPDATED (1<<3)
57 #define REDISMODULE_ZADD_NOP     (1<<4)
58 
59 /* Hash API flags. */
60 #define REDISMODULE_HASH_NONE       0
61 #define REDISMODULE_HASH_NX         (1<<0)
62 #define REDISMODULE_HASH_XX         (1<<1)
63 #define REDISMODULE_HASH_CFIELDS    (1<<2)
64 #define REDISMODULE_HASH_EXISTS     (1<<3)
65 
66 /* Context Flags: Info about the current context returned by
67  * RM_GetContextFlags(). */
68 
69 /* The command is running in the context of a Lua script */
70 #define REDISMODULE_CTX_FLAGS_LUA         (1<<0)
71 /* The command is running inside a Redis transaction */
72 #define REDISMODULE_CTX_FLAGS_MULTI       (1<<1)
73 /* The instance is a master */
74 #define REDISMODULE_CTX_FLAGS_MASTER      (1<<2)
75 /* The instance is a slave */
76 #define REDISMODULE_CTX_FLAGS_SLAVE       (1<<3)
77 /* The instance is read-only (usually meaning it's a slave as well) */
78 #define REDISMODULE_CTX_FLAGS_READONLY    (1<<4)
79 /* The instance is running in cluster mode */
80 #define REDISMODULE_CTX_FLAGS_CLUSTER     (1<<5)
81 /* The instance has AOF enabled */
82 #define REDISMODULE_CTX_FLAGS_AOF         (1<<6)
83 /* The instance has RDB enabled */
84 #define REDISMODULE_CTX_FLAGS_RDB         (1<<7)
85 /* The instance has Maxmemory set */
86 #define REDISMODULE_CTX_FLAGS_MAXMEMORY   (1<<8)
87 /* Maxmemory is set and has an eviction policy that may delete keys */
88 #define REDISMODULE_CTX_FLAGS_EVICT       (1<<9)
89 /* Redis is out of memory according to the maxmemory flag. */
90 #define REDISMODULE_CTX_FLAGS_OOM         (1<<10)
91 /* Less than 25% of memory available according to maxmemory. */
92 #define REDISMODULE_CTX_FLAGS_OOM_WARNING (1<<11)
93 /* The command was sent over the replication link. */
94 #define REDISMODULE_CTX_FLAGS_REPLICATED  (1<<12)
95 /* Redis is currently loading either from AOF or RDB. */
96 #define REDISMODULE_CTX_FLAGS_LOADING     (1<<13)
97 
98 #define REDISMODULE_NOTIFY_GENERIC  (1<<2)    /* g */
99 #define REDISMODULE_NOTIFY_STRING   (1<<3)    /* $ */
100 #define REDISMODULE_NOTIFY_LIST     (1<<4)    /* l */
101 #define REDISMODULE_NOTIFY_SET      (1<<5)    /* s */
102 #define REDISMODULE_NOTIFY_HASH     (1<<6)    /* h */
103 #define REDISMODULE_NOTIFY_ZSET     (1<<7)    /* z */
104 #define REDISMODULE_NOTIFY_EXPIRED  (1<<8)    /* x */
105 #define REDISMODULE_NOTIFY_EVICTED  (1<<9)    /* e */
106 #define REDISMODULE_NOTIFY_STREAM   (1<<10)   /* t */
107 #define REDISMODULE_NOTIFY_KEY_MISS (1<<11)   /* m */
108 #define REDISMODULE_NOTIFY_ALL (REDISMODULE_NOTIFY_GENERIC | REDISMODULE_NOTIFY_STRING | REDISMODULE_NOTIFY_LIST | REDISMODULE_NOTIFY_SET | REDISMODULE_NOTIFY_HASH | REDISMODULE_NOTIFY_ZSET | REDISMODULE_NOTIFY_EXPIRED | REDISMODULE_NOTIFY_EVICTED | REDISMODULE_NOTIFY_STREAM | REDISMODULE_NOTIFY_KEY_MISS)      /* A */
109 
110 
111 /* A special pointer that we can use between the core and the module to signal
112  * field deletion, and that is impossible to be a valid pointer. */
113 #define REDISMODULE_HASH_DELETE ((RedisModuleString*)(long)1)
114 
115 /* Error messages. */
116 #define REDISMODULE_ERRORMSG_WRONGTYPE "WRONGTYPE Operation against a key holding the wrong kind of value"
117 
118 #define REDISMODULE_POSITIVE_INFINITE (1.0/0.0)
119 #define REDISMODULE_NEGATIVE_INFINITE (-1.0/0.0)
120 
121 /* Cluster API defines. */
122 #define REDISMODULE_NODE_ID_LEN 40
123 #define REDISMODULE_NODE_MYSELF     (1<<0)
124 #define REDISMODULE_NODE_MASTER     (1<<1)
125 #define REDISMODULE_NODE_SLAVE      (1<<2)
126 #define REDISMODULE_NODE_PFAIL      (1<<3)
127 #define REDISMODULE_NODE_FAIL       (1<<4)
128 #define REDISMODULE_NODE_NOFAILOVER (1<<5)
129 
130 #define REDISMODULE_CLUSTER_FLAG_NONE           0
131 #define REDISMODULE_CLUSTER_FLAG_NO_FAILOVER    (1<<1)
132 #define REDISMODULE_CLUSTER_FLAG_NO_REDIRECTION (1<<2)
133 
134 #define REDISMODULE_NOT_USED(V) ((void) V)
135 
136 /* Bit flags for aux_save_triggers and the aux_load and aux_save callbacks */
137 #define REDISMODULE_AUX_BEFORE_RDB (1<<0)
138 #define REDISMODULE_AUX_AFTER_RDB  (1<<1)
139 
140 /* This type represents a timer handle, and is returned when a timer is
141  * registered and used in order to invalidate a timer. It's just a 64 bit
142  * number, because this is how each timer is represented inside the radix tree
143  * of timers that are going to expire, sorted by expire time. */
144 typedef uint64_t RedisModuleTimerID;
145 
146 /* CommandFilter Flags */
147 
148 /* Do filter RedisModule_Call() commands initiated by module itself. */
149 #define REDISMODULE_CMDFILTER_NOSELF    (1<<0)
150 
151 /* ------------------------- End of common defines ------------------------ */
152 
153 #ifndef REDISMODULE_CORE
154 
155 typedef long long mstime_t;
156 
157 /* Incomplete structures for compiler checks but opaque access. */
158 typedef struct RedisModuleCtx RedisModuleCtx;
159 typedef struct RedisModuleKey RedisModuleKey;
160 typedef struct RedisModuleString RedisModuleString;
161 typedef struct RedisModuleCallReply RedisModuleCallReply;
162 typedef struct RedisModuleIO RedisModuleIO;
163 typedef struct RedisModuleType RedisModuleType;
164 typedef struct RedisModuleDigest RedisModuleDigest;
165 typedef struct RedisModuleBlockedClient RedisModuleBlockedClient;
166 typedef struct RedisModuleClusterInfo RedisModuleClusterInfo;
167 typedef struct RedisModuleDict RedisModuleDict;
168 typedef struct RedisModuleDictIter RedisModuleDictIter;
169 typedef struct RedisModuleCommandFilterCtx RedisModuleCommandFilterCtx;
170 typedef struct RedisModuleCommandFilter RedisModuleCommandFilter;
171 
172 typedef int (*RedisModuleCmdFunc)(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
173 typedef void (*RedisModuleDisconnectFunc)(RedisModuleCtx *ctx, RedisModuleBlockedClient *bc);
174 typedef int (*RedisModuleNotificationFunc)(RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key);
175 typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver);
176 typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value);
177 typedef int (*RedisModuleTypeAuxLoadFunc)(RedisModuleIO *rdb, int encver, int when);
178 typedef void (*RedisModuleTypeAuxSaveFunc)(RedisModuleIO *rdb, int when);
179 typedef void (*RedisModuleTypeRewriteFunc)(RedisModuleIO *aof, RedisModuleString *key, void *value);
180 typedef size_t (*RedisModuleTypeMemUsageFunc)(const void *value);
181 typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value);
182 typedef void (*RedisModuleForkDoneHandler) (int exitcode, int bysignal, void *user_data);
183 typedef void (*RedisModuleTypeFreeFunc)(void *value);
184 typedef void (*RedisModuleClusterMessageReceiver)(RedisModuleCtx *ctx, const char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len);
185 typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data);
186 typedef void (*RedisModuleCommandFilterFunc)(RedisModuleCommandFilterCtx *filter);
187 
188 #define REDISMODULE_TYPE_METHOD_VERSION 2
189 typedef struct RedisModuleTypeMethods {
190     uint64_t version;
191     RedisModuleTypeLoadFunc rdb_load;
192     RedisModuleTypeSaveFunc rdb_save;
193     RedisModuleTypeRewriteFunc aof_rewrite;
194     RedisModuleTypeMemUsageFunc mem_usage;
195     RedisModuleTypeDigestFunc digest;
196     RedisModuleTypeFreeFunc free;
197     RedisModuleTypeAuxLoadFunc aux_load;
198     RedisModuleTypeAuxSaveFunc aux_save;
199     int aux_save_triggers;
200 } RedisModuleTypeMethods;
201 
202 #define REDISMODULE_XAPI_STABLE(X) \
203     X(void *, Alloc, (size_t bytes)) \
204     X(void *, Realloc, (void *ptr, size_t bytes)) \
205     X(void,Free, (void *ptr)) \
206     X(void *, Calloc, (size_t nmemb, size_t size)) \
207     X(char *, Strdup, (const char *str)) \
208     X(int, GetApi, (const char *, void *)) \
209     X(int, CreateCommand, (RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep)) \
210     X(void, SetModuleAttribs, (RedisModuleCtx *ctx, const char *name, int ver, int apiver)) \
211     X(int, IsModuleNameBusy, (const char *name)) \
212     X(int, WrongArity, (RedisModuleCtx *ctx)) \
213     X(int, ReplyWithLongLong, (RedisModuleCtx *ctx, long long ll)) \
214     X(int, GetSelectedDb, (RedisModuleCtx *ctx)) \
215     X(int, SelectDb, (RedisModuleCtx *ctx, int newid)) \
216     X(RedisModuleKey *, OpenKey, (RedisModuleCtx *ctx, RedisModuleString *keyname, int mode)) \
217     X(void, CloseKey, (RedisModuleKey *kp)) \
218     X(int, KeyType, (RedisModuleKey *kp)) \
219     X(size_t, ValueLength, (RedisModuleKey *kp)) \
220     X(int, ListPush, (RedisModuleKey *kp, int where, RedisModuleString *ele)) \
221     X(RedisModuleString *, ListPop, (RedisModuleKey *key, int where)) \
222     X(RedisModuleCallReply *, Call, (RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...)) \
223     X(const char *, CallReplyProto, (RedisModuleCallReply *reply, size_t *len)) \
224     X(void, FreeCallReply, (RedisModuleCallReply *reply)) \
225     X(int, CallReplyType, (RedisModuleCallReply *reply)) \
226     X(long long, CallReplyInteger, (RedisModuleCallReply *reply)) \
227     X(size_t, CallReplyLength, (RedisModuleCallReply *reply)) \
228     X(RedisModuleCallReply *, CallReplyArrayElement, (RedisModuleCallReply *reply, size_t idx)) \
229     X(RedisModuleString *, CreateString, (RedisModuleCtx *ctx, const char *ptr, size_t len)) \
230     X(RedisModuleString *, CreateStringFromLongLong, (RedisModuleCtx *ctx, long long ll)) \
231     X(RedisModuleString *, CreateStringFromString, (RedisModuleCtx *ctx, const RedisModuleString *str)) \
232     X(RedisModuleString *, CreateStringPrintf, (RedisModuleCtx *ctx, const char *fmt, ...)) \
233     X(void, FreeString, (RedisModuleCtx *ctx, RedisModuleString *str)) \
234     X(const char *, StringPtrLen, (const RedisModuleString *str, size_t *len)) \
235     X(int, ReplyWithError, (RedisModuleCtx *ctx, const char *err)) \
236     X(int, ReplyWithSimpleString, (RedisModuleCtx *ctx, const char *msg)) \
237     X(int, ReplyWithArray, (RedisModuleCtx *ctx, long len)) \
238     X(void, ReplySetArrayLength, (RedisModuleCtx *ctx, long len)) \
239     X(int, ReplyWithStringBuffer, (RedisModuleCtx *ctx, const char *buf, size_t len)) \
240     X(int, ReplyWithCString, (RedisModuleCtx *ctx, const char *buf)) \
241     X(int, ReplyWithString, (RedisModuleCtx *ctx, RedisModuleString *str)) \
242     X(int, ReplyWithNull, (RedisModuleCtx *ctx)) \
243     X(int, ReplyWithDouble, (RedisModuleCtx *ctx, double d)) \
244     X(int, ReplyWithCallReply, (RedisModuleCtx *ctx, RedisModuleCallReply *reply)) \
245     X(int, StringToLongLong, (const RedisModuleString *str, long long *ll)) \
246     X(int, StringToDouble, (const RedisModuleString *str, double *d)) \
247     X(void, AutoMemory, (RedisModuleCtx *ctx)) \
248     X(int, Replicate, (RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...)) \
249     X(int, ReplicateVerbatim, (RedisModuleCtx *ctx)) \
250     X(const char *, CallReplyStringPtr, (RedisModuleCallReply *reply, size_t *len)) \
251     X(RedisModuleString *, CreateStringFromCallReply, (RedisModuleCallReply *reply)) \
252     X(int, DeleteKey, (RedisModuleKey *key)) \
253     X(int, UnlinkKey, (RedisModuleKey *key)) \
254     X(int, StringSet, (RedisModuleKey *key, RedisModuleString *str)) \
255     X(char *, StringDMA, (RedisModuleKey *key, size_t *len, int mode)) \
256     X(int, StringTruncate, (RedisModuleKey *key, size_t newlen)) \
257     X(mstime_t, GetExpire, (RedisModuleKey *key)) \
258     X(int, SetExpire, (RedisModuleKey *key, mstime_t expire)) \
259     X(int, ZsetAdd, (RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr)) \
260     X(int, ZsetIncrby, (RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr, double *newscore)) \
261     X(int, ZsetScore, (RedisModuleKey *key, RedisModuleString *ele, double *score)) \
262     X(int, ZsetRem, (RedisModuleKey *key, RedisModuleString *ele, int *deleted)) \
263     X(void ,ZsetRangeStop, (RedisModuleKey *key)) \
264     X(int, ZsetFirstInScoreRange, (RedisModuleKey *key, double min, double max, int minex, int maxex)) \
265     X(int, ZsetLastInScoreRange, (RedisModuleKey *key, double min, double max, int minex, int maxex)) \
266     X(int, ZsetFirstInLexRange, (RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max)) \
267     X(int, ZsetLastInLexRange, (RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max)) \
268     X(RedisModuleString *, ZsetRangeCurrentElement, (RedisModuleKey *key, double *score)) \
269     X(int, ZsetRangeNext, (RedisModuleKey *key)) \
270     X(int, ZsetRangePrev, (RedisModuleKey *key)) \
271     X(int, ZsetRangeEndReached, (RedisModuleKey *key)) \
272     X(int, HashSet, (RedisModuleKey *key, int flags, ...)) \
273     X(int, HashGet, (RedisModuleKey *key, int flags, ...)) \
274     X(int, IsKeysPositionRequest, (RedisModuleCtx *ctx)) \
275     X(void, KeyAtPos, (RedisModuleCtx *ctx, int pos)) \
276     X(unsigned long long, GetClientId, (RedisModuleCtx *ctx)) \
277     X(int, GetContextFlags, (RedisModuleCtx *ctx)) \
278     X(void *, PoolAlloc, (RedisModuleCtx *ctx, size_t bytes)) \
279     X(RedisModuleType *, CreateDataType, (RedisModuleCtx *ctx, const char *name, int encver, RedisModuleTypeMethods *typemethods)) \
280     X(int,ModuleTypeSetValue, (RedisModuleKey *key, RedisModuleType *mt, void *value)) \
281     X(RedisModuleType *, ModuleTypeGetType, (RedisModuleKey *key)) \
282     X(void *, ModuleTypeGetValue, (RedisModuleKey *key)) \
283     X(void, SaveUnsigned, (RedisModuleIO *io, uint64_t value)) \
284     X(uint64_t, LoadUnsigned, (RedisModuleIO *io)) \
285     X(void, SaveSigned, (RedisModuleIO *io, int64_t value)) \
286     X(int64_t, LoadSigned, (RedisModuleIO *io)) \
287     X(void, EmitAOF, (RedisModuleIO *io, const char *cmdname, const char *fmt, ...)) \
288     X(void, SaveString, (RedisModuleIO *io, RedisModuleString *s)) \
289     X(void, SaveStringBuffer, (RedisModuleIO *io, const char *str, size_t len)) \
290     X(RedisModuleString *, LoadString, (RedisModuleIO *io)) \
291     X(char *, LoadStringBuffer, (RedisModuleIO *io, size_t *lenptr)) \
292     X(void, SaveDouble, (RedisModuleIO *io, double value)) \
293     X(double, LoadDouble, (RedisModuleIO *io)) \
294     X(void, SaveFloat, (RedisModuleIO *io, float value)) \
295     X(float, LoadFloat, (RedisModuleIO *io)) \
296     X(void, Log, (RedisModuleCtx *ctx, const char *level, const char *fmt, ...)) \
297     X(void, LogIOError, (RedisModuleIO *io, const char *levelstr, const char *fmt, ...)) \
298     X(int, StringAppendBuffer, (RedisModuleCtx *ctx, RedisModuleString *str, const char *buf, size_t len)) \
299     X(void, RetainString, (RedisModuleCtx *ctx, RedisModuleString *str)) \
300     X(int, StringCompare, (RedisModuleString *a, RedisModuleString *b)) \
301     X(RedisModuleCtx *, GetContextFromIO, (RedisModuleIO *io)) \
302     X(const RedisModuleString *, GetKeyNameFromIO, (RedisModuleIO *io)) \
303     X(long long, Milliseconds, (void)) \
304     X(void, DigestAddStringBuffer, (RedisModuleDigest *md, unsigned char *ele, size_t len)) \
305     X(void, DigestAddLongLong, (RedisModuleDigest *md, long long ele)) \
306     X(void, DigestEndSequence, (RedisModuleDigest *md)) \
307     X(RedisModuleDict *, CreateDict, (RedisModuleCtx *ctx)) \
308     X(void, FreeDict, (RedisModuleCtx *ctx, RedisModuleDict *d)) \
309     X(uint64_t, DictSize, (RedisModuleDict *d)) \
310     X(int, DictSetC, (RedisModuleDict *d, void *key, size_t keylen, void *ptr)) \
311     X(int, DictReplaceC, (RedisModuleDict *d, void *key, size_t keylen, void *ptr)) \
312     X(int, DictSet, (RedisModuleDict *d, RedisModuleString *key, void *ptr)) \
313     X(int, DictReplace, (RedisModuleDict *d, RedisModuleString *key, void *ptr)) \
314     X(void *, DictGetC, (RedisModuleDict *d, void *key, size_t keylen, int *nokey)) \
315     X(void *, DictGet, (RedisModuleDict *d, RedisModuleString *key, int *nokey)) \
316     X(int, DictDelC, (RedisModuleDict *d, void *key, size_t keylen, void *oldval)) \
317     X(int, DictDel, (RedisModuleDict *d, RedisModuleString *key, void *oldval)) \
318     X(RedisModuleDictIter *, DictIteratorStartC, (RedisModuleDict *d, const char *op, void *key, size_t keylen)) \
319     X(RedisModuleDictIter *, DictIteratorStart, (RedisModuleDict *d, const char *op, RedisModuleString *key)) \
320     X(void, DictIteratorStop, (RedisModuleDictIter *di)) \
321     X(int, DictIteratorReseekC, (RedisModuleDictIter *di, const char *op, void *key, size_t keylen)) \
322     X(int, DictIteratorReseek, (RedisModuleDictIter *di, const char *op, RedisModuleString *key)) \
323     X(void *, DictNextC, (RedisModuleDictIter *di, size_t *keylen, void **dataptr)) \
324     X(void *, DictPrevC, (RedisModuleDictIter *di, size_t *keylen, void **dataptr)) \
325     X(RedisModuleString *, DictNext, (RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr)) \
326     X(RedisModuleString *, DictPrev, (RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr)) \
327     X(int, DictCompareC, (RedisModuleDictIter *di, const char *op, void *key, size_t keylen)) \
328     X(int, DictCompare, (RedisModuleDictIter *di, const char *op, RedisModuleString *key)) \
329     X(int, GetServerVersion, ())
330 
331 /* Experimental APIs */
332 
333 #define REDISMODULE_EXPERIMENTAL_API_VERSION 3
334 
335 #define REDISMODULE_XAPI_EXPERIMENTAL(X) \
336     X(RedisModuleBlockedClient *, BlockClient, (RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms)) \
337     X(int, UnblockClient, (RedisModuleBlockedClient *bc, void *privdata)) \
338     X(int, IsBlockedReplyRequest, (RedisModuleCtx *ctx)) \
339     X(int, IsBlockedTimeoutRequest, (RedisModuleCtx *ctx)) \
340     X(void *, GetBlockedClientPrivateData, (RedisModuleCtx *ctx)) \
341     X(RedisModuleBlockedClient *, GetBlockedClientHandle, (RedisModuleCtx *ctx)) \
342     X(int, AbortBlock, (RedisModuleBlockedClient *bc)) \
343     X(RedisModuleCtx *, GetThreadSafeContext, (RedisModuleBlockedClient *bc)) \
344     X(void, FreeThreadSafeContext, (RedisModuleCtx *ctx)) \
345     X(void, ThreadSafeContextLock, (RedisModuleCtx *ctx)) \
346     X(void, ThreadSafeContextUnlock, (RedisModuleCtx *ctx)) \
347     X(int, SubscribeToKeyspaceEvents, (RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc cb)) \
348     X(int, BlockedClientDisconnected, (RedisModuleCtx *ctx)) \
349     X(void, RegisterClusterMessageReceiver, (RedisModuleCtx *ctx, uint8_t type, RedisModuleClusterMessageReceiver callback)) \
350     X(int, SendClusterMessage, (RedisModuleCtx *ctx, char *target_id, uint8_t type, unsigned char *msg, uint32_t len)) \
351     X(int, GetClusterNodeInfo, (RedisModuleCtx *ctx, const char *id, char *ip, char *master_id, int *port, int *flags)) \
352     X(char **, GetClusterNodesList, (RedisModuleCtx *ctx, size_t *numnodes)) \
353     X(void, FreeClusterNodesList, (char **ids)) \
354     X(RedisModuleTimerID, CreateTimer, (RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data)) \
355     X(int, StopTimer, (RedisModuleCtx *ctx, RedisModuleTimerID id, void **data)) \
356     X(int, GetTimerInfo, (RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remaining, void **data)) \
357     X(const char *, GetMyClusterID, (void)) \
358     X(size_t, GetClusterSize, (void)) \
359     X(void, GetRandomBytes, (unsigned char *dst, size_t len)) \
360     X(void, GetRandomHexChars, (char *dst, size_t len)) \
361     X(void, SetDisconnectCallback, (RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback)) \
362     X(void, SetClusterFlags, (RedisModuleCtx *ctx, uint64_t flags)) \
363     X(int, ExportSharedAPI, (RedisModuleCtx *ctx, const char *apiname, void *func)) \
364     X(void *, GetSharedAPI, (RedisModuleCtx *ctx, const char *apiname)) \
365     X(RedisModuleCommandFilter *, RegisterCommandFilter, (RedisModuleCtx *ctx, RedisModuleCommandFilterFunc cb, int flags)) \
366     X(int, UnregisterCommandFilter, (RedisModuleCtx *ctx, RedisModuleCommandFilter *filter)) \
367     X(int, CommandFilterArgsCount, (RedisModuleCommandFilterCtx *fctx)) \
368     X(const RedisModuleString *, CommandFilterArgGet, (RedisModuleCommandFilterCtx *fctx, int pos)) \
369     X(int, CommandFilterArgInsert, (RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg)) \
370     X(int, CommandFilterArgReplace, (RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg)) \
371     X(int, CommandFilterArgDelete, (RedisModuleCommandFilterCtx *fctx, int pos))
372 
373 #define REDISMODULE_XAPI_ENTERPRISE(X) \
374     X(int, AvoidReplicaTraffic, ()) \
375     X(int, Fork, (RedisModuleForkDoneHandler cb, void *user_data)) \
376     X(int, ExitFromChild, (int retcode)) \
377     X(int, KillForkChild, (int child_pid))
378 
379 #ifdef REDISMODULE_EXPERIMENTAL_API
380 #define REDISMODULE_XAPI(X) REDISMODULE_XAPI_STABLE(X) REDISMODULE_XAPI_EXPERIMENTAL(X) REDISMODULE_XAPI_ENTERPRISE(X)
381 #else
382 #define REDISMODULE_XAPI(X) REDISMODULE_XAPI_STABLE(X) REDISMODULE_XAPI_ENTERPRISE(X)
383 #endif
384 
385 typedef int (*RedisModule_GetApiFunctionType)(const char *name, void *pp);
386 
387 #pragma push_macro("X")
388 #define X(TYPE, NAME, ARGS) \
389     extern TYPE (*RedisModule_##NAME) ARGS;
390 REDISMODULE_XAPI(X)
391 #undef X
392 #pragma pop_macro("X")
393 
394 /* This is included inline inside each Redis module. */
395 
396 static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) __attribute__((unused));
397 
RedisModule_Init(RedisModuleCtx * ctx,const char * name,int ver,int apiver)398 static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) {
399     RedisModule_GetApiFunctionType getapifuncptr = (RedisModule_GetApiFunctionType)((void **)ctx)[0];
400 
401 #pragma push_macro("X")
402 #define X(TYPE, NAME, ARGS) getapifuncptr("RedisModule_" #NAME, (void *)&RedisModule_##NAME);
403     REDISMODULE_XAPI(X)
404 #undef X
405 #pragma pop_macro("X")
406 
407     if (RedisModule_IsModuleNameBusy && RedisModule_IsModuleNameBusy(name)) {
408         return REDISMODULE_ERR;
409     }
410     RedisModule_SetModuleAttribs(ctx,name,ver,apiver);
411     return REDISMODULE_OK;
412 }
413 
414 #define REDISMODULE__INIT_WITH_NULL(TYPE, NAME, ARGS) \
415     TYPE (*RedisModule_##NAME)ARGS = NULL;
416 #define REDISMODULE_INIT_SYMBOLS() REDISMODULE_XAPI(REDISMODULE__INIT_WITH_NULL)
417 
418 #else
419 
420 /* Things only defined for the modules core, not exported to modules
421  * including this file. */
422 #define RedisModuleString robj
423 
424 #endif /* REDISMODULE_CORE */
425 
426 #ifdef __cplusplus
427 }
428 #endif
429 
430 #endif /* REDISMOUDLE_H */
431