2 * Copyright (c) 2018-2019 Nokia.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19 * platform project (RICP).
22 #include "redismodule.h"
28 #include "../../redismodule/include/redismodule.h"
31 #include "exstringsStub.h"
34 /* make sure the response is not NULL or an error.
35 sends the error to the client and exit the current function if its */
36 #define ASSERT_NOERROR(r) \
38 return RedisModule_ReplyWithError(ctx,"ERR reply is NULL"); \
39 } else if (RedisModule_CallReplyType(r) == REDISMODULE_REPLY_ERROR) { \
40 RedisModule_ReplyWithCallReply(ctx,r); \
41 RedisModule_FreeCallReply(r); \
42 return REDISMODULE_ERR; \
46 #define OBJ_OP_XX (1<<1) /* OP if key exist */
47 #define OBJ_OP_NX (1<<2) /* OP if key not exist */
48 #define OBJ_OP_IE (1<<4) /* OP if equal old value */
49 #define OBJ_OP_NE (1<<5) /* OP if not equal old value */
51 int getKeyType(RedisModuleCtx *ctx, RedisModuleString *key_str)
53 RedisModuleKey *key = RedisModule_OpenKey(ctx, key_str, REDISMODULE_READ);
54 int type = RedisModule_KeyType(key);
55 RedisModule_CloseKey(key);
59 bool replyContentsEqualString(RedisModuleCallReply *reply, RedisModuleString *expected_value)
61 size_t replylen = 0, expectedlen = 0;
62 const char *expectedval = RedisModule_StringPtrLen(expected_value, &expectedlen);
63 const char *replyval = RedisModule_CallReplyStringPtr(reply, &replylen);
65 expectedlen == replylen &&
66 !strncmp(expectedval, replyval, replylen);
69 typedef struct _SetParams {
70 RedisModuleString **key_val_pairs;
74 typedef struct _PubParams {
75 RedisModuleString **channel_msg_pairs;
79 typedef struct _DelParams {
80 RedisModuleString **keys;
84 void multiPubCommand(RedisModuleCtx *ctx, PubParams* pubParams)
86 RedisModuleCallReply *reply = NULL;
87 for (unsigned int i = 0 ; i < pubParams->length ; i += 2) {
88 reply = RedisModule_Call(ctx, "PUBLISH", "v", pubParams->channel_msg_pairs + i, 2);
89 RedisModule_FreeCallReply(reply);
93 int setStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
94 int argc, const int flag)
96 RedisModuleString *oldvalstr = NULL;
97 RedisModuleCallReply *reply = NULL;
100 return RedisModule_WrongArity(ctx);
104 /*Check if key type is string*/
105 RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1],
107 int type = RedisModule_KeyType(key);
108 RedisModule_CloseKey(key);
110 if (type == REDISMODULE_KEYTYPE_EMPTY) {
111 if (flag == OBJ_OP_IE){
112 RedisModule_ReplyWithNull(ctx);
113 return REDISMODULE_OK;
115 } else if (type != REDISMODULE_KEYTYPE_STRING) {
116 return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE);
120 reply = RedisModule_Call(ctx, "GET", "s", argv[1]);
121 ASSERT_NOERROR(reply)
122 size_t curlen=0, oldvallen=0;
123 const char *oldval = RedisModule_StringPtrLen(oldvalstr, &oldvallen);
124 const char *curval = RedisModule_CallReplyStringPtr(reply, &curlen);
125 if (((flag == OBJ_OP_IE) &&
126 (!curval || (oldvallen != curlen) || strncmp(oldval, curval, curlen)))
128 ((flag == OBJ_OP_NE) && curval && (oldvallen == curlen) &&
129 !strncmp(oldval, curval, curlen))) {
130 RedisModule_FreeCallReply(reply);
131 return RedisModule_ReplyWithNull(ctx);
133 RedisModule_FreeCallReply(reply);
135 /* Prepare the arguments for the command. */
136 int i, j=0, cmdargc=argc-2;
137 RedisModuleString *cmdargv[cmdargc];
138 for (i = 1; i < argc; i++) {
141 cmdargv[j++] = argv[i];
144 /* Call the command and pass back the reply. */
145 reply = RedisModule_Call(ctx, "SET", "v!", cmdargv, cmdargc);
146 ASSERT_NOERROR(reply)
147 RedisModule_ReplyWithCallReply(ctx, reply);
149 RedisModule_FreeCallReply(reply);
150 return REDISMODULE_OK;
153 int SetIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
155 return setStringGenericCommand(ctx, argv, argc, OBJ_OP_IE);
158 int SetNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
160 return setStringGenericCommand(ctx, argv, argc, OBJ_OP_NE);
163 int delStringGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
164 int argc, const int flag)
166 RedisModuleString *oldvalstr = NULL;
167 RedisModuleCallReply *reply = NULL;
172 return RedisModule_WrongArity(ctx);
174 /*Check if key type is string*/
175 RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1],
177 int type = RedisModule_KeyType(key);
178 RedisModule_CloseKey(key);
180 if (type == REDISMODULE_KEYTYPE_EMPTY) {
181 return RedisModule_ReplyWithLongLong(ctx, 0);
182 } else if (type != REDISMODULE_KEYTYPE_STRING) {
183 return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE);
187 reply = RedisModule_Call(ctx, "GET", "s", argv[1]);
188 ASSERT_NOERROR(reply)
189 size_t curlen = 0, oldvallen = 0;
190 const char *oldval = RedisModule_StringPtrLen(oldvalstr, &oldvallen);
191 const char *curval = RedisModule_CallReplyStringPtr(reply, &curlen);
192 if (((flag == OBJ_OP_IE) &&
193 (!curval || (oldvallen != curlen) || strncmp(oldval, curval, curlen)))
195 ((flag == OBJ_OP_NE) && curval && (oldvallen == curlen) &&
196 !strncmp(oldval, curval, curlen))) {
197 RedisModule_FreeCallReply(reply);
198 return RedisModule_ReplyWithLongLong(ctx, 0);
200 RedisModule_FreeCallReply(reply);
202 /* Prepare the arguments for the command. */
204 RedisModuleString *cmdargv[1];
205 cmdargv[0] = argv[1];
207 /* Call the command and pass back the reply. */
208 reply = RedisModule_Call(ctx, "UNLINK", "v!", cmdargv, cmdargc);
209 ASSERT_NOERROR(reply)
210 RedisModule_ReplyWithCallReply(ctx, reply);
212 RedisModule_FreeCallReply(reply);
213 return REDISMODULE_OK;
216 int DelIE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
218 return delStringGenericCommand(ctx, argv, argc, OBJ_OP_IE);
221 int DelNE_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
223 return delStringGenericCommand(ctx, argv, argc, OBJ_OP_NE);
226 int NGet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
228 RedisModuleCallReply *reply = NULL;
231 return RedisModule_WrongArity(ctx);
233 /* Call the command to get keys with pattern. */
234 reply = RedisModule_Call(ctx, "KEYS", "s", argv[1]);
235 ASSERT_NOERROR(reply)
237 /* Prepare the arguments for the command. */
238 size_t items = RedisModule_CallReplyLength(reply);
240 //RedisModule_ReplyWithArray(ctx, items);
241 RedisModule_ReplyWithCallReply(ctx, reply);
242 RedisModule_FreeCallReply(reply);
245 RedisModuleString *cmdargv[items];
247 for (j = 0; j < items; j++) {
248 RedisModuleString *rms = RedisModule_CreateStringFromCallReply(RedisModule_CallReplyArrayElement(reply, j));
251 /*Assume all keys via SDL is string type for sake of saving time*/
253 /*Check if key type is string*/
254 RedisModuleKey *key = RedisModule_OpenKey(ctx, rms ,REDISMODULE_READ);
257 int type = RedisModule_KeyType(key);
258 RedisModule_CloseKey(key);
259 if (type == REDISMODULE_KEYTYPE_STRING) {
263 RedisModule_CloseKey(key);
267 RedisModule_FreeCallReply(reply);
269 reply = RedisModule_Call(ctx, "MGET", "v", cmdargv, i);
270 ASSERT_NOERROR(reply)
271 items = RedisModule_CallReplyLength(reply);
272 RedisModule_ReplyWithArray(ctx, i*2);
273 for (j = 0; (j<items && j<i); j++) {
274 RedisModule_ReplyWithString(ctx, cmdargv[j]);
275 RedisModule_ReplyWithString(ctx, RedisModule_CreateStringFromCallReply(RedisModule_CallReplyArrayElement(reply, j)));
278 RedisModule_FreeCallReply(reply);
281 return REDISMODULE_OK;
284 int NDel_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
286 RedisModuleCallReply *reply = NULL;
289 return RedisModule_WrongArity(ctx);
291 /* Call the command to get keys with pattern. */
292 reply = RedisModule_Call(ctx, "KEYS", "s", argv[1]);
293 ASSERT_NOERROR(reply)
295 /* Prepare the arguments for the command. */
296 size_t items = RedisModule_CallReplyLength(reply);
298 RedisModule_ReplyWithLongLong(ctx, 0);
299 RedisModule_FreeCallReply(reply);
302 RedisModuleString *cmdargv[items];
304 for (j = 0; j < items; j++) {
305 RedisModuleString *rms = RedisModule_CreateStringFromCallReply(RedisModule_CallReplyArrayElement(reply, j));
308 /*Assume all keys via SDL is string type for sake of saving time*/
310 //Check if key type is string
311 RedisModuleKey *key = RedisModule_OpenKey(ctx, rms ,REDISMODULE_READ);
314 int type = RedisModule_KeyType(key);
315 RedisModule_CloseKey(key);
316 if (type == REDISMODULE_KEYTYPE_STRING) {
320 RedisModule_CloseKey(key);
324 RedisModule_FreeCallReply(reply);
326 reply = RedisModule_Call(ctx, "UNLINK", "v!", cmdargv, i);
327 ASSERT_NOERROR(reply)
328 RedisModule_ReplyWithCallReply(ctx, reply);
329 RedisModule_FreeCallReply(reply);
333 return REDISMODULE_OK;
336 int setPubStringCommon(RedisModuleCtx *ctx, SetParams* setParamsPtr, PubParams* pubParamsPtr)
338 RedisModuleCallReply *setReply;
339 setReply = RedisModule_Call(ctx, "MSET", "v!", setParamsPtr->key_val_pairs, setParamsPtr->length);
340 ASSERT_NOERROR(setReply)
341 int replytype = RedisModule_CallReplyType(setReply);
342 if (replytype == REDISMODULE_REPLY_NULL) {
343 RedisModule_ReplyWithNull(ctx);
345 multiPubCommand(ctx, pubParamsPtr);
346 RedisModule_ReplyWithCallReply(ctx, setReply);
348 RedisModule_FreeCallReply(setReply);
349 return REDISMODULE_OK;
352 int SetPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
354 if (argc < 5 || (argc % 2) == 0)
355 return RedisModule_WrongArity(ctx);
357 SetParams setParams = {
358 .key_val_pairs = argv + 1,
361 PubParams pubParams = {
362 .channel_msg_pairs = argv + argc - 2,
366 return setPubStringCommon(ctx, &setParams, &pubParams);
369 int SetMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
371 if (argc < 7 || (argc % 2) == 0)
372 return RedisModule_WrongArity(ctx);
374 long long setPairsCount, pubPairsCount;
375 RedisModule_StringToLongLong(argv[1], &setPairsCount);
376 RedisModule_StringToLongLong(argv[2], &pubPairsCount);
377 if (setPairsCount < 1 || pubPairsCount < 1)
378 return RedisModule_ReplyWithError(ctx, "ERR SET_PAIR_COUNT and PUB_PAIR_COUNT must be greater than zero");
380 long long setLen, pubLen;
381 setLen = 2*setPairsCount;
382 pubLen = 2*pubPairsCount;
383 if (setLen + pubLen + 3 != argc)
384 return RedisModule_ReplyWithError(ctx, "ERR SET_PAIR_COUNT or PUB_PAIR_COUNT do not match the total pair count");
386 SetParams setParams = {
387 .key_val_pairs = argv + 3,
390 PubParams pubParams = {
391 .channel_msg_pairs = argv + 3 + setParams.length,
395 return setPubStringCommon(ctx, &setParams, &pubParams);
398 int setIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
400 if (argc < 6 || (argc % 2) != 0)
401 return RedisModule_WrongArity(ctx);
403 SetParams setParams = {
404 .key_val_pairs = argv + 1,
407 PubParams pubParams = {
408 .channel_msg_pairs = argv + 4,
411 RedisModuleString *key = setParams.key_val_pairs[0];
412 RedisModuleString *oldvalstr = argv[3];
414 int type = getKeyType(ctx, key);
415 if (flag == OBJ_OP_IE && type == REDISMODULE_KEYTYPE_EMPTY) {
416 return RedisModule_ReplyWithNull(ctx);
417 } else if (type != REDISMODULE_KEYTYPE_STRING && type != REDISMODULE_KEYTYPE_EMPTY) {
418 return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
421 RedisModuleCallReply *reply = RedisModule_Call(ctx, "GET", "s", key);
422 ASSERT_NOERROR(reply)
423 bool is_equal = replyContentsEqualString(reply, oldvalstr);
424 RedisModule_FreeCallReply(reply);
425 if ((flag == OBJ_OP_IE && !is_equal) ||
426 (flag == OBJ_OP_NE && is_equal)) {
427 return RedisModule_ReplyWithNull(ctx);
430 return setPubStringCommon(ctx, &setParams, &pubParams);
433 int SetNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
435 return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE);
438 int SetIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
440 return setIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
443 int setXXNXPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
445 if (argc < 5 || (argc % 2) == 0)
446 return RedisModule_WrongArity(ctx);
448 SetParams setParams = {
449 .key_val_pairs = argv + 1,
452 PubParams pubParams = {
453 .channel_msg_pairs = argv + 3,
456 RedisModuleString *key = setParams.key_val_pairs[0];
458 int type = getKeyType(ctx, key);
459 if ((flag == OBJ_OP_XX && type == REDISMODULE_KEYTYPE_EMPTY) ||
460 (flag == OBJ_OP_NX && type == REDISMODULE_KEYTYPE_STRING)) {
461 return RedisModule_ReplyWithNull(ctx);
462 } else if (type != REDISMODULE_KEYTYPE_STRING && type != REDISMODULE_KEYTYPE_EMPTY) {
463 RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
464 return REDISMODULE_OK;
467 return setPubStringCommon(ctx, &setParams, &pubParams);
470 int SetNXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
472 return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_NX);
475 int SetXXPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
477 return setXXNXPubStringCommon(ctx, argv, argc, OBJ_OP_XX);
480 int delPubStringCommon(RedisModuleCtx *ctx, DelParams *delParamsPtr, PubParams *pubParamsPtr)
482 RedisModuleCallReply *reply = RedisModule_Call(ctx, "UNLINK", "v!", delParamsPtr->keys, delParamsPtr->length);
483 ASSERT_NOERROR(reply)
484 int replytype = RedisModule_CallReplyType(reply);
485 if (replytype == REDISMODULE_REPLY_NULL) {
486 RedisModule_ReplyWithNull(ctx);
487 } else if (RedisModule_CallReplyInteger(reply) == 0) {
488 RedisModule_ReplyWithCallReply(ctx, reply);
490 RedisModule_ReplyWithCallReply(ctx, reply);
491 multiPubCommand(ctx, pubParamsPtr);
493 RedisModule_FreeCallReply(reply);
494 return REDISMODULE_OK;
497 int DelPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
500 return RedisModule_WrongArity(ctx);
502 DelParams delParams = {
506 PubParams pubParams = {
507 .channel_msg_pairs = argv + 1 + delParams.length,
511 return delPubStringCommon(ctx, &delParams, &pubParams);
514 int DelMPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
517 return RedisModule_WrongArity(ctx);
519 long long delCount, pubPairsCount;
520 RedisModule_StringToLongLong(argv[1], &delCount);
521 RedisModule_StringToLongLong(argv[2], &pubPairsCount);
522 if (delCount < 1 || pubPairsCount < 1)
523 return RedisModule_ReplyWithError(ctx, "ERR DEL_COUNT and PUB_PAIR_COUNT must be greater than zero");
525 long long delLen, pubLen;
527 pubLen = 2*pubPairsCount;
528 if (delLen + pubLen + 3 != argc)
529 return RedisModule_ReplyWithError(ctx, "ERR DEL_COUNT or PUB_PAIR_COUNT do not match the total pair count");
531 DelParams delParams = {
535 PubParams pubParams = {
536 .channel_msg_pairs = argv + 3 + delParams.length,
540 return delPubStringCommon(ctx, &delParams, &pubParams);
543 int delIENEPubStringCommon(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int flag)
545 if (argc < 5 || (argc % 2) == 0)
546 return RedisModule_WrongArity(ctx);
548 DelParams delParams = {
552 PubParams pubParams = {
553 .channel_msg_pairs = argv + 3,
556 RedisModuleString *key = argv[1];
557 RedisModuleString *oldvalstr = argv[2];
559 int type = getKeyType(ctx, key);
560 if (type == REDISMODULE_KEYTYPE_EMPTY) {
561 return RedisModule_ReplyWithLongLong(ctx, 0);
562 } else if (type != REDISMODULE_KEYTYPE_STRING) {
563 return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
566 RedisModuleCallReply *reply = RedisModule_Call(ctx, "GET", "s", key);
567 ASSERT_NOERROR(reply)
568 bool is_equal = replyContentsEqualString(reply, oldvalstr);
569 RedisModule_FreeCallReply(reply);
570 if ((flag == OBJ_OP_IE && !is_equal) ||
571 (flag == OBJ_OP_NE && is_equal)) {
572 return RedisModule_ReplyWithLongLong(ctx, 0);
575 return delPubStringCommon(ctx, &delParams, &pubParams);
578 int DelIEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
580 return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_IE);
583 int DelNEPub_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
585 return delIENEPubStringCommon(ctx, argv, argc, OBJ_OP_NE);
588 /* This function must be present on each Redis module. It is used in order to
589 * register the commands into the Redis server. */
590 int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
591 REDISMODULE_NOT_USED(argv);
592 REDISMODULE_NOT_USED(argc);
594 if (RedisModule_Init(ctx,"exstrings",1,REDISMODULE_APIVER_1)
595 == REDISMODULE_ERR) return REDISMODULE_ERR;
597 if (RedisModule_CreateCommand(ctx,"setie",
598 SetIE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
599 return REDISMODULE_ERR;
601 if (RedisModule_CreateCommand(ctx,"setne",
602 SetNE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
603 return REDISMODULE_ERR;
605 if (RedisModule_CreateCommand(ctx,"delie",
606 DelIE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
607 return REDISMODULE_ERR;
609 if (RedisModule_CreateCommand(ctx,"delne",
610 DelNE_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
611 return REDISMODULE_ERR;
613 if (RedisModule_CreateCommand(ctx,"nget",
614 NGet_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR)
615 return REDISMODULE_ERR;
617 if (RedisModule_CreateCommand(ctx,"ndel",
618 NDel_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
619 return REDISMODULE_ERR;
621 if (RedisModule_CreateCommand(ctx,"msetpub",
622 SetPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
623 return REDISMODULE_ERR;
625 if (RedisModule_CreateCommand(ctx,"msetmpub",
626 SetMPub_RedisCommand,"write deny-oom pubsub",1,1,1) == REDISMODULE_ERR)
627 return REDISMODULE_ERR;
629 if (RedisModule_CreateCommand(ctx,"setiepub",
630 SetIEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
631 return REDISMODULE_ERR;
633 if (RedisModule_CreateCommand(ctx,"setnepub",
634 SetNEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
635 return REDISMODULE_ERR;
637 if (RedisModule_CreateCommand(ctx,"setxxpub",
638 SetXXPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
639 return REDISMODULE_ERR;
641 if (RedisModule_CreateCommand(ctx,"setnxpub",
642 SetNXPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
643 return REDISMODULE_ERR;
645 if (RedisModule_CreateCommand(ctx,"delpub",
646 DelPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
647 return REDISMODULE_ERR;
649 if (RedisModule_CreateCommand(ctx,"delmpub",
650 DelMPub_RedisCommand,"write deny-oom pubsub",1,1,1) == REDISMODULE_ERR)
651 return REDISMODULE_ERR;
653 if (RedisModule_CreateCommand(ctx,"deliepub",
654 DelIEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
655 return REDISMODULE_ERR;
657 if (RedisModule_CreateCommand(ctx,"delnepub",
658 DelNEPub_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
659 return REDISMODULE_ERR;
661 return REDISMODULE_OK;