Skip to content

Commit

Permalink
Fix Redis 7.2 undefined symbol: RedisModule_TryCalloc
Browse files Browse the repository at this point in the history
RedisLabsModules#67

Signed-off-by: fcbry <bryan.hunt@foodsconnected.com>
  • Loading branch information
fcbry committed Aug 12, 2024
1 parent 6a62be4 commit 0139ac1
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 166 deletions.
157 changes: 24 additions & 133 deletions example/module.c
Original file line number Diff line number Diff line change
@@ -1,146 +1,37 @@
#include "../redismodule.h"
#include "../rmutil/util.h"
#include "../rmutil/strings.h"
#include "../rmutil/test_util.h"
// #include "../rmutil/util.h"
// #include "../rmutil/strings.h"
// #include "../rmutil/test_util.h"

/* EXAMPLE.PARSE [SUM <x> <y>] | [PROD <x> <y>]
* Demonstrates the automatic arg parsing utility.
* If the command receives "SUM <x> <y>" it returns their sum
* If it receives "PROD <x> <y>" it returns their product
*/
int ParseCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
// #include "redismodule.h"
#include <string.h>
#include <stdio.h>

// we must have at least 4 args
if (argc < 4) {
int LogSet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 3) {
return RedisModule_WrongArity(ctx);
}

// init auto memory for created strings
RedisModule_AutoMemory(ctx);
long long x, y;

// If we got SUM - return the sum of 2 consecutive arguments
if (RMUtil_ParseArgsAfter("SUM", argv, argc, "ll", &x, &y) ==
REDISMODULE_OK) {
RedisModule_ReplyWithLongLong(ctx, x + y);
return REDISMODULE_OK;
}

// If we got PROD - return the product of 2 consecutive arguments
if (RMUtil_ParseArgsAfter("PROD", argv, argc, "ll", &x, &y) ==
REDISMODULE_OK) {
RedisModule_ReplyWithLongLong(ctx, x * y);
return REDISMODULE_OK;
}

// something is fishy...
RedisModule_ReplyWithError(ctx, "Invalid arguments");

return REDISMODULE_ERR;
}

/*
* example.HGETSET <key> <element> <value>
* Atomically set a value in a HASH key to <value> and return its value before
* the HSET.
*
* Basically atomic HGET + HSET
*/
int HGetSetCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {

// we need EXACTLY 4 arguments
if (argc != 4) {
return RedisModule_WrongArity(ctx);
}
RedisModule_AutoMemory(ctx);

// open the key and make sure it's indeed a HASH and not empty
RedisModuleKey *key =
RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ | REDISMODULE_WRITE);
if (RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_HASH &&
RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_EMPTY) {
return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
}

// get the current value of the hash element
RedisModuleCallReply *rep =
RedisModule_Call(ctx, "HGET", "ss", argv[1], argv[2]);
RMUTIL_ASSERT_NOERROR(ctx, rep);

// set the new value of the element
RedisModuleCallReply *srep =
RedisModule_Call(ctx, "HSET", "sss", argv[1], argv[2], argv[3]);
RMUTIL_ASSERT_NOERROR(ctx, srep);

// if the value was null before - we just return null
if (RedisModule_CallReplyType(rep) == REDISMODULE_REPLY_NULL) {
RedisModule_ReplyWithNull(ctx);
return REDISMODULE_OK;
}

// forward the HGET reply to the client
RedisModule_ReplyWithCallReply(ctx, rep);
RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
size_t val_len;
const char *val = RedisModule_StringPtrLen(argv[2], &val_len);
// Perform the SET operation
RedisModule_StringSet(key, argv[2]);
// Check if value size > 4 bytes and log if so
if (val_len > 4) {
const char *key_str = RedisModule_StringPtrLen(argv[1], NULL);
printf("LOGSET: Key '%s' set with value of size %zu bytes\n", key_str, val_len);
}
RedisModule_CloseKey(key);
RedisModule_ReplyWithSimpleString(ctx, "OK");
return REDISMODULE_OK;
}

// Test the the PARSE command
int testParse(RedisModuleCtx *ctx) {

RedisModuleCallReply *r =
RedisModule_Call(ctx, "example.parse", "ccc", "SUM", "5", "2");
RMUtil_Assert(RedisModule_CallReplyType(r) == REDISMODULE_REPLY_INTEGER);
RMUtil_AssertReplyEquals(r, "7");

r = RedisModule_Call(ctx, "example.parse", "ccc", "PROD", "5", "2");
RMUtil_Assert(RedisModule_CallReplyType(r) == REDISMODULE_REPLY_INTEGER);
RMUtil_AssertReplyEquals(r, "10");
return 0;
}

