Add updated version of Redis modules
[ric-plt/dbaas.git] / redismodule / src / exstrings.c
1 /*
2  * Copyright (c) 2018-2020 Nokia.
3  *
4  *   Licensed under the Apache License, Version 2.0 (the "License");
5  *   you may not use this file except in compliance with the License.
6  *   You may obtain a copy of the License at
7  *
8  *       http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *   Unless required by applicable law or agreed to in writing, software
11  *   distributed under the License is distributed on an "AS IS" BASIS,
12  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *   See the License for the specific language governing permissions and
14  *   limitations under the License.
15  */
16
17 /*
18  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19  * platform project (RICP).
20  */
21
22 #include "redismodule.h"
23 #include <string.h>
24 #include <pthread.h>
25 #include <stdbool.h>
26
27 #ifdef __UT__
28 #include "exstringsStub.h"
29 #include "commonStub.h"
30 #endif
31
32
33 /* make sure the response is not NULL or an error.
34 sends the error to the client and exit the current function if its */
35 #define  ASSERT_NOERROR(r) \
36     if (r == NULL) { \
37         return RedisModule_ReplyWithError(ctx,"ERR reply is NULL"); \
38     } else if (RedisModule_CallReplyType(r) == REDISMODULE_REPLY_ERROR) { \
39         return RedisModule_ReplyWithCallReply(ctx,r); \
40     }
41
42 #define OBJ_OP_NO 0
43 #define OBJ_OP_XX (1<<1)     /* OP if key exist */
44 #define OBJ_OP_NX (1<<2)     /* OP if key not exist */
45 #define OBJ_OP_IE (1<<4)     /* OP if equal old value */
46 #define OBJ_OP_NE (1<<5)     /* OP if not equal old value */
47
48 #define DEF_COUNT     50
49 #define ZERO          0
50 #define MATCH_STR     "MATCH"
51 #define COUNT_STR     "COUNT"
52 #define SCANARGC      5
53
54 RedisModuleString *def_count_str = NULL, *match_str = NULL, *count_str = NULL, *zero_str = NULL;
55
56 void InitStaticVariable()
57 {
58     if (def_count_str == NULL)
59         def_count_str = RedisModule_CreateStringFromLongLong(NULL, DEF_COUNT);
60     if (match_str == NULL)
61         match_str = RedisModule_CreateString(NULL, MATCH_STR, sizeof(MATCH_STR));
62     if (count_str == NULL)
63         count_str = RedisModule_CreateString(NULL, COUNT_STR, sizeof(COUNT_STR));
64     if (zero_str == NULL)
65         zero_str = RedisModule_CreateStringFromLongLong(NULL, ZERO);
66
67     return;
68 }
69
70 int getKeyType(RedisModuleCtx *ctx, RedisModuleString *key_str)
71 {
72     RedisModuleKey *key = RedisModule_OpenKey(ctx, key_str, REDISMODULE_READ);
73     int type = RedisModule_KeyType(key);
74     RedisModule_CloseKey(key);
75     return type;
76 }
77
78 bool replyContentsEqualString(RedisModuleCallReply *reply, RedisModuleString *expected_value)
79 {
80     size_t replylen = 0, expectedlen = 0;
81     const char *expectedval = RedisModule_StringPtrLen(expected_value, &expectedlen);
82     const char *replyval = RedisModule_CallReplyStringPtr(reply, &replylen);
83     return replyval &&
84            expectedlen == replylen &&
85            !strncmp(expectedval, replyval, replylen);
86 }
87
88 typedef struct _SetParams {
89     RedisModuleString **key_val_pairs;
90     size_t length;
91 } SetParams;
92
93 typedef struct _PubParams {
94     RedisModuleString **channel_msg_pairs;
95     size_t length;
96 } PubParams;
97
98 typedef struct _DelParams {
99     RedisModuleString **keys;
100     size_t length;
101 } DelParams;
102
103 void multiPubCommand(RedisModuleCtx *ctx, PubParams* pubParams)
104 {
105     RedisModuleCallReply *reply = NULL;
106     for (unsigned int i = 0 ; i < pubParams->length ; i += 2) {
107         reply = RedisModule_Call(ctx, "PUBLISH", "v", pubParams->channel_msg_pairs + i, 2);
108         RedisModule_FreeCallReply(reply);
109     }
110 }
111
112 int setStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
113                                        int argc, const int flag)
114 {
115     RedisModuleString *oldvalstr = NULL;
116     RedisModuleCallReply *reply = NULL;
117
118     if (argc < 4)
119         return RedisModule_WrongArity(ctx);
120     else
121         oldvalstr = argv[3];
122
123     /*Check if key type is string*/
124     RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1],
125         REDISMODULE_READ);
126     int type = RedisModule_KeyType(key);
127     RedisModule_CloseKey(key);
128
129     if (type == REDISMODULE_KEYTYPE_EMPTY) {
130         if (flag == OBJ_OP_IE){
131             RedisModule_ReplyWithNull(ctx);
132             return REDISMODULE_OK;
133         }
134     } else if (type != REDISMODULE_KEYTYPE_STRING) {
135         return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE);
136     }
137
138     /*Get the value*/
139     reply = RedisModule_Call(ctx, "GET", "s", argv[1]);
140     ASSERT_NOERROR(reply)
141     size_t curlen=0, oldvallen=0;
142     const char *oldval = RedisModule_StringPtrLen(oldvalstr, &oldvallen);
143     const char *curval = RedisModule_CallReplyStringPtr(reply, &curlen);
144     if (((flag == OBJ_OP_IE) &&
145         (!curval || (oldvallen != curlen) || strncmp(oldval, curval, curlen)))
146         ||
147         ((flag == OBJ_OP_NE) && curval && (oldvallen == curlen) &&
148           !strncmp(oldval, curval, curlen))) {
149         RedisModule_FreeCallReply(reply);
150         return RedisModule_ReplyWithNull(ctx);
151     }
152     RedisModule_FreeCallReply(reply);
153
154     /* Prepare the arguments for the command. */
155     int i, j=0, cmdargc=argc-2;
156     RedisModuleString *cmdargv[cmdargc];
157     for (i = 1; i < argc; i++) {
158         if (i == 3)
159             continue;
160         cmdargv[j++] = argv[i];
161     }
162
163     /* Call the command and pass back the reply. */
164     reply = RedisModule_Call(ctx, "SET", "v!", cmdargv, cmdargc);
165     ASSERT_NOERROR(reply)
166     RedisModule_ReplyWithCallReply(ctx, reply);
167
168     RedisModule_FreeCallReply(reply);
169     return REDISMODULE_OK;
170 }
171
172 int SetIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
173 {
174     RedisModule_AutoMemory(ctx);
175     return setStringGenericCommand(ctx, argv, argc, OBJ_OP_IE);
176 }
177
178 int SetNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
179 {
180     RedisModule_AutoMemory(ctx);
181     return setStringGenericCommand(ctx, argv, argc, OBJ_OP_NE);
182 }
183
184 int delStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
185                                        int argc, const int flag)
186 {
187     RedisModuleString *oldvalstr = NULL;
188     RedisModuleCallReply *reply = NULL;
189
190     if (argc == 3)
191         oldvalstr = argv[2];
192     else
193         return RedisModule_WrongArity(ctx);
194
195     /*Check if key type is string*/
196     RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1],
197         REDISMODULE_READ);
198     int type = RedisModule_KeyType(key);
199     RedisModule_CloseKey(key);
200
201     if (type == REDISMODULE_KEYTYPE_EMPTY) {
202         return RedisModule_ReplyWithLongLong(ctx, 0);
203     } else if (type != REDISMODULE_KEYTYPE_STRING) {
204         return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE);
205     }
206
207     /*Get the value*/
208     reply = RedisModule_Call(ctx, "GET", "s", argv[1]);
209     ASSERT_NOERROR(reply)
210     size_t curlen = 0, oldvallen = 0;
211     const char *oldval = RedisModule_StringPtrLen(oldvalstr, &oldvallen);
212     const char *curval = RedisModule_CallReplyStringPtr(reply, &curlen);
213     if (((flag == OBJ_OP_IE) &&
214         (!curval || (oldvallen != curlen) || strncmp(oldval, curval, curlen)))
215         ||
216         ((flag == OBJ_OP_NE) && curval && (oldvallen == curlen) &&
217           !strncmp(oldval, curval, curlen))) {
218         RedisModule_FreeCallReply(reply);
219         return RedisModule_ReplyWithLongLong(ctx, 0);
220     }
221     RedisModule_FreeCallReply(reply);
222
223     /* Prepare the arguments for the command. */
224     int cmdargc=1;
225     RedisModuleString *cmdargv[1];
226     cmdargv[0] = argv[1];
227
228     /* Call the command and pass back the reply. */
229     reply = RedisModule_Call(ctx, "UNLINK", "v!", cmdargv, cmdargc);
230     ASSERT_NOERROR(reply)
231     RedisModule_ReplyWithCallReply(ctx, reply);
232
233     RedisModule_FreeCallReply(reply);
234     return REDISMODULE_OK;
235 }
236
237 int DelIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
238 {
239     RedisModule_AutoMemory(ctx);
240     return delStringGenericCommand(ctx, argv, argc, OBJ_OP_IE);
241 }
242
243 int DelNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
244 {
245     RedisModule_AutoMemory(ctx);
246     return delStringGenericCommand(ctx, argv, argc, OBJ_OP_NE);
247 }
248 int setPubStringCommon(RedisModuleCtx *ctx, SetParams* setParamsPtr, PubParams* pubParamsPtr)
249 {
250     RedisModuleCallReply *setReply;
251     setReply = RedisModule_Call(ctx, "MSET", "v!", setParamsPtr->key_val_pairs, setParamsPtr->length);
252     ASSERT_NOERROR(setReply)
253     multiPubCommand(ctx, pubParamsPtr);
254     RedisModule_ReplyWithCallReply(ctx, setReply);
255     RedisModule_FreeCallReply(setReply);
256     return REDISMODULE_OK;
257 }
258
259 int SetPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
260 {
261     if (argc < 5 || (argc % 2) == 0)
262         return RedisModule_WrongArity(ctx);
263
264     RedisModule_AutoMemory(ctx);
265     SetParams setParams = {
266                            .key_val_pairs = argv + 1,
267                            .length = argc - 3
268                           };
269     PubParams pubParams = {
270                            .channel_msg_pairs = argv + 1 + setParams.length,
271                            .length = 2
272                           };
273
274     return setPubStringCommon(ctx, &setParams, &pubParams);
275 }
276
277 int SetMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
278 {
279     if (argc < 7 || (argc % 2) == 0)
280         return RedisModule_WrongArity(ctx);
281
282     RedisModule_AutoMemory(ctx);
283     long long setPairsCount, pubPairsCount;
284     RedisModule_StringToLongLong(argv[1], &setPairsCount);
285     RedisModule_StringToLongLong(argv[2], &pubPairsCount);
286     if (setPairsCount < 1 || pubPairsCount < 1)
287         return RedisModule_ReplyWithError(ctx, "ERR SET_PAIR_COUNT and PUB_PAIR_COUNT must be greater than zero");
288
289     long long setLen, pubLen;
290     setLen = 2*setPairsCount;
291     pubLen = 2*pubPairsCount;
292
293     if (setLen + pubLen + 3 != argc)
294         return RedisModule_ReplyWithError(ctx, "ERR SET_PAIR_COUNT or PUB_PAIR_COUNT do not match the total pair count");
295
296     SetParams setParams = {
297                            .key_val_pairs = argv + 3,
298                            .length = setLen
299                           };
300     PubParams pubParams = {
301                            .channel_msg_pairs = argv + 3 + setParams.length,
302                            .length = pubLen
303                           };
304
305     return setPubStringCommon(ctx, &setParams, &pubParams);
306 }
307
308 int setIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
309 {
310     SetParams setParams = {
311                            .key_val_pairs = argv + 1,
312                            .length = 2
313                           };
314     PubParams pubParams = {
315                            .channel_msg_pairs = argv + 4,
316                            .length = argc - 4
317                           };
318     RedisModuleString *key = setParams.key_val_pairs[0];
319     RedisModuleString *oldvalstr = argv[3];
320
321     int type = getKeyType(ctx, key);
322     if (flag == OBJ_OP_IE && type == REDISMODULE_KEYTYPE_EMPTY) {
323         return RedisModule_ReplyWithNull(ctx);
324     } else if (type != REDISMODULE_KEYTYPE_STRING && type != REDISMODULE_KEYTYPE_EMPTY) {
325         return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
326     }
327
328     RedisModuleCallReply *reply = RedisModule_Call(ctx, "GET", "s", key);
329     ASSERT_NOERROR(reply)
330     bool is_equal = replyContentsEqualString(reply, oldvalstr);
331     RedisModule_FreeCallReply(reply);
332     if ((flag == OBJ_OP_IE && !is_equal) ||
333         (flag == OBJ_OP_NE && is_equal)) {
334         return RedisModule_ReplyWithNull(ctx);
335     }
336
337     return setPubStringCommon(ctx, &setParams, &pubParams);
338 }
339
340 int SetIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
341 {
342     if (argc != 6)
343         return RedisModule_WrongArity(ctx);
344
345     RedisModule_AutoMemory(ctx);
346     return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
347 }
348
349 int SetIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
350 {
351     if (argc < 6 || (argc % 2) != 0)
352         return RedisModule_WrongArity(ctx);
353
354     RedisModule_AutoMemory(ctx);
355     return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
356 }
357
358 int SetNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
359 {
360     if (argc != 6)
361         return RedisModule_WrongArity(ctx);
362
363     RedisModule_AutoMemory(ctx);
364     return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE);
365 }
366
367 int setXXNXPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
368 {
369     SetParams setParams = {
370                            .key_val_pairs = argv + 1,
371                            .length = 2
372                           };
373     PubParams pubParams = {
374                            .channel_msg_pairs = argv + 3,
375                            .length = argc - 3
376                           };
377     RedisModuleString *key = setParams.key_val_pairs[0];
378
379     int type = getKeyType(ctx, key);
380     if ((flag == OBJ_OP_XX && type == REDISMODULE_KEYTYPE_EMPTY) ||
381         (flag == OBJ_OP_NX && type == REDISMODULE_KEYTYPE_STRING)) {
382         return RedisModule_ReplyWithNull(ctx);
383     } else if (type != REDISMODULE_KEYTYPE_STRING && type != REDISMODULE_KEYTYPE_EMPTY) {
384         RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
385         return REDISMODULE_OK;
386     }
387
388     return setPubStringCommon(ctx, &setParams, &pubParams);
389 }
390
391 int SetNXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
392 {
393     if (argc != 5)
394         return RedisModule_WrongArity(ctx);
395
396     RedisModule_AutoMemory(ctx);
397     return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_NX);
398 }
399
400 int SetNXMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
401 {
402     if (argc < 5 || (argc % 2) == 0)
403         return RedisModule_WrongArity(ctx);
404
405     RedisModule_AutoMemory(ctx);
406     return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_NX);
407 }
408
409 int SetXXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
410 {
411     if (argc != 5)
412         return RedisModule_WrongArity(ctx);
413
414     RedisModule_AutoMemory(ctx);
415     return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_XX);
416 }
417
418 int delPubStringCommon(RedisModuleCtx *ctx, DelParams *delParamsPtr, PubParams *pubParamsPtr)
419 {
420     RedisModuleCallReply *reply = RedisModule_Call(ctx, "UNLINK", "v!", delParamsPtr->keys, delParamsPtr->length);
421     ASSERT_NOERROR(reply)
422     int replytype = RedisModule_CallReplyType(reply);
423     if (replytype == REDISMODULE_REPLY_NULL) {
424         RedisModule_ReplyWithNull(ctx);
425     } else if (RedisModule_CallReplyInteger(reply) == 0) {
426         RedisModule_ReplyWithCallReply(ctx, reply);
427     } else {
428         RedisModule_ReplyWithCallReply(ctx, reply);
429         multiPubCommand(ctx, pubParamsPtr);
430     }
431     RedisModule_FreeCallReply(reply);
432     return REDISMODULE_OK;
433 }
434
435 int DelPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
436 {
437     if (argc < 4)
438         return RedisModule_WrongArity(ctx);
439
440     RedisModule_AutoMemory(ctx);
441     DelParams delParams = {
442                            .keys = argv + 1,
443                            .length = argc - 3
444                           };
445     PubParams pubParams = {
446                            .channel_msg_pairs = argv + 1 + delParams.length,
447                            .length = 2
448                           };
449
450     return delPubStringCommon(ctx, &delParams, &pubParams);
451 }
452
453 int DelMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
454 {
455     if (argc < 6)
456         return RedisModule_WrongArity(ctx);
457
458     RedisModule_AutoMemory(ctx);
459     long long delCount, pubPairsCount;
460     RedisModule_StringToLongLong(argv[1], &delCount);
461     RedisModule_StringToLongLong(argv[2], &pubPairsCount);
462     if (delCount < 1 || pubPairsCount < 1)
463         return RedisModule_ReplyWithError(ctx, "ERR DEL_COUNT and PUB_PAIR_COUNT must be greater than zero");
464
465     long long delLen, pubLen;
466     delLen = delCount;
467     pubLen = 2*pubPairsCount;
468     if (delLen + pubLen + 3 != argc)
469         return RedisModule_ReplyWithError(ctx, "ERR DEL_COUNT or PUB_PAIR_COUNT do not match the total pair count");
470
471     DelParams delParams = {
472                            .keys = argv + 3,
473                            .length = delLen
474                           };
475     PubParams pubParams = {
476                            .channel_msg_pairs = argv + 3 + delParams.length,
477                            .length = pubLen
478                           };
479
480     return delPubStringCommon(ctx, &delParams, &pubParams);
481 }
482
483 int delIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
484 {
485     DelParams delParams = {
486                            .keys = argv + 1,
487                            .length = 1
488                           };
489     PubParams pubParams = {
490                            .channel_msg_pairs = argv + 3,
491                            .length = argc - 3
492                           };
493     RedisModuleString *key = argv[1];
494     RedisModuleString *oldvalstr = argv[2];
495
496     int type = getKeyType(ctx, key);
497     if (type == REDISMODULE_KEYTYPE_EMPTY) {
498         return RedisModule_ReplyWithLongLong(ctx, 0);
499     } else if (type != REDISMODULE_KEYTYPE_STRING) {
500         return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
501     }
502
503     RedisModuleCallReply *reply = RedisModule_Call(ctx, "GET", "s", key);
504     ASSERT_NOERROR(reply)
505     bool is_equal = replyContentsEqualString(reply, oldvalstr);
506     RedisModule_FreeCallReply(reply);
507     if ((flag == OBJ_OP_IE && !is_equal) ||
508         (flag == OBJ_OP_NE && is_equal)) {
509         return RedisModule_ReplyWithLongLong(ctx, 0);
510     }
511
512     return delPubStringCommon(ctx, &delParams, &pubParams);
513 }
514
515 int DelIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
516 {
517     if (argc != 5)
518         return RedisModule_WrongArity(ctx);
519
520     RedisModule_AutoMemory(ctx);
521     return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
522 }
523
524 int DelIEMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
525 {
526     if (argc < 5 || (argc % 2) == 0)
527         return RedisModule_WrongArity(ctx);
528
529     RedisModule_AutoMemory(ctx);
530     return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
531 }
532
533 int DelNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
534 {
535     if (argc != 5)
536         return RedisModule_WrongArity(ctx);
537
538     RedisModule_AutoMemory(ctx);
539     return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE);
540 }
541
542 /* This function must be present on each Redis module. It is used in order to
543  * register the commands into the Redis server. */
544 int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
545     REDISMODULE_NOT_USED(argv);
546     REDISMODULE_NOT_USED(argc);
547
548     if (RedisModule_Init(ctx,"exstrings",1,REDISMODULE_APIVER_1)
549         == REDISMODULE_ERR) return REDISMODULE_ERR;
550
551     if (RedisModule_CreateCommand(ctx,"setie",
552         SetIE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
553         return REDISMODULE_ERR;
554
555     if (RedisModule_CreateCommand(ctx,"setne",
556         SetNE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
557         return REDISMODULE_ERR;
558
559     if (RedisModule_CreateCommand(ctx,"delie",
560         DelIE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
561         return REDISMODULE_ERR;
562
563     if (RedisModule_CreateCommand(ctx,"delne",
564         DelNE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
565         return REDISMODULE_ERR;
566
567     if (RedisModule_CreateCommand(ctx,"msetpub",
568         SetPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
569         return REDISMODULE_ERR;
570
571     if (RedisModule_CreateCommand(ctx,"msetmpub",
572         SetMPub_RedisCommand,"write deny-oom pubsub",1,1,1) == REDISMODULE_ERR)
573         return REDISMODULE_ERR;
574
575     if (RedisModule_CreateCommand(ctx,"setiepub",
576         SetIEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
577         return REDISMODULE_ERR;
578
579     if (RedisModule_CreateCommand(ctx,"setiempub",
580         SetIEMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
581         return REDISMODULE_ERR;
582
583     if (RedisModule_CreateCommand(ctx,"setnepub",
584         SetNEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
585         return REDISMODULE_ERR;
586
587     if (RedisModule_CreateCommand(ctx,"setxxpub",
588         SetXXPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
589         return REDISMODULE_ERR;
590
591     if (RedisModule_CreateCommand(ctx,"setnxpub",
592         SetNXPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
593         return REDISMODULE_ERR;
594
595     if (RedisModule_CreateCommand(ctx,"setnxmpub",
596         SetNXMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
597         return REDISMODULE_ERR;
598
599     if (RedisModule_CreateCommand(ctx,"delpub",
600         DelPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
601         return REDISMODULE_ERR;
602
603     if (RedisModule_CreateCommand(ctx,"delmpub",
604         DelMPub_RedisCommand,"write deny-oom pubsub",1,1,1) == REDISMODULE_ERR)
605         return REDISMODULE_ERR;
606
607     if (RedisModule_CreateCommand(ctx,"deliepub",
608         DelIEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
609         return REDISMODULE_ERR;
610
611     if (RedisModule_CreateCommand(ctx,"deliempub",
612         DelIEMPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
613         return REDISMODULE_ERR;
614
615     if (RedisModule_CreateCommand(ctx,"delnepub",
616         DelNEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
617         return REDISMODULE_ERR;
618
619     return REDISMODULE_OK;
620 }