mirror of
https://github.com/fluencelabs/redis
synced 2025-03-19 09:00:51 +00:00
Modules: avoid conflict between modules func pointers and dynamic symbols.
In modules we fill a set of function pointers defined in redismodule.h, populating a set of APIs that are callable from the module. We use this manual process instead of resorting to dynamic linking so that we have exact control on how we pass the API to the module, and we can even pass different functions for the same name, depending on the API version declared by the module. However if the function pointers in redismodule.h and the functions defined in module.c have the same name, they conflict since the core exports the symbols to the module. There is probably some compiler flags trick to avoid this, but in order to be safer in the future and be more easily compatible with different builidng systems, this commit changes the internal function prefix from RedisModule_ to RM_, so for example: RM_StringSet() will be exported as RedisModule_StringSet()
This commit is contained in:
parent
6020469452
commit
85919f80ed
180
src/module.c
180
src/module.c
@ -53,11 +53,11 @@ struct RedisModuleCtx {
|
|||||||
};
|
};
|
||||||
typedef struct RedisModuleCtx RedisModuleCtx;
|
typedef struct RedisModuleCtx RedisModuleCtx;
|
||||||
|
|
||||||
#define REDISMODULE_CTX_INIT {(void*)(unsigned long)&RedisModule_GetApi, NULL, NULL, NULL, 0, 0, 0}
|
#define REDISMODULE_CTX_INIT {(void*)(unsigned long)&RM_GetApi, NULL, NULL, NULL, 0, 0, 0}
|
||||||
#define REDISMODULE_CTX_MULTI_EMITTED (1<<0)
|
#define REDISMODULE_CTX_MULTI_EMITTED (1<<0)
|
||||||
#define REDISMODULE_CTX_AUTO_MEMORY (1<<1)
|
#define REDISMODULE_CTX_AUTO_MEMORY (1<<1)
|
||||||
|
|
||||||
/* This represents a Redis key opened with RedisModule_OpenKey(). */
|
/* This represents a Redis key opened with RM_OpenKey(). */
|
||||||
struct RedisModuleKey {
|
struct RedisModuleKey {
|
||||||
RedisModuleCtx *ctx;
|
RedisModuleCtx *ctx;
|
||||||
redisDb *db;
|
redisDb *db;
|
||||||
@ -85,7 +85,7 @@ typedef struct RedisModuleCommandProxy RedisModuleCommandProxy;
|
|||||||
#define REDISMODULE_REPLYFLAG_NESTED (1<<1) /* Nested reply object. No proto
|
#define REDISMODULE_REPLYFLAG_NESTED (1<<1) /* Nested reply object. No proto
|
||||||
or struct free. */
|
or struct free. */
|
||||||
|
|
||||||
/* Reply of RedisModule_Call() function. The function is filled in a lazy
|
/* Reply of RM_Call() function. The function is filled in a lazy
|
||||||
* way depending on the function called on the reply structure. By default
|
* way depending on the function called on the reply structure. By default
|
||||||
* only the type and proto are filled. */
|
* only the type and proto are filled. */
|
||||||
struct RedisModuleCallReply {
|
struct RedisModuleCallReply {
|
||||||
@ -110,9 +110,9 @@ typedef struct RedisModuleCallReply RedisModuleCallReply;
|
|||||||
* Prototypes
|
* Prototypes
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void RedisModule_FreeCallReply(RedisModuleCallReply *reply);
|
void RM_FreeCallReply(RedisModuleCallReply *reply);
|
||||||
void RedisModule_CloseKey(RedisModuleKey *key);
|
void RM_CloseKey(RedisModuleKey *key);
|
||||||
void RedisModule_AutoMemoryCollect(RedisModuleCtx *ctx);
|
void RM_AutoMemoryCollect(RedisModuleCtx *ctx);
|
||||||
robj **moduleCreateArgvFromUserFormat(const char *cmdname, const char *fmt, int *argcp, int *flags, va_list ap);
|
robj **moduleCreateArgvFromUserFormat(const char *cmdname, const char *fmt, int *argcp, int *flags, va_list ap);
|
||||||
void moduleReplicateMultiIfNeeded(RedisModuleCtx *ctx);
|
void moduleReplicateMultiIfNeeded(RedisModuleCtx *ctx);
|
||||||
|
|
||||||
@ -186,12 +186,18 @@ int moduleDelKeyIfEmpty(RedisModuleKey *key) {
|
|||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* Service API exported to modules
|
* Service API exported to modules
|
||||||
|
*
|
||||||
|
* Note that all the exported APIs are called RM_<funcname> in the core
|
||||||
|
* and RedisModule_<funcname> in the module side (defined as function
|
||||||
|
* pointers in redismodule.h). In this way the dynamic linker does not
|
||||||
|
* mess with our global function pointers, overriding it with the symbols
|
||||||
|
* defined in the main executable having the same names.
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Lookup the requested module API and store the function pointer into the
|
/* Lookup the requested module API and store the function pointer into the
|
||||||
* target pointer. The function returns REDISMODULE_ERR if there is no such
|
* target pointer. The function returns REDISMODULE_ERR if there is no such
|
||||||
* named API, otherwise REDISMODULE_OK. */
|
* named API, otherwise REDISMODULE_OK. */
|
||||||
int RedisModule_GetApi(const char *funcname, void **targetPtrPtr) {
|
int RM_GetApi(const char *funcname, void **targetPtrPtr) {
|
||||||
dictEntry *he = dictFind(server.moduleapi, funcname);
|
dictEntry *he = dictFind(server.moduleapi, funcname);
|
||||||
if (!he) return REDISMODULE_ERR;
|
if (!he) return REDISMODULE_ERR;
|
||||||
*targetPtrPtr = dictGetVal(he);
|
*targetPtrPtr = dictGetVal(he);
|
||||||
@ -207,7 +213,7 @@ void RedisModuleCommandDispatcher(client *c) {
|
|||||||
ctx.module = cp->module;
|
ctx.module = cp->module;
|
||||||
ctx.client = c;
|
ctx.client = c;
|
||||||
cp->func(&ctx,(void**)c->argv,c->argc);
|
cp->func(&ctx,(void**)c->argv,c->argc);
|
||||||
RedisModule_AutoMemoryCollect(&ctx);
|
RM_AutoMemoryCollect(&ctx);
|
||||||
preventCommandPropagation(c);
|
preventCommandPropagation(c);
|
||||||
|
|
||||||
/* Handle the replication of the final EXEC, since whatever a command
|
/* Handle the replication of the final EXEC, since whatever a command
|
||||||
@ -225,7 +231,7 @@ void RedisModuleCommandDispatcher(client *c) {
|
|||||||
* calling the function pointer 'func' using the RedisModule calling
|
* calling the function pointer 'func' using the RedisModule calling
|
||||||
* convention. The function returns REDISMODULE_ERR if the specified command
|
* convention. The function returns REDISMODULE_ERR if the specified command
|
||||||
* name is already busy, otherwise REDISMODULE_OK. */
|
* name is already busy, otherwise REDISMODULE_OK. */
|
||||||
int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc) {
|
int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc) {
|
||||||
struct redisCommand *rediscmd;
|
struct redisCommand *rediscmd;
|
||||||
RedisModuleCommandProxy *cp;
|
RedisModuleCommandProxy *cp;
|
||||||
sds cmdname = sdsnew(name);
|
sds cmdname = sdsnew(name);
|
||||||
@ -262,8 +268,8 @@ int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModule
|
|||||||
return REDISMODULE_OK;
|
return REDISMODULE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called by RedisModule_Init() to setup the ctx->module structure. */
|
/* Called by RM_Init() to setup the ctx->module structure. */
|
||||||
void RedisModule_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int apiver){
|
void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int apiver){
|
||||||
RedisModule *module;
|
RedisModule *module;
|
||||||
|
|
||||||
if (ctx->module != NULL) return;
|
if (ctx->module != NULL) return;
|
||||||
@ -279,12 +285,12 @@ void RedisModule_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Enable auto memory. */
|
/* Enable auto memory. */
|
||||||
void RedisModule_AutoMemory(RedisModuleCtx *ctx) {
|
void RM_AutoMemory(RedisModuleCtx *ctx) {
|
||||||
ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
|
ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a new object to release automatically when the callback returns. */
|
/* Add a new object to release automatically when the callback returns. */
|
||||||
void RedisModule_AutoMemoryAdd(RedisModuleCtx *ctx, int type, void *ptr) {
|
void RM_AutoMemoryAdd(RedisModuleCtx *ctx, int type, void *ptr) {
|
||||||
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
||||||
if (ctx->amqueue_used == ctx->amqueue_len) {
|
if (ctx->amqueue_used == ctx->amqueue_len) {
|
||||||
ctx->amqueue_len *= 2;
|
ctx->amqueue_len *= 2;
|
||||||
@ -298,7 +304,7 @@ void RedisModule_AutoMemoryAdd(RedisModuleCtx *ctx, int type, void *ptr) {
|
|||||||
|
|
||||||
/* Mark an object as freed in the auto release queue, so that users can still
|
/* Mark an object as freed in the auto release queue, so that users can still
|
||||||
* free things manually if they want. */
|
* free things manually if they want. */
|
||||||
void RedisModule_AutoMemoryFreed(RedisModuleCtx *ctx, int type, void *ptr) {
|
void RM_AutoMemoryFreed(RedisModuleCtx *ctx, int type, void *ptr) {
|
||||||
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
||||||
|
|
||||||
int j;
|
int j;
|
||||||
@ -315,7 +321,7 @@ void RedisModule_AutoMemoryFreed(RedisModuleCtx *ctx, int type, void *ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Release all the objects in queue. */
|
/* Release all the objects in queue. */
|
||||||
void RedisModule_AutoMemoryCollect(RedisModuleCtx *ctx) {
|
void RM_AutoMemoryCollect(RedisModuleCtx *ctx) {
|
||||||
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
||||||
/* Clear the AUTO_MEMORY flag from the context, otherwise the functions
|
/* Clear the AUTO_MEMORY flag from the context, otherwise the functions
|
||||||
* we call to free the resources, will try to scan the auto release
|
* we call to free the resources, will try to scan the auto release
|
||||||
@ -326,8 +332,8 @@ void RedisModule_AutoMemoryCollect(RedisModuleCtx *ctx) {
|
|||||||
void *ptr = ctx->amqueue[j].ptr;
|
void *ptr = ctx->amqueue[j].ptr;
|
||||||
switch(ctx->amqueue[j].type) {
|
switch(ctx->amqueue[j].type) {
|
||||||
case REDISMODULE_AM_STRING: decrRefCount(ptr); break;
|
case REDISMODULE_AM_STRING: decrRefCount(ptr); break;
|
||||||
case REDISMODULE_AM_REPLY: RedisModule_FreeCallReply(ptr); break;
|
case REDISMODULE_AM_REPLY: RM_FreeCallReply(ptr); break;
|
||||||
case REDISMODULE_AM_KEY: RedisModule_CloseKey(ptr); break;
|
case REDISMODULE_AM_KEY: RM_CloseKey(ptr); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
|
ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
|
||||||
@ -342,31 +348,31 @@ void RedisModule_AutoMemoryCollect(RedisModuleCtx *ctx) {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Create a new module string object. Must be freed with
|
/* Create a new module string object. Must be freed with
|
||||||
* RedisModule_FreeString(), unless automatic memory is enabled. */
|
* RM_FreeString(), unless automatic memory is enabled. */
|
||||||
RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len)
|
RedisModuleString *RM_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len)
|
||||||
{
|
{
|
||||||
RedisModuleString *o = createStringObject(ptr,len);
|
RedisModuleString *o = createStringObject(ptr,len);
|
||||||
RedisModule_AutoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
|
RM_AutoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like RedisModule_CreatString, but creates a string starting from a long long
|
/* Like RM_CreatString, but creates a string starting from a long long
|
||||||
* integer instea of taking a buffer and length. */
|
* integer instea of taking a buffer and length. */
|
||||||
RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll) {
|
RedisModuleString *RM_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll) {
|
||||||
char buf[LONG_STR_SIZE];
|
char buf[LONG_STR_SIZE];
|
||||||
size_t len = ll2string(buf,sizeof(buf),ll);
|
size_t len = ll2string(buf,sizeof(buf),ll);
|
||||||
return RedisModule_CreateString(ctx,buf,len);
|
return RM_CreateString(ctx,buf,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free a module string object obtained with one of the Redis API calls
|
/* Free a module string object obtained with one of the Redis API calls
|
||||||
* that return new string objects. */
|
* that return new string objects. */
|
||||||
void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str) {
|
void RM_FreeString(RedisModuleCtx *ctx, RedisModuleString *str) {
|
||||||
decrRefCount(str);
|
decrRefCount(str);
|
||||||
RedisModule_AutoMemoryFreed(ctx,REDISMODULE_AM_STRING,str);
|
RM_AutoMemoryFreed(ctx,REDISMODULE_AM_STRING,str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the string pointer and length. */
|
/* Return the string pointer and length. */
|
||||||
const char *RedisModule_StringPtrLen(RedisModuleString *str, size_t *len) {
|
const char *RM_StringPtrLen(RedisModuleString *str, size_t *len) {
|
||||||
if (len) *len = sdslen(str->ptr);
|
if (len) *len = sdslen(str->ptr);
|
||||||
return str->ptr;
|
return str->ptr;
|
||||||
}
|
}
|
||||||
@ -375,7 +381,7 @@ const char *RedisModule_StringPtrLen(RedisModuleString *str, size_t *len) {
|
|||||||
* Returns REDISMODULE_OK on success. If the string can't be parsed
|
* Returns REDISMODULE_OK on success. If the string can't be parsed
|
||||||
* as a valid, strict long long (no spaces before/after), REDISMODULE_ERR
|
* as a valid, strict long long (no spaces before/after), REDISMODULE_ERR
|
||||||
* is returned. */
|
* is returned. */
|
||||||
int RedisModule_StringToLongLong(RedisModuleString *str, long long *ll) {
|
int RM_StringToLongLong(RedisModuleString *str, long long *ll) {
|
||||||
return string2ll(str->ptr,sdslen(str->ptr),ll) ? REDISMODULE_OK :
|
return string2ll(str->ptr,sdslen(str->ptr),ll) ? REDISMODULE_OK :
|
||||||
REDISMODULE_ERR;
|
REDISMODULE_ERR;
|
||||||
}
|
}
|
||||||
@ -387,11 +393,11 @@ int RedisModule_StringToLongLong(RedisModuleString *str, long long *ll) {
|
|||||||
* 'return' in order to return from the command implementation with:
|
* 'return' in order to return from the command implementation with:
|
||||||
*
|
*
|
||||||
* if (... some condition ...)
|
* if (... some condition ...)
|
||||||
* return RedisModule_ReplyWithLongLong(ctx,mycount);
|
* return RM_ReplyWithLongLong(ctx,mycount);
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Send an error about the number of arguments given to the command. */
|
/* Send an error about the number of arguments given to the command. */
|
||||||
int RedisModule_WrongArity(RedisModuleCtx *ctx) {
|
int RM_WrongArity(RedisModuleCtx *ctx) {
|
||||||
addReplyErrorFormat(ctx->client,
|
addReplyErrorFormat(ctx->client,
|
||||||
"wrong number of arguments for '%s' command",
|
"wrong number of arguments for '%s' command",
|
||||||
(char*)ctx->client->argv[0]->ptr);
|
(char*)ctx->client->argv[0]->ptr);
|
||||||
@ -400,14 +406,14 @@ int RedisModule_WrongArity(RedisModuleCtx *ctx) {
|
|||||||
|
|
||||||
/* Send an integer reply with the specified long long value.
|
/* Send an integer reply with the specified long long value.
|
||||||
* The function always returns REDISMODULE_OK. */
|
* The function always returns REDISMODULE_OK. */
|
||||||
int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll) {
|
int RM_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll) {
|
||||||
addReplyLongLong(ctx->client,ll);
|
addReplyLongLong(ctx->client,ll);
|
||||||
return REDISMODULE_OK;
|
return REDISMODULE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reply with an error or simple string (status message). Used to implement
|
/* Reply with an error or simple string (status message). Used to implement
|
||||||
* ReplyWithSimpleString() and ReplyWithError(). */
|
* ReplyWithSimpleString() and ReplyWithError(). */
|
||||||
int RedisModule_ReplyWithStatus(RedisModuleCtx *ctx, const char *msg, char *prefix) {
|
int RM_ReplyWithStatus(RedisModuleCtx *ctx, const char *msg, char *prefix) {
|
||||||
sds strmsg = sdsnewlen(prefix,1);
|
sds strmsg = sdsnewlen(prefix,1);
|
||||||
strmsg = sdscat(strmsg,msg);
|
strmsg = sdscat(strmsg,msg);
|
||||||
strmsg = sdscatlen(strmsg,"\r\n",2);
|
strmsg = sdscatlen(strmsg,"\r\n",2);
|
||||||
@ -421,39 +427,39 @@ int RedisModule_ReplyWithStatus(RedisModuleCtx *ctx, const char *msg, char *pref
|
|||||||
* the initial error code. The function only provides the initial "-", so
|
* the initial error code. The function only provides the initial "-", so
|
||||||
* the usage is, for example:
|
* the usage is, for example:
|
||||||
*
|
*
|
||||||
* RedisModule_ReplyWithError(ctx,"ERR Wrong Type");
|
* RM_ReplyWithError(ctx,"ERR Wrong Type");
|
||||||
*
|
*
|
||||||
* and not just:
|
* and not just:
|
||||||
*
|
*
|
||||||
* RedisModule_ReplyWithError(ctx,"Wrong Type");
|
* RM_ReplyWithError(ctx,"Wrong Type");
|
||||||
*/
|
*/
|
||||||
int RedisModule_ReplyWithError(RedisModuleCtx *ctx, const char *err) {
|
int RM_ReplyWithError(RedisModuleCtx *ctx, const char *err) {
|
||||||
return RedisModule_ReplyWithStatus(ctx,err,"-");
|
return RM_ReplyWithStatus(ctx,err,"-");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reply with a simple string (+... \r\n in RESP protocol). This replies
|
/* Reply with a simple string (+... \r\n in RESP protocol). This replies
|
||||||
* are suitalbe only when sending a small non-binary string wiht small
|
* are suitalbe only when sending a small non-binary string wiht small
|
||||||
* overhead, like "OK" or similar replies. */
|
* overhead, like "OK" or similar replies. */
|
||||||
int RedisModule_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg) {
|
int RM_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg) {
|
||||||
return RedisModule_ReplyWithStatus(ctx,msg,"+");
|
return RM_ReplyWithStatus(ctx,msg,"+");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reply with an array type of 'len' elements. However 'len' other calls
|
/* Reply with an array type of 'len' elements. However 'len' other calls
|
||||||
* to ReplyWith* style functions must follow in order to emit the elements
|
* to ReplyWith* style functions must follow in order to emit the elements
|
||||||
* of the array. */
|
* of the array. */
|
||||||
int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, int len) {
|
int RM_ReplyWithArray(RedisModuleCtx *ctx, int len) {
|
||||||
addReplyMultiBulkLen(ctx->client,len);
|
addReplyMultiBulkLen(ctx->client,len);
|
||||||
return REDISMODULE_OK;
|
return REDISMODULE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reply with a bulk string, taking in input a C buffer pointer and length. */
|
/* Reply with a bulk string, taking in input a C buffer pointer and length. */
|
||||||
int RedisModule_ReplyWithStringBuffer(RedisModuleCtx *ctx, const char *buf, size_t len) {
|
int RM_ReplyWithStringBuffer(RedisModuleCtx *ctx, const char *buf, size_t len) {
|
||||||
addReplyBulkCBuffer(ctx->client,(char*)buf,len);
|
addReplyBulkCBuffer(ctx->client,(char*)buf,len);
|
||||||
return REDISMODULE_OK;
|
return REDISMODULE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reply with a bulk string, taking in input a RedisModuleString object. */
|
/* Reply with a bulk string, taking in input a RedisModuleString object. */
|
||||||
int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str) {
|
int RM_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str) {
|
||||||
addReplyBulk(ctx->client,str);
|
addReplyBulk(ctx->client,str);
|
||||||
return REDISMODULE_OK;
|
return REDISMODULE_OK;
|
||||||
}
|
}
|
||||||
@ -476,12 +482,12 @@ void moduleReplicateMultiIfNeeded(RedisModuleCtx *ctx) {
|
|||||||
*
|
*
|
||||||
* The replicated commands are always wrapepd into the MULTI/EXEC that
|
* The replicated commands are always wrapepd into the MULTI/EXEC that
|
||||||
* contains all the commands replicated in a given module command
|
* contains all the commands replicated in a given module command
|
||||||
* execution. However the commands replicated with RedisModule_Call()
|
* execution. However the commands replicated with RM_Call()
|
||||||
* are the first items, the ones replicated with RedisModule_Replicate()
|
* are the first items, the ones replicated with RM_Replicate()
|
||||||
* will all follow before the EXEC.
|
* will all follow before the EXEC.
|
||||||
*
|
*
|
||||||
* Modules should try to use one interface or the other. */
|
* Modules should try to use one interface or the other. */
|
||||||
int RedisModule_Replicate(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
|
int RM_Replicate(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
|
||||||
struct redisCommand *cmd;
|
struct redisCommand *cmd;
|
||||||
robj **argv = NULL;
|
robj **argv = NULL;
|
||||||
int argc = 0, flags = 0, j;
|
int argc = 0, flags = 0, j;
|
||||||
@ -511,7 +517,7 @@ int RedisModule_Replicate(RedisModuleCtx *ctx, const char *cmdname, const char *
|
|||||||
* by the client. This function will not wrap the command into
|
* by the client. This function will not wrap the command into
|
||||||
* a MULTI/EXEC stanza, so it should not be mixed with other replication
|
* a MULTI/EXEC stanza, so it should not be mixed with other replication
|
||||||
* commands. */
|
* commands. */
|
||||||
int RedisModule_ReplicateVerbatim(RedisModuleCtx *ctx) {
|
int RM_ReplicateVerbatim(RedisModuleCtx *ctx) {
|
||||||
alsoPropagate(ctx->client->cmd,ctx->client->db->id,
|
alsoPropagate(ctx->client->cmd,ctx->client->db->id,
|
||||||
ctx->client->argv,ctx->client->argc,
|
ctx->client->argv,ctx->client->argc,
|
||||||
PROPAGATE_AOF|PROPAGATE_REPL);
|
PROPAGATE_AOF|PROPAGATE_REPL);
|
||||||
@ -523,13 +529,13 @@ int RedisModule_ReplicateVerbatim(RedisModuleCtx *ctx) {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Return the currently selected DB. */
|
/* Return the currently selected DB. */
|
||||||
int RedisModule_GetSelectedDb(RedisModuleCtx *ctx) {
|
int RM_GetSelectedDb(RedisModuleCtx *ctx) {
|
||||||
return ctx->client->db->id;
|
return ctx->client->db->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change the currently selected DB. Returns an error if the id
|
/* Change the currently selected DB. Returns an error if the id
|
||||||
* is out of range. */
|
* is out of range. */
|
||||||
int RedisModule_SelectDb(RedisModuleCtx *ctx, int newid) {
|
int RM_SelectDb(RedisModuleCtx *ctx, int newid) {
|
||||||
int retval = selectDb(ctx->client,newid);
|
int retval = selectDb(ctx->client,newid);
|
||||||
return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
|
return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
|
||||||
}
|
}
|
||||||
@ -539,16 +545,16 @@ int RedisModule_SelectDb(RedisModuleCtx *ctx, int newid) {
|
|||||||
* operations on the key.
|
* operations on the key.
|
||||||
*
|
*
|
||||||
* The return value is the handle repesenting the key, that must be
|
* The return value is the handle repesenting the key, that must be
|
||||||
* closed with RedisModule_CloseKey().
|
* closed with RM_CloseKey().
|
||||||
*
|
*
|
||||||
* If the key does not exist and WRITE mode is requested, the handle
|
* If the key does not exist and WRITE mode is requested, the handle
|
||||||
* is still returned, since it is possible to perform operations on
|
* is still returned, since it is possible to perform operations on
|
||||||
* a yet not existing key (that will be created, for example, after
|
* a yet not existing key (that will be created, for example, after
|
||||||
* a list push operation). If the mode is just READ instead, and the
|
* a list push operation). If the mode is just READ instead, and the
|
||||||
* key does not exist, NULL is returned. However it is still safe to
|
* key does not exist, NULL is returned. However it is still safe to
|
||||||
* call RedisModule_CloseKey() and RedisModule_KeyType() on a NULL
|
* call RM_CloseKey() and RM_KeyType() on a NULL
|
||||||
* value. */
|
* value. */
|
||||||
void *RedisModule_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
|
void *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
|
||||||
RedisModuleKey *kp;
|
RedisModuleKey *kp;
|
||||||
robj *value;
|
robj *value;
|
||||||
|
|
||||||
@ -571,23 +577,23 @@ void *RedisModule_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
|
|||||||
kp->value = value;
|
kp->value = value;
|
||||||
kp->iter = NULL;
|
kp->iter = NULL;
|
||||||
kp->mode = mode;
|
kp->mode = mode;
|
||||||
RedisModule_AutoMemoryAdd(ctx,REDISMODULE_AM_KEY,kp);
|
RM_AutoMemoryAdd(ctx,REDISMODULE_AM_KEY,kp);
|
||||||
return (void*)kp;
|
return (void*)kp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close a key handle. */
|
/* Close a key handle. */
|
||||||
void RedisModule_CloseKey(RedisModuleKey *key) {
|
void RM_CloseKey(RedisModuleKey *key) {
|
||||||
if (key == NULL) return;
|
if (key == NULL) return;
|
||||||
if (key->mode & REDISMODULE_WRITE) signalModifiedKey(key->db,key->key);
|
if (key->mode & REDISMODULE_WRITE) signalModifiedKey(key->db,key->key);
|
||||||
/* TODO: if (key->iter) RedisModule_KeyIteratorStop(kp); */
|
/* TODO: if (key->iter) RM_KeyIteratorStop(kp); */
|
||||||
decrRefCount(key->key);
|
decrRefCount(key->key);
|
||||||
RedisModule_AutoMemoryFreed(key->ctx,REDISMODULE_AM_KEY,key);
|
RM_AutoMemoryFreed(key->ctx,REDISMODULE_AM_KEY,key);
|
||||||
zfree(key);
|
zfree(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the type of the key. If the key pointer is NULL then
|
/* Return the type of the key. If the key pointer is NULL then
|
||||||
* REDISMODULE_KEYTYPE_EMPTY is returned. */
|
* REDISMODULE_KEYTYPE_EMPTY is returned. */
|
||||||
int RedisModule_KeyType(RedisModuleKey *key) {
|
int RM_KeyType(RedisModuleKey *key) {
|
||||||
if (key == NULL || key->value == NULL) return REDISMODULE_KEYTYPE_EMPTY;
|
if (key == NULL || key->value == NULL) return REDISMODULE_KEYTYPE_EMPTY;
|
||||||
/* We map between defines so that we are free to change the internal
|
/* We map between defines so that we are free to change the internal
|
||||||
* defines as desired. */
|
* defines as desired. */
|
||||||
@ -606,7 +612,7 @@ int RedisModule_KeyType(RedisModuleKey *key) {
|
|||||||
* is the number of elements (just counting keys for hashes).
|
* is the number of elements (just counting keys for hashes).
|
||||||
*
|
*
|
||||||
* If the key pointer is NULL or the key is empty, zero is returned. */
|
* If the key pointer is NULL or the key is empty, zero is returned. */
|
||||||
size_t RedisModule_ValueLength(RedisModuleKey *key) {
|
size_t RM_ValueLength(RedisModuleKey *key) {
|
||||||
if (key == NULL || key->value == NULL) return 0;
|
if (key == NULL || key->value == NULL) return 0;
|
||||||
switch(key->value->type) {
|
switch(key->value->type) {
|
||||||
case OBJ_STRING: return stringObjectLen(key->value);
|
case OBJ_STRING: return stringObjectLen(key->value);
|
||||||
@ -622,7 +628,7 @@ size_t RedisModule_ValueLength(RedisModuleKey *key) {
|
|||||||
* accept new writes as an empty key (that will be created on demand).
|
* accept new writes as an empty key (that will be created on demand).
|
||||||
* On success REDISMODULE_OK is returned. If the key is not open for
|
* On success REDISMODULE_OK is returned. If the key is not open for
|
||||||
* writing REDISMODULE_ERR is returned. */
|
* writing REDISMODULE_ERR is returned. */
|
||||||
int RedisModule_DeleteKey(RedisModuleKey *key) {
|
int RM_DeleteKey(RedisModuleKey *key) {
|
||||||
if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
|
if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
|
||||||
if (key->value) {
|
if (key->value) {
|
||||||
dbDelete(key->db,key->key);
|
dbDelete(key->db,key->key);
|
||||||
@ -639,9 +645,9 @@ int RedisModule_DeleteKey(RedisModuleKey *key) {
|
|||||||
* value of the key, deleting the old value if any.
|
* value of the key, deleting the old value if any.
|
||||||
* On success REDISMODULE_OK is returned. If the key is not open for
|
* On success REDISMODULE_OK is returned. If the key is not open for
|
||||||
* writing or there is an active iterator, REDISMODULE_ERR is returned. */
|
* writing or there is an active iterator, REDISMODULE_ERR is returned. */
|
||||||
int RedisModule_StringSet(RedisModuleKey *key, RedisModuleString *str) {
|
int RM_StringSet(RedisModuleKey *key, RedisModuleString *str) {
|
||||||
if (!(key->mode & REDISMODULE_WRITE) || key->iter) return REDISMODULE_ERR;
|
if (!(key->mode & REDISMODULE_WRITE) || key->iter) return REDISMODULE_ERR;
|
||||||
RedisModule_DeleteKey(key);
|
RM_DeleteKey(key);
|
||||||
setKey(key->db,key->key,str);
|
setKey(key->db,key->key,str);
|
||||||
return REDISMODULE_OK;
|
return REDISMODULE_OK;
|
||||||
}
|
}
|
||||||
@ -666,16 +672,16 @@ int RedisModule_StringSet(RedisModuleKey *key, RedisModuleString *str) {
|
|||||||
* the pointer is obtained, for all the time we want to use DMA access
|
* the pointer is obtained, for all the time we want to use DMA access
|
||||||
* to read or modify the string.
|
* to read or modify the string.
|
||||||
*
|
*
|
||||||
* 2. Each time RedisModule_StringTruncate() is called, to continue with the DMA
|
* 2. Each time RM_StringTruncate() is called, to continue with the DMA
|
||||||
* access, RedisModule_StringDMA() should be called again to re-obtain
|
* access, RM_StringDMA() should be called again to re-obtain
|
||||||
* a new pointer and length.
|
* a new pointer and length.
|
||||||
*
|
*
|
||||||
* 3. If the returned pointer is not NULL, but the length is zero, no
|
* 3. If the returned pointer is not NULL, but the length is zero, no
|
||||||
* byte can be touched (the string is empty, or the key itself is empty)
|
* byte can be touched (the string is empty, or the key itself is empty)
|
||||||
* so a RedisModule_StringTruncate() call should be used if there is to enlarge
|
* so a RM_StringTruncate() call should be used if there is to enlarge
|
||||||
* the string, and later call StringDMA() again to get the pointer.
|
* the string, and later call StringDMA() again to get the pointer.
|
||||||
*/
|
*/
|
||||||
char *RedisModule_StringDMA(RedisModuleKey *key, size_t *len, int mode) {
|
char *RM_StringDMA(RedisModuleKey *key, size_t *len, int mode) {
|
||||||
/* We need to return *some* pointer for empty keys, we just return
|
/* We need to return *some* pointer for empty keys, we just return
|
||||||
* a string literal pointer, that is the advantage to be mapped into
|
* a string literal pointer, that is the advantage to be mapped into
|
||||||
* a read only memory page, so the module will segfault if a write
|
* a read only memory page, so the module will segfault if a write
|
||||||
@ -700,7 +706,7 @@ char *RedisModule_StringDMA(RedisModuleKey *key, size_t *len, int mode) {
|
|||||||
/* If the string is open for writing and is of string type, resize it, padding
|
/* If the string is open for writing and is of string type, resize it, padding
|
||||||
* with zero bytes if the new length is greater than the old one.
|
* with zero bytes if the new length is greater than the old one.
|
||||||
*
|
*
|
||||||
* After this call, RedisModule_StringDMA() must be called again to continue
|
* After this call, RM_StringDMA() must be called again to continue
|
||||||
* DMA access with the new pointer.
|
* DMA access with the new pointer.
|
||||||
*
|
*
|
||||||
* The function returns REDISMODULE_OK on success, and REDISMODULE_ERR on
|
* The function returns REDISMODULE_OK on success, and REDISMODULE_ERR on
|
||||||
@ -709,7 +715,7 @@ char *RedisModule_StringDMA(RedisModuleKey *key, size_t *len, int mode) {
|
|||||||
*
|
*
|
||||||
* If the key is empty, a string key is created with the new string value
|
* If the key is empty, a string key is created with the new string value
|
||||||
* unless the new length value requested is zero. */
|
* unless the new length value requested is zero. */
|
||||||
int RedisModule_StringTruncate(RedisModuleKey *key, size_t newlen) {
|
int RM_StringTruncate(RedisModuleKey *key, size_t newlen) {
|
||||||
if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
|
if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
|
||||||
if (key->value && key->value->type != OBJ_STRING) return REDISMODULE_ERR;
|
if (key->value && key->value->type != OBJ_STRING) return REDISMODULE_ERR;
|
||||||
if (newlen > 512*1024*1024) return REDISMODULE_ERR;
|
if (newlen > 512*1024*1024) return REDISMODULE_ERR;
|
||||||
@ -749,7 +755,7 @@ int RedisModule_StringTruncate(RedisModuleKey *key, size_t newlen) {
|
|||||||
* If the key pointer is about an empty key opened for writing, the key
|
* If the key pointer is about an empty key opened for writing, the key
|
||||||
* is created. On error (key opened for read-only operations or of the wrong
|
* is created. On error (key opened for read-only operations or of the wrong
|
||||||
* type) REDISMODULE_ERR is returned, otherwise REDISMODULE_OK is returned. */
|
* type) REDISMODULE_ERR is returned, otherwise REDISMODULE_OK is returned. */
|
||||||
int RedisModule_ListPush(RedisModuleKey *key, int where, RedisModuleString *ele) {
|
int RM_ListPush(RedisModuleKey *key, int where, RedisModuleString *ele) {
|
||||||
if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
|
if (!(key->mode & REDISMODULE_WRITE)) return REDISMODULE_ERR;
|
||||||
if (key->value == NULL) moduleCreateEmtpyKey(key,REDISMODULE_KEYTYPE_LIST);
|
if (key->value == NULL) moduleCreateEmtpyKey(key,REDISMODULE_KEYTYPE_LIST);
|
||||||
if (key->value->type != OBJ_LIST) return REDISMODULE_ERR;
|
if (key->value->type != OBJ_LIST) return REDISMODULE_ERR;
|
||||||
@ -760,13 +766,13 @@ int RedisModule_ListPush(RedisModuleKey *key, int where, RedisModuleString *ele)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Pop an element from the list, and returns it as a module string object
|
/* Pop an element from the list, and returns it as a module string object
|
||||||
* that the user should be free with RedisModule_FreeString() or by enabling
|
* that the user should be free with RM_FreeString() or by enabling
|
||||||
* automatic memory. 'where' specifies if the element should be popped from
|
* automatic memory. 'where' specifies if the element should be popped from
|
||||||
* head or tail. The command returns NULL if:
|
* head or tail. The command returns NULL if:
|
||||||
* 1) The list is empty.
|
* 1) The list is empty.
|
||||||
* 2) The key was not open for writing.
|
* 2) The key was not open for writing.
|
||||||
* 3) The key is not a list. */
|
* 3) The key is not a list. */
|
||||||
RedisModuleString *RedisModule_ListPop(RedisModuleKey *key, int where) {
|
RedisModuleString *RM_ListPop(RedisModuleKey *key, int where) {
|
||||||
if (!(key->mode & REDISMODULE_WRITE) ||
|
if (!(key->mode & REDISMODULE_WRITE) ||
|
||||||
key->value == NULL ||
|
key->value == NULL ||
|
||||||
key->value->type != OBJ_LIST) return NULL;
|
key->value->type != OBJ_LIST) return NULL;
|
||||||
@ -775,7 +781,7 @@ RedisModuleString *RedisModule_ListPop(RedisModuleKey *key, int where) {
|
|||||||
robj *decoded = getDecodedObject(ele);
|
robj *decoded = getDecodedObject(ele);
|
||||||
decrRefCount(ele);
|
decrRefCount(ele);
|
||||||
moduleDelKeyIfEmpty(key);
|
moduleDelKeyIfEmpty(key);
|
||||||
RedisModule_AutoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,decoded);
|
RM_AutoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,decoded);
|
||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -894,7 +900,7 @@ void moduleParseCallReply_Array(RedisModuleCallReply *reply) {
|
|||||||
|
|
||||||
/* Free a Call reply and all the nested replies it contains if it's an
|
/* Free a Call reply and all the nested replies it contains if it's an
|
||||||
* array. */
|
* array. */
|
||||||
void RedisModule_FreeCallReply_Rec(RedisModuleCallReply *reply, int freenested){
|
void RM_FreeCallReply_Rec(RedisModuleCallReply *reply, int freenested){
|
||||||
/* Don't free nested replies by default: the user must always free the
|
/* Don't free nested replies by default: the user must always free the
|
||||||
* toplevel reply. However be gentle and don't crash if the module
|
* toplevel reply. However be gentle and don't crash if the module
|
||||||
* misuses the API. */
|
* misuses the API. */
|
||||||
@ -904,7 +910,7 @@ void RedisModule_FreeCallReply_Rec(RedisModuleCallReply *reply, int freenested){
|
|||||||
if (reply->type == REDISMODULE_REPLY_ARRAY) {
|
if (reply->type == REDISMODULE_REPLY_ARRAY) {
|
||||||
size_t j;
|
size_t j;
|
||||||
for (j = 0; j < reply->len; j++)
|
for (j = 0; j < reply->len; j++)
|
||||||
RedisModule_FreeCallReply_Rec(reply->val.array+j,1);
|
RM_FreeCallReply_Rec(reply->val.array+j,1);
|
||||||
zfree(reply->val.array);
|
zfree(reply->val.array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -922,18 +928,18 @@ void RedisModule_FreeCallReply_Rec(RedisModuleCallReply *reply, int freenested){
|
|||||||
/* Wrapper for the recursive free reply function. This is needed in order
|
/* Wrapper for the recursive free reply function. This is needed in order
|
||||||
* to have the first level function to return on nested replies, but only
|
* to have the first level function to return on nested replies, but only
|
||||||
* if called by the module API. */
|
* if called by the module API. */
|
||||||
void RedisModule_FreeCallReply(RedisModuleCallReply *reply) {
|
void RM_FreeCallReply(RedisModuleCallReply *reply) {
|
||||||
RedisModule_FreeCallReply_Rec(reply,0);
|
RM_FreeCallReply_Rec(reply,0);
|
||||||
RedisModule_AutoMemoryFreed(reply->ctx,REDISMODULE_AM_REPLY,reply);
|
RM_AutoMemoryFreed(reply->ctx,REDISMODULE_AM_REPLY,reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the reply type. */
|
/* Return the reply type. */
|
||||||
int RedisModule_CallReplyType(RedisModuleCallReply *reply) {
|
int RM_CallReplyType(RedisModuleCallReply *reply) {
|
||||||
return reply->type;
|
return reply->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the reply type length, where applicable. */
|
/* Return the reply type length, where applicable. */
|
||||||
size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply) {
|
size_t RM_CallReplyLength(RedisModuleCallReply *reply) {
|
||||||
moduleParseCallReply(reply);
|
moduleParseCallReply(reply);
|
||||||
switch(reply->type) {
|
switch(reply->type) {
|
||||||
case REDISMODULE_REPLY_STRING:
|
case REDISMODULE_REPLY_STRING:
|
||||||
@ -947,7 +953,7 @@ size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply) {
|
|||||||
|
|
||||||
/* Return the 'idx'-th nested call reply element of an array reply, or NULL
|
/* Return the 'idx'-th nested call reply element of an array reply, or NULL
|
||||||
* if the reply type is wrong or the index is out of range. */
|
* if the reply type is wrong or the index is out of range. */
|
||||||
RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *reply, size_t idx) {
|
RedisModuleCallReply *RM_CallReplyArrayElement(RedisModuleCallReply *reply, size_t idx) {
|
||||||
moduleParseCallReply(reply);
|
moduleParseCallReply(reply);
|
||||||
if (reply->type != REDISMODULE_REPLY_ARRAY) return NULL;
|
if (reply->type != REDISMODULE_REPLY_ARRAY) return NULL;
|
||||||
if (idx >= reply->len) return NULL;
|
if (idx >= reply->len) return NULL;
|
||||||
@ -955,14 +961,14 @@ RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *re
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the long long of an integer reply. */
|
/* Return the long long of an integer reply. */
|
||||||
long long RedisModule_CallReplyInteger(RedisModuleCallReply *reply) {
|
long long RM_CallReplyInteger(RedisModuleCallReply *reply) {
|
||||||
moduleParseCallReply(reply);
|
moduleParseCallReply(reply);
|
||||||
if (reply->type != REDISMODULE_REPLY_INTEGER) return LLONG_MIN;
|
if (reply->type != REDISMODULE_REPLY_INTEGER) return LLONG_MIN;
|
||||||
return reply->val.ll;
|
return reply->val.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the pointer and length of a string or error reply. */
|
/* Return the pointer and length of a string or error reply. */
|
||||||
const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *len) {
|
const char *RM_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *len) {
|
||||||
moduleParseCallReply(reply);
|
moduleParseCallReply(reply);
|
||||||
if (reply->type != REDISMODULE_REPLY_STRING &&
|
if (reply->type != REDISMODULE_REPLY_STRING &&
|
||||||
reply->type != REDISMODULE_REPLY_ERROR) return NULL;
|
reply->type != REDISMODULE_REPLY_ERROR) return NULL;
|
||||||
@ -972,16 +978,16 @@ const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply, size_t *
|
|||||||
|
|
||||||
/* Return a new string object from a call reply of type string, error or
|
/* Return a new string object from a call reply of type string, error or
|
||||||
* integer. Otherwise (wrong reply type) return NULL. */
|
* integer. Otherwise (wrong reply type) return NULL. */
|
||||||
RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *reply) {
|
RedisModuleString *RM_CreateStringFromCallReply(RedisModuleCallReply *reply) {
|
||||||
moduleParseCallReply(reply);
|
moduleParseCallReply(reply);
|
||||||
switch(reply->type) {
|
switch(reply->type) {
|
||||||
case REDISMODULE_REPLY_STRING:
|
case REDISMODULE_REPLY_STRING:
|
||||||
case REDISMODULE_REPLY_ERROR:
|
case REDISMODULE_REPLY_ERROR:
|
||||||
return RedisModule_CreateString(reply->ctx,reply->val.str,reply->len);
|
return RM_CreateString(reply->ctx,reply->val.str,reply->len);
|
||||||
case REDISMODULE_REPLY_INTEGER: {
|
case REDISMODULE_REPLY_INTEGER: {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
int len = ll2string(buf,sizeof(buf),reply->val.ll);
|
int len = ll2string(buf,sizeof(buf),reply->val.ll);
|
||||||
return RedisModule_CreateString(reply->ctx,buf,len);
|
return RM_CreateString(reply->ctx,buf,len);
|
||||||
}
|
}
|
||||||
default: return NULL;
|
default: return NULL;
|
||||||
}
|
}
|
||||||
@ -989,7 +995,7 @@ RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *r
|
|||||||
|
|
||||||
/* Returns an array of robj pointers, and populates *argc with the number
|
/* Returns an array of robj pointers, and populates *argc with the number
|
||||||
* of items, by parsing the format specifier "fmt" as described for
|
* of items, by parsing the format specifier "fmt" as described for
|
||||||
* the RedisModule_Call(), RedisModule_Replicate() and other module APIs.
|
* the RM_Call(), RM_Replicate() and other module APIs.
|
||||||
*
|
*
|
||||||
* The integer pointed by 'flags' is populated with flags according
|
* The integer pointed by 'flags' is populated with flags according
|
||||||
* to special modifiers in "fmt". For now only one exists:
|
* to special modifiers in "fmt". For now only one exists:
|
||||||
@ -1056,7 +1062,7 @@ fmterr:
|
|||||||
*
|
*
|
||||||
* EINVAL: command non existing, wrong arity, wrong format specifier.
|
* EINVAL: command non existing, wrong arity, wrong format specifier.
|
||||||
* EPERM: operation in Cluster instance with key in non local slot. */
|
* EPERM: operation in Cluster instance with key in non local slot. */
|
||||||
RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
|
RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
|
||||||
struct redisCommand *cmd;
|
struct redisCommand *cmd;
|
||||||
client *c = NULL;
|
client *c = NULL;
|
||||||
robj **argv = NULL;
|
robj **argv = NULL;
|
||||||
@ -1133,7 +1139,7 @@ RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx, const char *cmdname,
|
|||||||
listDelNode(c->reply,listFirst(c->reply));
|
listDelNode(c->reply,listFirst(c->reply));
|
||||||
}
|
}
|
||||||
reply = moduleCreateCallReplyFromProto(ctx,proto);
|
reply = moduleCreateCallReplyFromProto(ctx,proto);
|
||||||
RedisModule_AutoMemoryAdd(ctx,REDISMODULE_AM_REPLY,reply);
|
RM_AutoMemoryAdd(ctx,REDISMODULE_AM_REPLY,reply);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
freeClient(c);
|
freeClient(c);
|
||||||
@ -1142,7 +1148,7 @@ cleanup:
|
|||||||
|
|
||||||
/* Return a pointer, and a length, to the protocol returned by the command
|
/* Return a pointer, and a length, to the protocol returned by the command
|
||||||
* that returned the reply object. */
|
* that returned the reply object. */
|
||||||
const char *RedisModule_CallReplyProto(RedisModuleCallReply *reply, size_t *len) {
|
const char *RM_CallReplyProto(RedisModuleCallReply *reply, size_t *len) {
|
||||||
if (reply->proto) *len = sdslen(reply->proto);
|
if (reply->proto) *len = sdslen(reply->proto);
|
||||||
return reply->proto;
|
return reply->proto;
|
||||||
}
|
}
|
||||||
@ -1177,7 +1183,7 @@ int moduleRegisterApi(const char *funcname, void *funcptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define REGISTER_API(name) \
|
#define REGISTER_API(name) \
|
||||||
moduleRegisterApi("RedisModule_" #name, (void *)(unsigned long)RedisModule_ ## name)
|
moduleRegisterApi("RedisModule_" #name, (void *)(unsigned long)RM_ ## name)
|
||||||
|
|
||||||
/* Register all the APIs we export. */
|
/* Register all the APIs we export. */
|
||||||
void moduleRegisterCoreAPI(void) {
|
void moduleRegisterCoreAPI(void) {
|
||||||
@ -1266,7 +1272,7 @@ int moduleLoad(const char *path) {
|
|||||||
void *handle;
|
void *handle;
|
||||||
RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
|
RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
|
||||||
|
|
||||||
handle = dlopen(path,RTLD_LAZY);
|
handle = dlopen(path,RTLD_NOW|RTLD_LOCAL);
|
||||||
if (handle == NULL) return C_ERR;
|
if (handle == NULL) return C_ERR;
|
||||||
onload = (int (*)(void *))(unsigned long) dlsym(handle,"RedisModule_OnLoad");
|
onload = (int (*)(void *))(unsigned long) dlsym(handle,"RedisModule_OnLoad");
|
||||||
if (onload == NULL) {
|
if (onload == NULL) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define REDISMODULE_H
|
#define REDISMODULE_H
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/* ---------------- Defines common between core and modules --------------- */
|
/* ---------------- Defines common between core and modules --------------- */
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ int REDISMODULE_API_FUNC(RedisModule_StringTruncate)(RedisModuleKey *key, size_t
|
|||||||
/* This is included inline inside each Redis module. */
|
/* This is included inline inside each Redis module. */
|
||||||
static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) {
|
static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) {
|
||||||
void *getapifuncptr = ((void**)ctx)[0];
|
void *getapifuncptr = ((void**)ctx)[0];
|
||||||
RedisModule_GetApi = (int (*)(const char *, void *)) getapifuncptr;
|
RedisModule_GetApi = (int (*)(const char *, void *)) (unsigned long)getapifuncptr;
|
||||||
REDISMODULE_GET_API(CreateCommand);
|
REDISMODULE_GET_API(CreateCommand);
|
||||||
REDISMODULE_GET_API(SetModuleAttribs);
|
REDISMODULE_GET_API(SetModuleAttribs);
|
||||||
REDISMODULE_GET_API(WrongArity);
|
REDISMODULE_GET_API(WrongArity);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user