// test the HGETSET command
int testHgetSet(RedisModuleCtx *ctx) {
RedisModuleCallReply *r =
RedisModule_Call(ctx, "example.hgetset", "ccc", "foo", "bar", "baz");
RMUtil_Assert(RedisModule_CallReplyType(r) != REDISMODULE_REPLY_ERROR);

r = RedisModule_Call(ctx, "example.hgetset", "ccc", "foo", "bar", "bag");
RMUtil_Assert(RedisModule_CallReplyType(r) == REDISMODULE_REPLY_STRING);
RMUtil_AssertReplyEquals(r, "baz");
r = RedisModule_Call(ctx, "example.hgetset", "ccc", "foo", "bar", "bang");
RMUtil_AssertReplyEquals(r, "bag");
return 0;
}

// Unit test entry point for the module
int TestModule(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
RedisModule_AutoMemory(ctx);

RMUtil_Test(testParse);
RMUtil_Test(testHgetSet);

RedisModule_ReplyWithSimpleString(ctx, "PASS");
return REDISMODULE_OK;
}

int RedisModule_OnLoad(RedisModuleCtx *ctx) {

// Register the module itself
if (RedisModule_Init(ctx, "example", 1, REDISMODULE_APIVER_1) ==
REDISMODULE_ERR) {
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (RedisModule_Init(ctx, "LogSetModule", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) {
return REDISMODULE_ERR;
}

// register example.parse - the default registration syntax
if (RedisModule_CreateCommand(ctx, "example.parse", ParseCommand, "readonly",
1, 1, 1) == REDISMODULE_ERR) {
if (RedisModule_CreateCommand(ctx, "logset", LogSet_RedisCommand, "write", 1, 1, 1) ==
REDISMODULE_ERR) {
return REDISMODULE_ERR;
}

// register example.hgetset - using the shortened utility registration macro
RMUtil_RegisterWriteCmd(ctx, "example.hgetset", HGetSetCommand);

// register the unit test
RMUtil_RegisterWriteCmd(ctx, "example.test", TestModule);

return REDISMODULE_OK;
}
33 changes: 0 additions & 33 deletions redismodule.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
#ifndef REDISMODULE_H
#define REDISMODULE_H

// clang-format off

#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct RedisModuleString RedisModuleString;
typedef struct RedisModuleKey RedisModuleKey;
Expand Down Expand Up @@ -952,10 +947,6 @@ typedef struct RedisModuleTypeMethods {
RedisModule_GetApi("RedisModule_" #name, ((void **)&RedisModule_ ## name))

/* Default API declaration prefix (not 'extern' for backwards compatibility) */
#ifndef REDISMODULE_MAIN
#define REDISMODULE_API extern
#endif

#ifndef REDISMODULE_API
#define REDISMODULE_API
#endif
Expand All @@ -968,18 +959,15 @@ typedef struct RedisModuleTypeMethods {
REDISMODULE_API void * (*RedisModule_Alloc)(size_t bytes) REDISMODULE_ATTR;
REDISMODULE_API void * (*RedisModule_TryAlloc)(size_t bytes) REDISMODULE_ATTR;
REDISMODULE_API void * (*RedisModule_Realloc)(void *ptr, size_t bytes) REDISMODULE_ATTR;
REDISMODULE_API void * (*RedisModule_TryRealloc)(void *ptr, size_t bytes) REDISMODULE_ATTR;
REDISMODULE_API void (*RedisModule_Free)(void *ptr) REDISMODULE_ATTR;
REDISMODULE_API void * (*RedisModule_Calloc)(size_t nmemb, size_t size) REDISMODULE_ATTR;
REDISMODULE_API void * (*RedisModule_TryCalloc)(size_t nmemb, size_t size) REDISMODULE_ATTR;
REDISMODULE_API char * (*RedisModule_Strdup)(const char *str) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_GetApi)(const char *, void *) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_CreateCommand)(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) REDISMODULE_ATTR;
REDISMODULE_API RedisModuleCommand *(*RedisModule_GetCommand)(RedisModuleCtx *ctx, const char *name) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_CreateSubcommand)(RedisModuleCommand *parent, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_SetCommandInfo)(RedisModuleCommand *command, const RedisModuleCommandInfo *info) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_SetCommandACLCategories)(RedisModuleCommand *command, const char *ctgrsflags) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_AddACLCategory)(RedisModuleCtx *ctx, const char *name) REDISMODULE_ATTR;
REDISMODULE_API void (*RedisModule_SetModuleAttribs)(RedisModuleCtx *ctx, const char *name, int ver, int apiver) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_IsModuleNameBusy)(const char *name) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_WrongArity)(RedisModuleCtx *ctx) REDISMODULE_ATTR;
Expand Down Expand Up @@ -1262,8 +1250,6 @@ REDISMODULE_API void (*RedisModule_GetRandomBytes)(unsigned char *dst, size_t le
REDISMODULE_API void (*RedisModule_GetRandomHexChars)(char *dst, size_t len) REDISMODULE_ATTR;
REDISMODULE_API void (*RedisModule_SetDisconnectCallback)(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback) REDISMODULE_ATTR;
REDISMODULE_API void (*RedisModule_SetClusterFlags)(RedisModuleCtx *ctx, uint64_t flags) REDISMODULE_ATTR;
REDISMODULE_API unsigned int (*RedisModule_ClusterKeySlot)(RedisModuleString *key) REDISMODULE_ATTR;
REDISMODULE_API const char *(*RedisModule_ClusterCanonicalKeyNameInSlot)(unsigned int slot) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_ExportSharedAPI)(RedisModuleCtx *ctx, const char *apiname, void *func) REDISMODULE_ATTR;
REDISMODULE_API void * (*RedisModule_GetSharedAPI)(RedisModuleCtx *ctx, const char *apiname) REDISMODULE_ATTR;
REDISMODULE_API RedisModuleCommandFilter * (*RedisModule_RegisterCommandFilter)(RedisModuleCtx *ctx, RedisModuleCommandFilterFunc cb, int flags) REDISMODULE_ATTR;
Expand Down Expand Up @@ -1327,10 +1313,6 @@ REDISMODULE_API int (*RedisModule_RdbSave)(RedisModuleCtx *ctx, RedisModuleRdbSt

#define RedisModule_IsAOFClient(id) ((id) == UINT64_MAX)

#ifdef REDISMODULE_SDK_RLEC
#include "redismodule-rlec.h"
#endif

/* This is included inline inside each Redis module. */
static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) REDISMODULE_ATTR_UNUSED;
static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) {
Expand All @@ -1339,17 +1321,14 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API(Alloc);
REDISMODULE_GET_API(TryAlloc);
REDISMODULE_GET_API(Calloc);
REDISMODULE_GET_API(TryCalloc);
REDISMODULE_GET_API(Free);
REDISMODULE_GET_API(Realloc);
REDISMODULE_GET_API(TryRealloc);
REDISMODULE_GET_API(Strdup);
REDISMODULE_GET_API(CreateCommand);
REDISMODULE_GET_API(GetCommand);
REDISMODULE_GET_API(CreateSubcommand);
REDISMODULE_GET_API(SetCommandInfo);
REDISMODULE_GET_API(SetCommandACLCategories);
REDISMODULE_GET_API(AddACLCategory);
REDISMODULE_GET_API(SetModuleAttribs);
REDISMODULE_GET_API(IsModuleNameBusy);
REDISMODULE_GET_API(WrongArity);
Expand Down Expand Up @@ -1632,8 +1611,6 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API(GetRandomBytes);
REDISMODULE_GET_API(GetRandomHexChars);
REDISMODULE_GET_API(SetClusterFlags);
REDISMODULE_GET_API(ClusterKeySlot);
REDISMODULE_GET_API(ClusterCanonicalKeyNameInSlot);
REDISMODULE_GET_API(ExportSharedAPI);
REDISMODULE_GET_API(GetSharedAPI);
REDISMODULE_GET_API(RegisterCommandFilter);
Expand Down Expand Up @@ -1695,11 +1672,6 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API(RdbLoad);
REDISMODULE_GET_API(RdbSave);


#ifdef REDISMODULE_RLEC_API_DEFS
REDISMODULE_RLEC_API_DEFS
#endif

if (RedisModule_IsModuleNameBusy && RedisModule_IsModuleNameBusy(name)) return REDISMODULE_ERR;
RedisModule_SetModuleAttribs(ctx,name,ver,apiver);
return REDISMODULE_OK;
Expand All @@ -1710,9 +1682,4 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
#define RMAPI_FUNC_SUPPORTED(func) (func != NULL)

#endif /* REDISMODULE_CORE */

#ifdef __cplusplus
}
#endif

#endif /* REDISMODULE_H */

0 comments on commit 0139ac1

Please sign in to comment.