diff options
Diffstat (limited to 'examples/redis-unstable/src/modules')
| -rw-r--r-- | examples/redis-unstable/src/modules/.gitignore | 2 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/Makefile | 69 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/helloacl.c | 190 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/helloblock.c | 198 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/hellocluster.c | 98 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/hellodict.c | 111 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/hellohook.c | 72 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/hellotimer.c | 55 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/hellotype.c | 342 | ||||
| -rw-r--r-- | examples/redis-unstable/src/modules/helloworld.c | 601 |
10 files changed, 0 insertions, 1738 deletions
diff --git a/examples/redis-unstable/src/modules/.gitignore b/examples/redis-unstable/src/modules/.gitignore deleted file mode 100644 index 4de1735..0000000 --- a/examples/redis-unstable/src/modules/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.so -*.xo diff --git a/examples/redis-unstable/src/modules/Makefile b/examples/redis-unstable/src/modules/Makefile deleted file mode 100644 index b9ef578..0000000 --- a/examples/redis-unstable/src/modules/Makefile +++ /dev/null @@ -1,69 +0,0 @@ - -# find the OS -uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') - -# Compile flags for linux / osx -ifeq ($(uname_S),Linux) - SHOBJ_CFLAGS ?= -W -Wall -fno-common -g -ggdb -std=c99 -O2 - SHOBJ_LDFLAGS ?= -shared -else - SHOBJ_CFLAGS ?= -W -Wall -dynamic -fno-common -g -ggdb -std=c99 -O2 - SHOBJ_LDFLAGS ?= -bundle -undefined dynamic_lookup -endif - -# OS X 11.x doesn't have /usr/lib/libSystem.dylib and needs an explicit setting. -ifeq ($(uname_S),Darwin) -ifeq ("$(wildcard /usr/lib/libSystem.dylib)","") -LIBS = -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lsystem -endif -endif - -.SUFFIXES: .c .so .xo .o - -all: helloworld.so hellotype.so helloblock.so hellocluster.so hellotimer.so hellodict.so hellohook.so helloacl.so - -.c.xo: - $(CC) -I. $(CFLAGS) $(SHOBJ_CFLAGS) -fPIC -c $< -o $@ - -helloworld.xo: ../redismodule.h - -helloworld.so: helloworld.xo - $(LD) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) -lc - -hellotype.xo: ../redismodule.h - -hellotype.so: hellotype.xo - $(LD) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) -lc - -helloblock.xo: ../redismodule.h - -helloblock.so: helloblock.xo - $(LD) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) -lpthread -lc - -hellocluster.xo: ../redismodule.h - -hellocluster.so: hellocluster.xo - $(LD) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) -lc - -hellotimer.xo: ../redismodule.h - -hellotimer.so: hellotimer.xo - $(LD) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) -lc - -hellodict.xo: ../redismodule.h - -hellodict.so: hellodict.xo - $(LD) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) -lc - -hellohook.xo: ../redismodule.h - -hellohook.so: hellohook.xo - $(LD) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) -lc - -helloacl.xo: ../redismodule.h - -helloacl.so: helloacl.xo - $(LD) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) -lc - -clean: - rm -rf *.xo *.so diff --git a/examples/redis-unstable/src/modules/helloacl.c b/examples/redis-unstable/src/modules/helloacl.c deleted file mode 100644 index 53f3a44..0000000 --- a/examples/redis-unstable/src/modules/helloacl.c +++ /dev/null @@ -1,190 +0,0 @@ -/* ACL API example - An example for performing custom synchronous and - * asynchronous password authentication. - * - * ----------------------------------------------------------------------------- - * - * Copyright 2019 Amazon.com, Inc. or its affiliates. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "../redismodule.h" -#include <pthread.h> -#include <unistd.h> - -// A simple global user -static RedisModuleUser *global; -static uint64_t global_auth_client_id = 0; - -/* HELLOACL.REVOKE - * Synchronously revoke access from a user. */ -int RevokeCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (global_auth_client_id) { - RedisModule_DeauthenticateAndCloseClient(ctx, global_auth_client_id); - return RedisModule_ReplyWithSimpleString(ctx, "OK"); - } else { - return RedisModule_ReplyWithError(ctx, "Global user currently not used"); - } -} - -/* HELLOACL.RESET - * Synchronously delete and re-create a module user. */ -int ResetCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - RedisModule_FreeModuleUser(global); - global = RedisModule_CreateModuleUser("global"); - RedisModule_SetModuleUserACL(global, "allcommands"); - RedisModule_SetModuleUserACL(global, "allkeys"); - RedisModule_SetModuleUserACL(global, "on"); - - return RedisModule_ReplyWithSimpleString(ctx, "OK"); -} - -/* Callback handler for user changes, use this to notify a module of - * changes to users authenticated by the module */ -void HelloACL_UserChanged(uint64_t client_id, void *privdata) { - REDISMODULE_NOT_USED(privdata); - REDISMODULE_NOT_USED(client_id); - global_auth_client_id = 0; -} - -/* HELLOACL.AUTHGLOBAL - * Synchronously assigns a module user to the current context. */ -int AuthGlobalCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (global_auth_client_id) { - return RedisModule_ReplyWithError(ctx, "Global user currently used"); - } - - RedisModule_AuthenticateClientWithUser(ctx, global, HelloACL_UserChanged, NULL, &global_auth_client_id); - - return RedisModule_ReplyWithSimpleString(ctx, "OK"); -} - -#define TIMEOUT_TIME 1000 - -/* Reply callback for auth command HELLOACL.AUTHASYNC */ -int HelloACL_Reply(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - size_t length; - - RedisModuleString *user_string = RedisModule_GetBlockedClientPrivateData(ctx); - const char *name = RedisModule_StringPtrLen(user_string, &length); - - if (RedisModule_AuthenticateClientWithACLUser(ctx, name, length, NULL, NULL, NULL) == - REDISMODULE_ERR) { - return RedisModule_ReplyWithError(ctx, "Invalid Username or password"); - } - return RedisModule_ReplyWithSimpleString(ctx, "OK"); -} - -/* Timeout callback for auth command HELLOACL.AUTHASYNC */ -int HelloACL_Timeout(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - return RedisModule_ReplyWithSimpleString(ctx, "Request timedout"); -} - -/* Private data frees data for HELLOACL.AUTHASYNC command. */ -void HelloACL_FreeData(RedisModuleCtx *ctx, void *privdata) { - REDISMODULE_NOT_USED(ctx); - RedisModule_FreeString(NULL, privdata); -} - -/* Background authentication can happen here. */ -void *HelloACL_ThreadMain(void *args) { - void **targs = args; - RedisModuleBlockedClient *bc = targs[0]; - RedisModuleString *user = targs[1]; - RedisModule_Free(targs); - - RedisModule_UnblockClient(bc,user); - return NULL; -} - -/* HELLOACL.AUTHASYNC - * Asynchronously assigns an ACL user to the current context. */ -int AuthAsyncCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 2) return RedisModule_WrongArity(ctx); - - pthread_t tid; - RedisModuleBlockedClient *bc = RedisModule_BlockClient(ctx, HelloACL_Reply, HelloACL_Timeout, HelloACL_FreeData, TIMEOUT_TIME); - - - void **targs = RedisModule_Alloc(sizeof(void*)*2); - targs[0] = bc; - targs[1] = RedisModule_CreateStringFromString(NULL, argv[1]); - - if (pthread_create(&tid, NULL, HelloACL_ThreadMain, targs) != 0) { - RedisModule_AbortBlock(bc); - return RedisModule_ReplyWithError(ctx, "-ERR Can't start thread"); - } - - return REDISMODULE_OK; -} - -/* This function must be present on each Redis module. It is used in order to - * register the commands into the Redis server. */ -int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (RedisModule_Init(ctx,"helloacl",1,REDISMODULE_APIVER_1) - == REDISMODULE_ERR) return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"helloacl.reset", - ResetCommand_RedisCommand,"",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"helloacl.revoke", - RevokeCommand_RedisCommand,"",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"helloacl.authglobal", - AuthGlobalCommand_RedisCommand,"no-auth",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"helloacl.authasync", - AuthAsyncCommand_RedisCommand,"no-auth",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - global = RedisModule_CreateModuleUser("global"); - RedisModule_SetModuleUserACL(global, "allcommands"); - RedisModule_SetModuleUserACL(global, "allkeys"); - RedisModule_SetModuleUserACL(global, "on"); - - global_auth_client_id = 0; - - return REDISMODULE_OK; -} diff --git a/examples/redis-unstable/src/modules/helloblock.c b/examples/redis-unstable/src/modules/helloblock.c deleted file mode 100644 index 44bb010..0000000 --- a/examples/redis-unstable/src/modules/helloblock.c +++ /dev/null @@ -1,198 +0,0 @@ -/* Helloblock module -- An example of blocking command implementation - * with threads. - * - * ----------------------------------------------------------------------------- - * - * Copyright (c) 2016-Present, Redis Ltd. - * All rights reserved. - * - * Licensed under your choice of (a) the Redis Source Available License 2.0 - * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the - * GNU Affero General Public License v3 (AGPLv3). - */ - -#include "../redismodule.h" -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> -#include <unistd.h> - -/* Reply callback for blocking command HELLO.BLOCK */ -int HelloBlock_Reply(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - int *myint = RedisModule_GetBlockedClientPrivateData(ctx); - return RedisModule_ReplyWithLongLong(ctx,*myint); -} - -/* Timeout callback for blocking command HELLO.BLOCK */ -int HelloBlock_Timeout(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - return RedisModule_ReplyWithSimpleString(ctx,"Request timedout"); -} - -/* Private data freeing callback for HELLO.BLOCK command. */ -void HelloBlock_FreeData(RedisModuleCtx *ctx, void *privdata) { - REDISMODULE_NOT_USED(ctx); - RedisModule_Free(privdata); -} - -/* The thread entry point that actually executes the blocking part - * of the command HELLO.BLOCK. */ -void *HelloBlock_ThreadMain(void *arg) { - void **targ = arg; - RedisModuleBlockedClient *bc = targ[0]; - long long delay = (unsigned long)targ[1]; - RedisModule_Free(targ); - - sleep(delay); - int *r = RedisModule_Alloc(sizeof(int)); - *r = rand(); - RedisModule_UnblockClient(bc,r); - return NULL; -} - -/* An example blocked client disconnection callback. - * - * Note that in the case of the HELLO.BLOCK command, the blocked client is now - * owned by the thread calling sleep(). In this specific case, there is not - * much we can do, however normally we could instead implement a way to - * signal the thread that the client disconnected, and sleep the specified - * amount of seconds with a while loop calling sleep(1), so that once we - * detect the client disconnection, we can terminate the thread ASAP. */ -void HelloBlock_Disconnected(RedisModuleCtx *ctx, RedisModuleBlockedClient *bc) { - RedisModule_Log(ctx,"warning","Blocked client %p disconnected!", - (void*)bc); - - /* Here you should cleanup your state / threads, and if possible - * call RedisModule_UnblockClient(), or notify the thread that will - * call the function ASAP. */ -} - -/* HELLO.BLOCK <delay> <timeout> -- Block for <count> seconds, then reply with - * a random number. Timeout is the command timeout, so that you can test - * what happens when the delay is greater than the timeout. */ -int HelloBlock_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 3) return RedisModule_WrongArity(ctx); - long long delay; - long long timeout; - - if (RedisModule_StringToLongLong(argv[1],&delay) != REDISMODULE_OK) { - return RedisModule_ReplyWithError(ctx,"ERR invalid count"); - } - - if (RedisModule_StringToLongLong(argv[2],&timeout) != REDISMODULE_OK) { - return RedisModule_ReplyWithError(ctx,"ERR invalid count"); - } - - pthread_t tid; - RedisModuleBlockedClient *bc = RedisModule_BlockClient(ctx,HelloBlock_Reply,HelloBlock_Timeout,HelloBlock_FreeData,timeout); - - /* Here we set a disconnection handler, however since this module will - * block in sleep() in a thread, there is not much we can do in the - * callback, so this is just to show you the API. */ - RedisModule_SetDisconnectCallback(bc,HelloBlock_Disconnected); - - /* Now that we setup a blocking client, we need to pass the control - * to the thread. However we need to pass arguments to the thread: - * the delay and a reference to the blocked client handle. */ - void **targ = RedisModule_Alloc(sizeof(void*)*2); - targ[0] = bc; - targ[1] = (void*)(unsigned long) delay; - - if (pthread_create(&tid,NULL,HelloBlock_ThreadMain,targ) != 0) { - RedisModule_AbortBlock(bc); - return RedisModule_ReplyWithError(ctx,"-ERR Can't start thread"); - } - return REDISMODULE_OK; -} - -/* The thread entry point that actually executes the blocking part - * of the command HELLO.KEYS. - * - * Note: this implementation is very simple on purpose, so no duplicated - * keys (returned by SCAN) are filtered. However adding such a functionality - * would be trivial just using any data structure implementing a dictionary - * in order to filter the duplicated items. */ -void *HelloKeys_ThreadMain(void *arg) { - RedisModuleBlockedClient *bc = arg; - RedisModuleCtx *ctx = RedisModule_GetThreadSafeContext(bc); - long long cursor = 0; - size_t replylen = 0; - - RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN); - do { - RedisModule_ThreadSafeContextLock(ctx); - RedisModuleCallReply *reply = RedisModule_Call(ctx, - "SCAN","l",(long long)cursor); - RedisModule_ThreadSafeContextUnlock(ctx); - - RedisModuleCallReply *cr_cursor = - RedisModule_CallReplyArrayElement(reply,0); - RedisModuleCallReply *cr_keys = - RedisModule_CallReplyArrayElement(reply,1); - - RedisModuleString *s = RedisModule_CreateStringFromCallReply(cr_cursor); - RedisModule_StringToLongLong(s,&cursor); - RedisModule_FreeString(ctx,s); - - size_t items = RedisModule_CallReplyLength(cr_keys); - for (size_t j = 0; j < items; j++) { - RedisModuleCallReply *ele = - RedisModule_CallReplyArrayElement(cr_keys,j); - RedisModule_ReplyWithCallReply(ctx,ele); - replylen++; - } - RedisModule_FreeCallReply(reply); - } while (cursor != 0); - RedisModule_ReplySetArrayLength(ctx,replylen); - - RedisModule_FreeThreadSafeContext(ctx); - RedisModule_UnblockClient(bc,NULL); - return NULL; -} - -/* HELLO.KEYS -- Return all the keys in the current database without blocking - * the server. The keys do not represent a point-in-time state so only the keys - * that were in the database from the start to the end are guaranteed to be - * there. */ -int HelloKeys_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - if (argc != 1) return RedisModule_WrongArity(ctx); - - pthread_t tid; - - /* Note that when blocking the client we do not set any callback: no - * timeout is possible since we passed '0', nor we need a reply callback - * because we'll use the thread safe context to accumulate a reply. */ - RedisModuleBlockedClient *bc = RedisModule_BlockClient(ctx,NULL,NULL,NULL,0); - - /* Now that we setup a blocking client, we need to pass the control - * to the thread. However we need to pass arguments to the thread: - * the reference to the blocked client handle. */ - if (pthread_create(&tid,NULL,HelloKeys_ThreadMain,bc) != 0) { - RedisModule_AbortBlock(bc); - return RedisModule_ReplyWithError(ctx,"-ERR Can't start thread"); - } - return REDISMODULE_OK; -} - -/* This function must be present on each Redis module. It is used in order to - * register the commands into the Redis server. */ -int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (RedisModule_Init(ctx,"helloblock",1,REDISMODULE_APIVER_1) - == REDISMODULE_ERR) return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.block", - HelloBlock_RedisCommand,"",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - if (RedisModule_CreateCommand(ctx,"hello.keys", - HelloKeys_RedisCommand,"",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - return REDISMODULE_OK; -} diff --git a/examples/redis-unstable/src/modules/hellocluster.c b/examples/redis-unstable/src/modules/hellocluster.c deleted file mode 100644 index 38d7e1f..0000000 --- a/examples/redis-unstable/src/modules/hellocluster.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Helloworld cluster -- A ping/pong cluster API example. - * - * ----------------------------------------------------------------------------- - * - * Copyright (c) 2018-Present, Redis Ltd. - * All rights reserved. - * - * Licensed under your choice of (a) the Redis Source Available License 2.0 - * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the - * GNU Affero General Public License v3 (AGPLv3). - */ - -#include "../redismodule.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> - -#define MSGTYPE_PING 1 -#define MSGTYPE_PONG 2 - -/* HELLOCLUSTER.PINGALL */ -int PingallCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - RedisModule_SendClusterMessage(ctx,NULL,MSGTYPE_PING,"Hey",3); - return RedisModule_ReplyWithSimpleString(ctx, "OK"); -} - -/* HELLOCLUSTER.LIST */ -int ListCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - size_t numnodes; - char **ids = RedisModule_GetClusterNodesList(ctx,&numnodes); - if (ids == NULL) { - return RedisModule_ReplyWithError(ctx,"Cluster not enabled"); - } - - RedisModule_ReplyWithArray(ctx,numnodes); - for (size_t j = 0; j < numnodes; j++) { - int port; - RedisModule_GetClusterNodeInfo(ctx,ids[j],NULL,NULL,&port,NULL); - RedisModule_ReplyWithArray(ctx,2); - RedisModule_ReplyWithStringBuffer(ctx,ids[j],REDISMODULE_NODE_ID_LEN); - RedisModule_ReplyWithLongLong(ctx,port); - } - RedisModule_FreeClusterNodesList(ids); - return REDISMODULE_OK; -} - -/* Callback for message MSGTYPE_PING */ -void PingReceiver(RedisModuleCtx *ctx, const char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len) { - RedisModule_Log(ctx,"notice","PING (type %d) RECEIVED from %.*s: '%.*s'", - type,REDISMODULE_NODE_ID_LEN,sender_id,(int)len, payload); - RedisModule_SendClusterMessage(ctx,NULL,MSGTYPE_PONG,"Ohi!",4); - RedisModuleCallReply *reply = RedisModule_Call(ctx, "INCR", "c", "pings_received"); - RedisModule_FreeCallReply(reply); -} - -/* Callback for message MSGTYPE_PONG. */ -void PongReceiver(RedisModuleCtx *ctx, const char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len) { - RedisModule_Log(ctx,"notice","PONG (type %d) RECEIVED from %.*s: '%.*s'", - type,REDISMODULE_NODE_ID_LEN,sender_id,(int)len, payload); -} - -/* This function must be present on each Redis module. It is used in order to - * register the commands into the Redis server. */ -int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (RedisModule_Init(ctx,"hellocluster",1,REDISMODULE_APIVER_1) - == REDISMODULE_ERR) return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellocluster.pingall", - PingallCommand_RedisCommand,"readonly",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellocluster.list", - ListCommand_RedisCommand,"readonly",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - /* Disable Redis Cluster sharding and redirections. This way every node - * will be able to access every possible key, regardless of the hash slot. - * This way the PING message handler will be able to increment a specific - * variable. Normally you do that in order for the distributed system - * you create as a module to have total freedom in the keyspace - * manipulation. */ - RedisModule_SetClusterFlags(ctx,REDISMODULE_CLUSTER_FLAG_NO_REDIRECTION); - - /* Register our handlers for different message types. */ - RedisModule_RegisterClusterMessageReceiver(ctx,MSGTYPE_PING,PingReceiver); - RedisModule_RegisterClusterMessageReceiver(ctx,MSGTYPE_PONG,PongReceiver); - return REDISMODULE_OK; -} diff --git a/examples/redis-unstable/src/modules/hellodict.c b/examples/redis-unstable/src/modules/hellodict.c deleted file mode 100644 index 00c4964..0000000 --- a/examples/redis-unstable/src/modules/hellodict.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Hellodict -- An example of modules dictionary API - * - * This module implements a volatile key-value store on top of the - * dictionary exported by the Redis modules API. - * - * ----------------------------------------------------------------------------- - * - * Copyright (c) 2018-Present, Redis Ltd. - * All rights reserved. - * - * Licensed under your choice of (a) the Redis Source Available License 2.0 - * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the - * GNU Affero General Public License v3 (AGPLv3). - */ - -#include "../redismodule.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> - -static RedisModuleDict *Keyspace; - -/* HELLODICT.SET <key> <value> - * - * Set the specified key to the specified value. */ -int cmd_SET(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 3) return RedisModule_WrongArity(ctx); - RedisModule_DictSet(Keyspace,argv[1],argv[2]); - /* We need to keep a reference to the value stored at the key, otherwise - * it would be freed when this callback returns. */ - RedisModule_RetainString(NULL,argv[2]); - return RedisModule_ReplyWithSimpleString(ctx, "OK"); -} - -/* HELLODICT.GET <key> - * - * Return the value of the specified key, or a null reply if the key - * is not defined. */ -int cmd_GET(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 2) return RedisModule_WrongArity(ctx); - RedisModuleString *val = RedisModule_DictGet(Keyspace,argv[1],NULL); - if (val == NULL) { - return RedisModule_ReplyWithNull(ctx); - } else { - return RedisModule_ReplyWithString(ctx, val); - } -} - -/* HELLODICT.KEYRANGE <startkey> <endkey> <count> - * - * Return a list of matching keys, lexicographically between startkey - * and endkey. No more than 'count' items are emitted. */ -int cmd_KEYRANGE(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 4) return RedisModule_WrongArity(ctx); - - /* Parse the count argument. */ - long long count; - if (RedisModule_StringToLongLong(argv[3],&count) != REDISMODULE_OK) { - return RedisModule_ReplyWithError(ctx,"ERR invalid count"); - } - - /* Seek the iterator. */ - RedisModuleDictIter *iter = RedisModule_DictIteratorStart( - Keyspace, ">=", argv[1]); - - /* Reply with the matching items. */ - char *key; - size_t keylen; - long long replylen = 0; /* Keep track of the emitted array len. */ - RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN); - while((key = RedisModule_DictNextC(iter,&keylen,NULL)) != NULL) { - if (replylen >= count) break; - if (RedisModule_DictCompare(iter,"<=",argv[2]) == REDISMODULE_ERR) - break; - RedisModule_ReplyWithStringBuffer(ctx,key,keylen); - replylen++; - } - RedisModule_ReplySetArrayLength(ctx,replylen); - - /* Cleanup. */ - RedisModule_DictIteratorStop(iter); - return REDISMODULE_OK; -} - -/* This function must be present on each Redis module. It is used in order to - * register the commands into the Redis server. */ -int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (RedisModule_Init(ctx,"hellodict",1,REDISMODULE_APIVER_1) - == REDISMODULE_ERR) return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellodict.set", - cmd_SET,"write deny-oom",1,1,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellodict.get", - cmd_GET,"readonly",1,1,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellodict.keyrange", - cmd_KEYRANGE,"readonly",1,1,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - /* Create our global dictionary. Here we'll set our keys and values. */ - Keyspace = RedisModule_CreateDict(NULL); - - return REDISMODULE_OK; -} diff --git a/examples/redis-unstable/src/modules/hellohook.c b/examples/redis-unstable/src/modules/hellohook.c deleted file mode 100644 index c8c371d..0000000 --- a/examples/redis-unstable/src/modules/hellohook.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Server hooks API example - * - * ----------------------------------------------------------------------------- - * - * Copyright (c) 2019-Present, Redis Ltd. - * All rights reserved. - * - * Licensed under your choice of (a) the Redis Source Available License 2.0 - * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the - * GNU Affero General Public License v3 (AGPLv3). - */ - -#include "../redismodule.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> - -/* Client state change callback. */ -void clientChangeCallback(RedisModuleCtx *ctx, RedisModuleEvent e, uint64_t sub, void *data) -{ - REDISMODULE_NOT_USED(ctx); - REDISMODULE_NOT_USED(e); - - RedisModuleClientInfo *ci = data; - printf("Client %s event for client #%llu %s:%d\n", - (sub == REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED) ? - "connection" : "disconnection", - (unsigned long long)ci->id,ci->addr,ci->port); -} - -void flushdbCallback(RedisModuleCtx *ctx, RedisModuleEvent e, uint64_t sub, void *data) -{ - REDISMODULE_NOT_USED(ctx); - REDISMODULE_NOT_USED(e); - - RedisModuleFlushInfo *fi = data; - if (sub == REDISMODULE_SUBEVENT_FLUSHDB_START) { - if (fi->dbnum != -1) { - RedisModuleCallReply *reply; - reply = RedisModule_Call(ctx,"DBSIZE",""); - long long numkeys = RedisModule_CallReplyInteger(reply); - printf("FLUSHDB event of database %d started (%lld keys in DB)\n", - fi->dbnum, numkeys); - RedisModule_FreeCallReply(reply); - } else { - printf("FLUSHALL event started\n"); - } - } else { - if (fi->dbnum != -1) { - printf("FLUSHDB event of database %d ended\n",fi->dbnum); - } else { - printf("FLUSHALL event ended\n"); - } - } -} - -/* This function must be present on each Redis module. It is used in order to - * register the commands into the Redis server. */ -int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (RedisModule_Init(ctx,"hellohook",1,REDISMODULE_APIVER_1) - == REDISMODULE_ERR) return REDISMODULE_ERR; - - RedisModule_SubscribeToServerEvent(ctx, - RedisModuleEvent_ClientChange, clientChangeCallback); - RedisModule_SubscribeToServerEvent(ctx, - RedisModuleEvent_FlushDB, flushdbCallback); - return REDISMODULE_OK; -} diff --git a/examples/redis-unstable/src/modules/hellotimer.c b/examples/redis-unstable/src/modules/hellotimer.c deleted file mode 100644 index 1c0c3a6..0000000 --- a/examples/redis-unstable/src/modules/hellotimer.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Timer API example -- Register and handle timer events - * - * ----------------------------------------------------------------------------- - * - * Copyright (c) 2018-Present, Redis Ltd. - * All rights reserved. - * - * Licensed under your choice of (a) the Redis Source Available License 2.0 - * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the - * GNU Affero General Public License v3 (AGPLv3). - */ - -#include "../redismodule.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> - -/* Timer callback. */ -void timerHandler(RedisModuleCtx *ctx, void *data) { - REDISMODULE_NOT_USED(ctx); - printf("Fired %s!\n", (char *)data); - RedisModule_Free(data); -} - -/* HELLOTIMER.TIMER*/ -int TimerCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - for (int j = 0; j < 10; j++) { - int delay = rand() % 5000; - char *buf = RedisModule_Alloc(256); - snprintf(buf,256,"After %d", delay); - RedisModuleTimerID tid = RedisModule_CreateTimer(ctx,delay,timerHandler,buf); - REDISMODULE_NOT_USED(tid); - } - return RedisModule_ReplyWithSimpleString(ctx, "OK"); -} - -/* This function must be present on each Redis module. It is used in order to - * register the commands into the Redis server. */ -int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (RedisModule_Init(ctx,"hellotimer",1,REDISMODULE_APIVER_1) - == REDISMODULE_ERR) return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellotimer.timer", - TimerCommand_RedisCommand,"readonly",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - return REDISMODULE_OK; -} diff --git a/examples/redis-unstable/src/modules/hellotype.c b/examples/redis-unstable/src/modules/hellotype.c deleted file mode 100644 index aecb331..0000000 --- a/examples/redis-unstable/src/modules/hellotype.c +++ /dev/null @@ -1,342 +0,0 @@ -/* This file implements a new module native data type called "HELLOTYPE". - * The data structure implemented is a very simple ordered linked list of - * 64 bit integers, in order to have something that is real world enough, but - * at the same time, extremely simple to understand, to show how the API - * works, how a new data type is created, and how to write basic methods - * for RDB loading, saving and AOF rewriting. - * - * ----------------------------------------------------------------------------- - * - * Copyright (c) 2016-Present, Redis Ltd. - * All rights reserved. - * - * Licensed under your choice of (a) the Redis Source Available License 2.0 - * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the - * GNU Affero General Public License v3 (AGPLv3). - */ - -#include "../redismodule.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> -#include <stdint.h> - -static RedisModuleType *HelloType; - -/* ========================== Internal data structure ======================= - * This is just a linked list of 64 bit integers where elements are inserted - * in-place, so it's ordered. There is no pop/push operation but just insert - * because it is enough to show the implementation of new data types without - * making things complex. */ - -struct HelloTypeNode { - int64_t value; - struct HelloTypeNode *next; -}; - -struct HelloTypeObject { - struct HelloTypeNode *head; - size_t len; /* Number of elements added. */ -}; - -struct HelloTypeObject *createHelloTypeObject(void) { - struct HelloTypeObject *o; - o = RedisModule_Alloc(sizeof(*o)); - o->head = NULL; - o->len = 0; - return o; -} - -void HelloTypeInsert(struct HelloTypeObject *o, int64_t ele) { - struct HelloTypeNode *next = o->head, *newnode, *prev = NULL; - - while(next && next->value < ele) { - prev = next; - next = next->next; - } - newnode = RedisModule_Alloc(sizeof(*newnode)); - newnode->value = ele; - newnode->next = next; - if (prev) { - prev->next = newnode; - } else { - o->head = newnode; - } - o->len++; -} - -void HelloTypeReleaseObject(struct HelloTypeObject *o) { - struct HelloTypeNode *cur, *next; - cur = o->head; - while(cur) { - next = cur->next; - RedisModule_Free(cur); - cur = next; - } - RedisModule_Free(o); -} - -/* ========================= "hellotype" type commands ======================= */ - -/* HELLOTYPE.INSERT key value */ -int HelloTypeInsert_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - - if (argc != 3) return RedisModule_WrongArity(ctx); - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - int type = RedisModule_KeyType(key); - if (type != REDISMODULE_KEYTYPE_EMPTY && - RedisModule_ModuleTypeGetType(key) != HelloType) - { - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - long long value; - if ((RedisModule_StringToLongLong(argv[2],&value) != REDISMODULE_OK)) { - return RedisModule_ReplyWithError(ctx,"ERR invalid value: must be a signed 64 bit integer"); - } - - /* Create an empty value object if the key is currently empty. */ - struct HelloTypeObject *hto; - if (type == REDISMODULE_KEYTYPE_EMPTY) { - hto = createHelloTypeObject(); - RedisModule_ModuleTypeSetValue(key,HelloType,hto); - } else { - hto = RedisModule_ModuleTypeGetValue(key); - } - - /* Insert the new element. */ - HelloTypeInsert(hto,value); - RedisModule_SignalKeyAsReady(ctx,argv[1]); - - RedisModule_ReplyWithLongLong(ctx,hto->len); - RedisModule_ReplicateVerbatim(ctx); - return REDISMODULE_OK; -} - -/* HELLOTYPE.RANGE key first count */ -int HelloTypeRange_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - - if (argc != 4) return RedisModule_WrongArity(ctx); - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - int type = RedisModule_KeyType(key); - if (type != REDISMODULE_KEYTYPE_EMPTY && - RedisModule_ModuleTypeGetType(key) != HelloType) - { - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - long long first, count; - if (RedisModule_StringToLongLong(argv[2],&first) != REDISMODULE_OK || - RedisModule_StringToLongLong(argv[3],&count) != REDISMODULE_OK || - first < 0 || count < 0) - { - return RedisModule_ReplyWithError(ctx, - "ERR invalid first or count parameters"); - } - - struct HelloTypeObject *hto = RedisModule_ModuleTypeGetValue(key); - struct HelloTypeNode *node = hto ? hto->head : NULL; - RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN); - long long arraylen = 0; - while(node && count--) { - RedisModule_ReplyWithLongLong(ctx,node->value); - arraylen++; - node = node->next; - } - RedisModule_ReplySetArrayLength(ctx,arraylen); - return REDISMODULE_OK; -} - -/* HELLOTYPE.LEN key */ -int HelloTypeLen_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - - if (argc != 2) return RedisModule_WrongArity(ctx); - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - int type = RedisModule_KeyType(key); - if (type != REDISMODULE_KEYTYPE_EMPTY && - RedisModule_ModuleTypeGetType(key) != HelloType) - { - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - struct HelloTypeObject *hto = RedisModule_ModuleTypeGetValue(key); - RedisModule_ReplyWithLongLong(ctx,hto ? hto->len : 0); - return REDISMODULE_OK; -} - -/* ====================== Example of a blocking command ==================== */ - -/* Reply callback for blocking command HELLOTYPE.BRANGE, this will get - * called when the key we blocked for is ready: we need to check if we - * can really serve the client, and reply OK or ERR accordingly. */ -int HelloBlock_Reply(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - RedisModuleString *keyname = RedisModule_GetBlockedClientReadyKey(ctx); - RedisModuleKey *key = RedisModule_OpenKey(ctx,keyname,REDISMODULE_READ); - int type = RedisModule_KeyType(key); - if (type != REDISMODULE_KEYTYPE_MODULE || - RedisModule_ModuleTypeGetType(key) != HelloType) - { - RedisModule_CloseKey(key); - return REDISMODULE_ERR; - } - - /* In case the key is able to serve our blocked client, let's directly - * use our original command implementation to make this example simpler. */ - RedisModule_CloseKey(key); - return HelloTypeRange_RedisCommand(ctx,argv,argc-1); -} - -/* Timeout callback for blocking command HELLOTYPE.BRANGE */ -int HelloBlock_Timeout(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - return RedisModule_ReplyWithSimpleString(ctx,"Request timedout"); -} - -/* Private data freeing callback for HELLOTYPE.BRANGE command. */ -void HelloBlock_FreeData(RedisModuleCtx *ctx, void *privdata) { - REDISMODULE_NOT_USED(ctx); - RedisModule_Free(privdata); -} - -/* HELLOTYPE.BRANGE key first count timeout -- This is a blocking version of - * the RANGE operation, in order to show how to use the API - * RedisModule_BlockClientOnKeys(). */ -int HelloTypeBRange_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 5) return RedisModule_WrongArity(ctx); - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - int type = RedisModule_KeyType(key); - if (type != REDISMODULE_KEYTYPE_EMPTY && - RedisModule_ModuleTypeGetType(key) != HelloType) - { - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - /* Parse the timeout before even trying to serve the client synchronously, - * so that we always fail ASAP on syntax errors. */ - long long timeout; - if (RedisModule_StringToLongLong(argv[4],&timeout) != REDISMODULE_OK) { - return RedisModule_ReplyWithError(ctx, - "ERR invalid timeout parameter"); - } - - /* Can we serve the reply synchronously? */ - if (type != REDISMODULE_KEYTYPE_EMPTY) { - return HelloTypeRange_RedisCommand(ctx,argv,argc-1); - } - - /* Otherwise let's block on the key. */ - void *privdata = RedisModule_Alloc(100); - RedisModule_BlockClientOnKeys(ctx,HelloBlock_Reply,HelloBlock_Timeout,HelloBlock_FreeData,timeout,argv+1,1,privdata); - return REDISMODULE_OK; -} - -/* ========================== "hellotype" type methods ======================= */ - -void *HelloTypeRdbLoad(RedisModuleIO *rdb, int encver) { - if (encver != 0) { - /* RedisModule_Log("warning","Can't load data with version %d", encver);*/ - return NULL; - } - uint64_t elements = RedisModule_LoadUnsigned(rdb); - struct HelloTypeObject *hto = createHelloTypeObject(); - while(elements--) { - int64_t ele = RedisModule_LoadSigned(rdb); - HelloTypeInsert(hto,ele); - } - return hto; -} - -void HelloTypeRdbSave(RedisModuleIO *rdb, void *value) { - struct HelloTypeObject *hto = value; - struct HelloTypeNode *node = hto->head; - RedisModule_SaveUnsigned(rdb,hto->len); - while(node) { - RedisModule_SaveSigned(rdb,node->value); - node = node->next; - } -} - -void HelloTypeAofRewrite(RedisModuleIO *aof, RedisModuleString *key, void *value) { - struct HelloTypeObject *hto = value; - struct HelloTypeNode *node = hto->head; - while(node) { - RedisModule_EmitAOF(aof,"HELLOTYPE.INSERT","sl",key,node->value); - node = node->next; - } -} - -/* The goal of this function is to return the amount of memory used by - * the HelloType value. */ -size_t HelloTypeMemUsage(const void *value) { - const struct HelloTypeObject *hto = value; - struct HelloTypeNode *node = hto->head; - return sizeof(*hto) + sizeof(*node)*hto->len; -} - -void HelloTypeFree(void *value) { - HelloTypeReleaseObject(value); -} - -void HelloTypeDigest(RedisModuleDigest *md, void *value) { - struct HelloTypeObject *hto = value; - struct HelloTypeNode *node = hto->head; - while(node) { - RedisModule_DigestAddLongLong(md,node->value); - node = node->next; - } - RedisModule_DigestEndSequence(md); -} - -/* This function must be present on each Redis module. It is used in order to - * register the commands into the Redis server. */ -int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - - if (RedisModule_Init(ctx,"hellotype",1,REDISMODULE_APIVER_1) - == REDISMODULE_ERR) return REDISMODULE_ERR; - - RedisModuleTypeMethods tm = { - .version = REDISMODULE_TYPE_METHOD_VERSION, - .rdb_load = HelloTypeRdbLoad, - .rdb_save = HelloTypeRdbSave, - .aof_rewrite = HelloTypeAofRewrite, - .mem_usage = HelloTypeMemUsage, - .free = HelloTypeFree, - .digest = HelloTypeDigest - }; - - HelloType = RedisModule_CreateDataType(ctx,"hellotype",0,&tm); - if (HelloType == NULL) return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellotype.insert", - HelloTypeInsert_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellotype.range", - HelloTypeRange_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellotype.len", - HelloTypeLen_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hellotype.brange", - HelloTypeBRange_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - return REDISMODULE_OK; -} diff --git a/examples/redis-unstable/src/modules/helloworld.c b/examples/redis-unstable/src/modules/helloworld.c deleted file mode 100644 index fdeb0a0..0000000 --- a/examples/redis-unstable/src/modules/helloworld.c +++ /dev/null @@ -1,601 +0,0 @@ -/* Helloworld module -- A few examples of the Redis Modules API in the form - * of commands showing how to accomplish common tasks. - * - * This module does not do anything useful, if not for a few commands. The - * examples are designed in order to show the API. - * - * ----------------------------------------------------------------------------- - * - * Copyright (c) 2016-Present, Redis Ltd. - * All rights reserved. - * - * Licensed under your choice of (a) the Redis Source Available License 2.0 - * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the - * GNU Affero General Public License v3 (AGPLv3). - */ - -#include "../redismodule.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> - -/* HELLO.SIMPLE is among the simplest commands you can implement. - * It just returns the currently selected DB id, a functionality which is - * missing in Redis. The command uses two important API calls: one to - * fetch the currently selected DB, the other in order to send the client - * an integer reply as response. */ -int HelloSimple_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - RedisModule_ReplyWithLongLong(ctx,RedisModule_GetSelectedDb(ctx)); - return REDISMODULE_OK; -} - -/* HELLO.PUSH.NATIVE re-implements RPUSH, and shows the low level modules API - * where you can "open" keys, make low level operations, create new keys by - * pushing elements into non-existing keys, and so forth. - * - * You'll find this command to be roughly as fast as the actual RPUSH - * command. */ -int HelloPushNative_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) -{ - if (argc != 3) return RedisModule_WrongArity(ctx); - - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - - RedisModule_ListPush(key,REDISMODULE_LIST_TAIL,argv[2]); - size_t newlen = RedisModule_ValueLength(key); - RedisModule_CloseKey(key); - RedisModule_ReplyWithLongLong(ctx,newlen); - return REDISMODULE_OK; -} - -/* HELLO.PUSH.CALL implements RPUSH using an higher level approach, calling - * a Redis command instead of working with the key in a low level way. This - * approach is useful when you need to call Redis commands that are not - * available as low level APIs, or when you don't need the maximum speed - * possible but instead prefer implementation simplicity. */ -int HelloPushCall_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) -{ - if (argc != 3) return RedisModule_WrongArity(ctx); - - RedisModuleCallReply *reply; - - reply = RedisModule_Call(ctx,"RPUSH","ss",argv[1],argv[2]); - long long len = RedisModule_CallReplyInteger(reply); - RedisModule_FreeCallReply(reply); - RedisModule_ReplyWithLongLong(ctx,len); - return REDISMODULE_OK; -} - -/* HELLO.PUSH.CALL2 - * This is exactly as HELLO.PUSH.CALL, but shows how we can reply to the - * client using directly a reply object that Call() returned. */ -int HelloPushCall2_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) -{ - if (argc != 3) return RedisModule_WrongArity(ctx); - - RedisModuleCallReply *reply; - - reply = RedisModule_Call(ctx,"RPUSH","ss",argv[1],argv[2]); - RedisModule_ReplyWithCallReply(ctx,reply); - RedisModule_FreeCallReply(reply); - return REDISMODULE_OK; -} - -/* HELLO.LIST.SUM.LEN returns the total length of all the items inside - * a Redis list, by using the high level Call() API. - * This command is an example of the array reply access. */ -int HelloListSumLen_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) -{ - if (argc != 2) return RedisModule_WrongArity(ctx); - - RedisModuleCallReply *reply; - - reply = RedisModule_Call(ctx,"LRANGE","sll",argv[1],(long long)0,(long long)-1); - size_t strlen = 0; - size_t items = RedisModule_CallReplyLength(reply); - size_t j; - for (j = 0; j < items; j++) { - RedisModuleCallReply *ele = RedisModule_CallReplyArrayElement(reply,j); - strlen += RedisModule_CallReplyLength(ele); - } - RedisModule_FreeCallReply(reply); - RedisModule_ReplyWithLongLong(ctx,strlen); - return REDISMODULE_OK; -} - -/* HELLO.LIST.SPLICE srclist dstlist count - * Moves 'count' elements from the tail of 'srclist' to the head of - * 'dstlist'. If less than count elements are available, it moves as much - * elements as possible. */ -int HelloListSplice_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 4) return RedisModule_WrongArity(ctx); - - RedisModuleKey *srckey = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - RedisModuleKey *dstkey = RedisModule_OpenKey(ctx,argv[2], - REDISMODULE_READ|REDISMODULE_WRITE); - - /* Src and dst key must be empty or lists. */ - if ((RedisModule_KeyType(srckey) != REDISMODULE_KEYTYPE_LIST && - RedisModule_KeyType(srckey) != REDISMODULE_KEYTYPE_EMPTY) || - (RedisModule_KeyType(dstkey) != REDISMODULE_KEYTYPE_LIST && - RedisModule_KeyType(dstkey) != REDISMODULE_KEYTYPE_EMPTY)) - { - RedisModule_CloseKey(srckey); - RedisModule_CloseKey(dstkey); - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - long long count; - if ((RedisModule_StringToLongLong(argv[3],&count) != REDISMODULE_OK) || - (count < 0)) { - RedisModule_CloseKey(srckey); - RedisModule_CloseKey(dstkey); - return RedisModule_ReplyWithError(ctx,"ERR invalid count"); - } - - while(count-- > 0) { - RedisModuleString *ele; - - ele = RedisModule_ListPop(srckey,REDISMODULE_LIST_TAIL); - if (ele == NULL) break; - RedisModule_ListPush(dstkey,REDISMODULE_LIST_HEAD,ele); - RedisModule_FreeString(ctx,ele); - } - - size_t len = RedisModule_ValueLength(srckey); - RedisModule_CloseKey(srckey); - RedisModule_CloseKey(dstkey); - RedisModule_ReplyWithLongLong(ctx,len); - return REDISMODULE_OK; -} - -/* Like the HELLO.LIST.SPLICE above, but uses automatic memory management - * in order to avoid freeing stuff. */ -int HelloListSpliceAuto_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 4) return RedisModule_WrongArity(ctx); - - RedisModule_AutoMemory(ctx); - - RedisModuleKey *srckey = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - RedisModuleKey *dstkey = RedisModule_OpenKey(ctx,argv[2], - REDISMODULE_READ|REDISMODULE_WRITE); - - /* Src and dst key must be empty or lists. */ - if ((RedisModule_KeyType(srckey) != REDISMODULE_KEYTYPE_LIST && - RedisModule_KeyType(srckey) != REDISMODULE_KEYTYPE_EMPTY) || - (RedisModule_KeyType(dstkey) != REDISMODULE_KEYTYPE_LIST && - RedisModule_KeyType(dstkey) != REDISMODULE_KEYTYPE_EMPTY)) - { - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - long long count; - if ((RedisModule_StringToLongLong(argv[3],&count) != REDISMODULE_OK) || - (count < 0)) - { - return RedisModule_ReplyWithError(ctx,"ERR invalid count"); - } - - while(count-- > 0) { - RedisModuleString *ele; - - ele = RedisModule_ListPop(srckey,REDISMODULE_LIST_TAIL); - if (ele == NULL) break; - RedisModule_ListPush(dstkey,REDISMODULE_LIST_HEAD,ele); - } - - size_t len = RedisModule_ValueLength(srckey); - RedisModule_ReplyWithLongLong(ctx,len); - return REDISMODULE_OK; -} - -/* HELLO.RAND.ARRAY <count> - * Shows how to generate arrays as commands replies. - * It just outputs <count> random numbers. */ -int HelloRandArray_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 2) return RedisModule_WrongArity(ctx); - long long count; - if (RedisModule_StringToLongLong(argv[1],&count) != REDISMODULE_OK || - count < 0) - return RedisModule_ReplyWithError(ctx,"ERR invalid count"); - - /* To reply with an array, we call RedisModule_ReplyWithArray() followed - * by other "count" calls to other reply functions in order to generate - * the elements of the array. */ - RedisModule_ReplyWithArray(ctx,count); - while(count--) RedisModule_ReplyWithLongLong(ctx,rand()); - return REDISMODULE_OK; -} - -/* This is a simple command to test replication. Because of the "!" modified - * in the RedisModule_Call() call, the two INCRs get replicated. - * Also note how the ECHO is replicated in an unexpected position (check - * comments the function implementation). */ -int HelloRepl1_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) -{ - REDISMODULE_NOT_USED(argv); - REDISMODULE_NOT_USED(argc); - RedisModule_AutoMemory(ctx); - - /* This will be replicated *after* the two INCR statements, since - * the Call() replication has precedence, so the actual replication - * stream will be: - * - * MULTI - * INCR foo - * INCR bar - * ECHO c foo - * EXEC - */ - RedisModule_Replicate(ctx,"ECHO","c","foo"); - - /* Using the "!" modifier we replicate the command if it - * modified the dataset in some way. */ - RedisModule_Call(ctx,"INCR","c!","foo"); - RedisModule_Call(ctx,"INCR","c!","bar"); - - RedisModule_ReplyWithLongLong(ctx,0); - - return REDISMODULE_OK; -} - -/* Another command to show replication. In this case, we call - * RedisModule_ReplicateVerbatim() to mean we want just the command to be - * propagated to slaves / AOF exactly as it was called by the user. - * - * This command also shows how to work with string objects. - * It takes a list, and increments all the elements (that must have - * a numerical value) by 1, returning the sum of all the elements - * as reply. - * - * Usage: HELLO.REPL2 <list-key> */ -int HelloRepl2_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 2) return RedisModule_WrongArity(ctx); - - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - - if (RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_LIST) - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - - size_t listlen = RedisModule_ValueLength(key); - long long sum = 0; - - /* Rotate and increment. */ - while(listlen--) { - RedisModuleString *ele = RedisModule_ListPop(key,REDISMODULE_LIST_TAIL); - long long val; - if (RedisModule_StringToLongLong(ele,&val) != REDISMODULE_OK) val = 0; - val++; - sum += val; - RedisModuleString *newele = RedisModule_CreateStringFromLongLong(ctx,val); - RedisModule_ListPush(key,REDISMODULE_LIST_HEAD,newele); - } - RedisModule_ReplyWithLongLong(ctx,sum); - RedisModule_ReplicateVerbatim(ctx); - return REDISMODULE_OK; -} - -/* This is an example of strings DMA access. Given a key containing a string - * it toggles the case of each character from lower to upper case or the - * other way around. - * - * No automatic memory management is used in this example (for the sake - * of variety). - * - * HELLO.TOGGLE.CASE key */ -int HelloToggleCase_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc != 2) return RedisModule_WrongArity(ctx); - - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - - int keytype = RedisModule_KeyType(key); - if (keytype != REDISMODULE_KEYTYPE_STRING && - keytype != REDISMODULE_KEYTYPE_EMPTY) - { - RedisModule_CloseKey(key); - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - if (keytype == REDISMODULE_KEYTYPE_STRING) { - size_t len, j; - char *s = RedisModule_StringDMA(key,&len,REDISMODULE_WRITE); - for (j = 0; j < len; j++) { - if (isupper(s[j])) { - s[j] = tolower(s[j]); - } else { - s[j] = toupper(s[j]); - } - } - } - - RedisModule_CloseKey(key); - RedisModule_ReplyWithSimpleString(ctx,"OK"); - RedisModule_ReplicateVerbatim(ctx); - return REDISMODULE_OK; -} - -/* HELLO.MORE.EXPIRE key milliseconds. - * - * If the key has already an associated TTL, extends it by "milliseconds" - * milliseconds. Otherwise no operation is performed. */ -int HelloMoreExpire_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - if (argc != 3) return RedisModule_WrongArity(ctx); - - mstime_t addms, expire; - - if (RedisModule_StringToLongLong(argv[2],&addms) != REDISMODULE_OK) - return RedisModule_ReplyWithError(ctx,"ERR invalid expire time"); - - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - expire = RedisModule_GetExpire(key); - if (expire != REDISMODULE_NO_EXPIRE) { - expire += addms; - RedisModule_SetExpire(key,expire); - } - return RedisModule_ReplyWithSimpleString(ctx,"OK"); -} - -/* HELLO.ZSUMRANGE key startscore endscore - * Return the sum of all the scores elements between startscore and endscore. - * - * The computation is performed two times, one time from start to end and - * another time backward. The two scores, returned as a two element array, - * should match.*/ -int HelloZsumRange_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - double score_start, score_end; - if (argc != 4) return RedisModule_WrongArity(ctx); - - if (RedisModule_StringToDouble(argv[2],&score_start) != REDISMODULE_OK || - RedisModule_StringToDouble(argv[3],&score_end) != REDISMODULE_OK) - { - return RedisModule_ReplyWithError(ctx,"ERR invalid range"); - } - - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - if (RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_ZSET) { - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - double scoresum_a = 0; - double scoresum_b = 0; - - RedisModule_ZsetFirstInScoreRange(key,score_start,score_end,0,0); - while(!RedisModule_ZsetRangeEndReached(key)) { - double score; - RedisModuleString *ele = RedisModule_ZsetRangeCurrentElement(key,&score); - RedisModule_FreeString(ctx,ele); - scoresum_a += score; - RedisModule_ZsetRangeNext(key); - } - RedisModule_ZsetRangeStop(key); - - RedisModule_ZsetLastInScoreRange(key,score_start,score_end,0,0); - while(!RedisModule_ZsetRangeEndReached(key)) { - double score; - RedisModuleString *ele = RedisModule_ZsetRangeCurrentElement(key,&score); - RedisModule_FreeString(ctx,ele); - scoresum_b += score; - RedisModule_ZsetRangePrev(key); - } - - RedisModule_ZsetRangeStop(key); - - RedisModule_CloseKey(key); - - RedisModule_ReplyWithArray(ctx,2); - RedisModule_ReplyWithDouble(ctx,scoresum_a); - RedisModule_ReplyWithDouble(ctx,scoresum_b); - return REDISMODULE_OK; -} - -/* HELLO.LEXRANGE key min_lex max_lex min_age max_age - * This command expects a sorted set stored at key in the following form: - * - All the elements have score 0. - * - Elements are pairs of "<name>:<age>", for example "Anna:52". - * The command will return all the sorted set items that are lexicographically - * between the specified range (using the same format as ZRANGEBYLEX) - * and having an age between min_age and max_age. */ -int HelloLexRange_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - - if (argc != 6) return RedisModule_WrongArity(ctx); - - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - if (RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_ZSET) { - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - if (RedisModule_ZsetFirstInLexRange(key,argv[2],argv[3]) != REDISMODULE_OK) { - return RedisModule_ReplyWithError(ctx,"invalid range"); - } - - int arraylen = 0; - RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN); - while(!RedisModule_ZsetRangeEndReached(key)) { - double score; - RedisModuleString *ele = RedisModule_ZsetRangeCurrentElement(key,&score); - RedisModule_ReplyWithString(ctx,ele); - RedisModule_FreeString(ctx,ele); - RedisModule_ZsetRangeNext(key); - arraylen++; - } - RedisModule_ZsetRangeStop(key); - RedisModule_ReplySetArrayLength(ctx,arraylen); - RedisModule_CloseKey(key); - return REDISMODULE_OK; -} - -/* HELLO.HCOPY key srcfield dstfield - * This is just an example command that sets the hash field dstfield to the - * same value of srcfield. If srcfield does not exist no operation is - * performed. - * - * The command returns 1 if the copy is performed (srcfield exists) otherwise - * 0 is returned. */ -int HelloHCopy_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - - if (argc != 4) return RedisModule_WrongArity(ctx); - RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], - REDISMODULE_READ|REDISMODULE_WRITE); - int type = RedisModule_KeyType(key); - if (type != REDISMODULE_KEYTYPE_HASH && - type != REDISMODULE_KEYTYPE_EMPTY) - { - return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); - } - - /* Get the old field value. */ - RedisModuleString *oldval; - RedisModule_HashGet(key,REDISMODULE_HASH_NONE,argv[2],&oldval,NULL); - if (oldval) { - RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[3],oldval,NULL); - } - RedisModule_ReplyWithLongLong(ctx,oldval != NULL); - return REDISMODULE_OK; -} - -/* HELLO.LEFTPAD str len ch - * This is an implementation of the infamous LEFTPAD function, that - * was at the center of an issue with the npm modules system in March 2016. - * - * LEFTPAD is a good example of using a Redis Modules API called - * "pool allocator", that was a famous way to allocate memory in yet another - * open source project, the Apache web server. - * - * The concept is very simple: there is memory that is useful to allocate - * only in the context of serving a request, and must be freed anyway when - * the callback implementing the command returns. So in that case the module - * does not need to retain a reference to these allocations, it is just - * required to free the memory before returning. When this is the case the - * module can call RedisModule_PoolAlloc() instead, that works like malloc() - * but will automatically free the memory when the module callback returns. - * - * Note that PoolAlloc() does not necessarily require AutoMemory to be - * active. */ -int HelloLeftPad_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ - long long padlen; - - if (argc != 4) return RedisModule_WrongArity(ctx); - - if ((RedisModule_StringToLongLong(argv[2],&padlen) != REDISMODULE_OK) || - (padlen< 0)) { - return RedisModule_ReplyWithError(ctx,"ERR invalid padding length"); - } - size_t strlen, chlen; - const char *str = RedisModule_StringPtrLen(argv[1], &strlen); - const char *ch = RedisModule_StringPtrLen(argv[3], &chlen); - - /* If the string is already larger than the target len, just return - * the string itself. */ - if (strlen >= (size_t)padlen) - return RedisModule_ReplyWithString(ctx,argv[1]); - - /* Padding must be a single character in this simple implementation. */ - if (chlen != 1) - return RedisModule_ReplyWithError(ctx, - "ERR padding must be a single char"); - - /* Here we use our pool allocator, for our throw-away allocation. */ - padlen -= strlen; - char *buf = RedisModule_PoolAlloc(ctx,padlen+strlen); - for (long long j = 0; j < padlen; j++) buf[j] = *ch; - memcpy(buf+padlen,str,strlen); - - RedisModule_ReplyWithStringBuffer(ctx,buf,padlen+strlen); - return REDISMODULE_OK; -} - -/* This function must be present on each Redis module. It is used in order to - * register the commands into the Redis server. */ -int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (RedisModule_Init(ctx,"helloworld",1,REDISMODULE_APIVER_1) - == REDISMODULE_ERR) return REDISMODULE_ERR; - - /* Log the list of parameters passing loading the module. */ - for (int j = 0; j < argc; j++) { - const char *s = RedisModule_StringPtrLen(argv[j],NULL); - printf("Module loaded with ARGV[%d] = %s\n", j, s); - } - - if (RedisModule_CreateCommand(ctx,"hello.simple", - HelloSimple_RedisCommand,"readonly",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.push.native", - HelloPushNative_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.push.call", - HelloPushCall_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.push.call2", - HelloPushCall2_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.list.sum.len", - HelloListSumLen_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.list.splice", - HelloListSplice_RedisCommand,"write deny-oom",1,2,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.list.splice.auto", - HelloListSpliceAuto_RedisCommand, - "write deny-oom",1,2,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.rand.array", - HelloRandArray_RedisCommand,"readonly",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.repl1", - HelloRepl1_RedisCommand,"write",0,0,0) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.repl2", - HelloRepl2_RedisCommand,"write",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.toggle.case", - HelloToggleCase_RedisCommand,"write",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.more.expire", - HelloMoreExpire_RedisCommand,"write",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.zsumrange", - HelloZsumRange_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.lexrange", - HelloLexRange_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.hcopy", - HelloHCopy_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - if (RedisModule_CreateCommand(ctx,"hello.leftpad", - HelloLeftPad_RedisCommand,"",1,1,1) == REDISMODULE_ERR) - return REDISMODULE_ERR; - - return REDISMODULE_OK; -} |
