mirror of
https://github.com/fluencelabs/redis
synced 2025-03-18 16:40:50 +00:00
Modules: fix top comments to be user-facing doc quality. About 33% done.
This commit is contained in:
parent
f362f7a18a
commit
0fd6d548ca
188
src/module.c
188
src/module.c
@ -116,7 +116,7 @@ typedef struct RedisModuleCallReply RedisModuleCallReply;
|
||||
|
||||
void RM_FreeCallReply(RedisModuleCallReply *reply);
|
||||
void RM_CloseKey(RedisModuleKey *key);
|
||||
void RM_AutoMemoryCollect(RedisModuleCtx *ctx);
|
||||
void autoMemoryCollect(RedisModuleCtx *ctx);
|
||||
robj **moduleCreateArgvFromUserFormat(const char *cmdname, const char *fmt, int *argcp, int *flags, va_list ap);
|
||||
void moduleReplicateMultiIfNeeded(RedisModuleCtx *ctx);
|
||||
void RM_ZsetRangeStop(RedisModuleKey *key);
|
||||
@ -204,7 +204,10 @@ int moduleDelKeyIfEmpty(RedisModuleKey *key) {
|
||||
|
||||
/* Lookup the requested module API and store the function pointer into the
|
||||
* target pointer. The function returns REDISMODULE_ERR if there is no such
|
||||
* named API, otherwise REDISMODULE_OK. */
|
||||
* named API, otherwise REDISMODULE_OK.
|
||||
*
|
||||
* This function is not meant to be used by modules developer, it is only
|
||||
* used implicitly by including redismodule.h. */
|
||||
int RM_GetApi(const char *funcname, void **targetPtrPtr) {
|
||||
dictEntry *he = dictFind(server.moduleapi, funcname);
|
||||
if (!he) return REDISMODULE_ERR;
|
||||
@ -221,7 +224,7 @@ void RedisModuleCommandDispatcher(client *c) {
|
||||
ctx.module = cp->module;
|
||||
ctx.client = c;
|
||||
cp->func(&ctx,(void**)c->argv,c->argc);
|
||||
RM_AutoMemoryCollect(&ctx);
|
||||
autoMemoryCollect(&ctx);
|
||||
preventCommandPropagation(c);
|
||||
|
||||
/* Handle the replication of the final EXEC, since whatever a command
|
||||
@ -238,7 +241,18 @@ void RedisModuleCommandDispatcher(client *c) {
|
||||
/* Register a new command in the Redis server, that will be handled by
|
||||
* calling the function pointer 'func' using the RedisModule calling
|
||||
* convention. The function returns REDISMODULE_ERR if the specified command
|
||||
* name is already busy, otherwise REDISMODULE_OK. */
|
||||
* name is already busy, otherwise REDISMODULE_OK is returned.
|
||||
*
|
||||
* This function must be called during the initialization of the module
|
||||
* inside the RedisModule_OnLoad() function. Calling this function outside
|
||||
* of the initialization function is not defined.
|
||||
*
|
||||
* The command function type is the following:
|
||||
*
|
||||
* int MyCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
*
|
||||
* And is supposed to always return REDISMODULE_OK.
|
||||
*/
|
||||
int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc) {
|
||||
struct redisCommand *rediscmd;
|
||||
RedisModuleCommandProxy *cp;
|
||||
@ -252,7 +266,7 @@ int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc c
|
||||
|
||||
/* Create a command "proxy", which is a structure that is referenced
|
||||
* in the command table, so that the generic command that works as
|
||||
* binidng between modules and Redis, can know what function to call
|
||||
* binding between modules and Redis, can know what function to call
|
||||
* and what the module is.
|
||||
*
|
||||
* Note that we use the Redis command table 'getkeys_proc' in order to
|
||||
@ -276,7 +290,10 @@ int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc c
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
/* Called by RM_Init() to setup the ctx->module structure. */
|
||||
/* Called by RM_Init() to setup the ctx->module structure.
|
||||
*
|
||||
* This is an internal function, Redis modules developers don't need
|
||||
* to use it. */
|
||||
void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int apiver){
|
||||
RedisModule *module;
|
||||
|
||||
@ -292,13 +309,16 @@ void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int api
|
||||
* Automatic memory management for modules
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Enable auto memory. */
|
||||
/* Enable automatic memory management. See API.md for more information.
|
||||
*
|
||||
* The function must be called as the first function of a command implementation
|
||||
* that wants to use automatic memory. */
|
||||
void RM_AutoMemory(RedisModuleCtx *ctx) {
|
||||
ctx->flags |= REDISMODULE_CTX_AUTO_MEMORY;
|
||||
}
|
||||
|
||||
/* Add a new object to release automatically when the callback returns. */
|
||||
void RM_AutoMemoryAdd(RedisModuleCtx *ctx, int type, void *ptr) {
|
||||
void autoMemoryAdd(RedisModuleCtx *ctx, int type, void *ptr) {
|
||||
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
||||
if (ctx->amqueue_used == ctx->amqueue_len) {
|
||||
ctx->amqueue_len *= 2;
|
||||
@ -312,7 +332,7 @@ void RM_AutoMemoryAdd(RedisModuleCtx *ctx, int type, void *ptr) {
|
||||
|
||||
/* Mark an object as freed in the auto release queue, so that users can still
|
||||
* free things manually if they want. */
|
||||
void RM_AutoMemoryFreed(RedisModuleCtx *ctx, int type, void *ptr) {
|
||||
void autoMemoryFreed(RedisModuleCtx *ctx, int type, void *ptr) {
|
||||
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
||||
|
||||
int j;
|
||||
@ -329,7 +349,7 @@ void RM_AutoMemoryFreed(RedisModuleCtx *ctx, int type, void *ptr) {
|
||||
}
|
||||
|
||||
/* Release all the objects in queue. */
|
||||
void RM_AutoMemoryCollect(RedisModuleCtx *ctx) {
|
||||
void autoMemoryCollect(RedisModuleCtx *ctx) {
|
||||
if (!(ctx->flags & REDISMODULE_CTX_AUTO_MEMORY)) return;
|
||||
/* Clear the AUTO_MEMORY flag from the context, otherwise the functions
|
||||
* we call to free the resources, will try to scan the auto release
|
||||
@ -355,37 +375,49 @@ void RM_AutoMemoryCollect(RedisModuleCtx *ctx) {
|
||||
* String objects APIs
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Create a new module string object. Must be freed with
|
||||
* RM_FreeString(), unless automatic memory is enabled. */
|
||||
/* Create a new module string object. The returned string must be freed
|
||||
* with RedisModule_FreeString(), unless automatic memory is enabled.
|
||||
*
|
||||
* The string is created by copying the `len` bytes starting
|
||||
* at `ptr`. No reference is retained to the passed buffer. */
|
||||
RedisModuleString *RM_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len)
|
||||
{
|
||||
RedisModuleString *o = createStringObject(ptr,len);
|
||||
RM_AutoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
|
||||
autoMemoryAdd(ctx,REDISMODULE_AM_STRING,o);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* Like RM_CreatString, but creates a string starting from a long long
|
||||
* integer instea of taking a buffer and length. */
|
||||
/* Like RedisModule_CreatString(), but creates a string starting from a long long
|
||||
* integer instead of taking a buffer and its length.
|
||||
*
|
||||
* The returned string must be released with RedisModule_FreeString() or by
|
||||
* enabling automatic memory management. */
|
||||
RedisModuleString *RM_CreateStringFromLongLong(RedisModuleCtx *ctx, long long ll) {
|
||||
char buf[LONG_STR_SIZE];
|
||||
size_t len = ll2string(buf,sizeof(buf),ll);
|
||||
return RM_CreateString(ctx,buf,len);
|
||||
}
|
||||
|
||||
/* Free a module string object obtained with one of the Redis API calls
|
||||
* that return new string objects. */
|
||||
/* Free a module string object obtained with one of the Redis modules API calls
|
||||
* that return new string objects.
|
||||
*
|
||||
* It is possible to call this function even when automatic memory management
|
||||
* is enabled. In that case the string will be released ASAP and removed
|
||||
* from the pool of string to release at the end. */
|
||||
void RM_FreeString(RedisModuleCtx *ctx, RedisModuleString *str) {
|
||||
decrRefCount(str);
|
||||
RM_AutoMemoryFreed(ctx,REDISMODULE_AM_STRING,str);
|
||||
autoMemoryFreed(ctx,REDISMODULE_AM_STRING,str);
|
||||
}
|
||||
|
||||
/* Return the string pointer and length. */
|
||||
/* Given a string module object, this function returns the string pointer
|
||||
* and length of the string. The returned pointer and length should only
|
||||
* be used for read only accesses and never modified. */
|
||||
const char *RM_StringPtrLen(RedisModuleString *str, size_t *len) {
|
||||
if (len) *len = sdslen(str->ptr);
|
||||
return str->ptr;
|
||||
}
|
||||
|
||||
/* Turn the string into a long long, storing it at *ll.
|
||||
/* Convert the string into a long long integer, storing it at *ll.
|
||||
* Returns REDISMODULE_OK on success. If the string can't be parsed
|
||||
* as a valid, strict long long (no spaces before/after), REDISMODULE_ERR
|
||||
* is returned. */
|
||||
@ -394,7 +426,7 @@ int RM_StringToLongLong(RedisModuleString *str, long long *ll) {
|
||||
REDISMODULE_ERR;
|
||||
}
|
||||
|
||||
/* Turn the string into a double, storing it at *d.
|
||||
/* Convert the string into a double, storing it at *d.
|
||||
* Returns REDISMODULE_OK on success or REDISMODULE_ERR if the string is
|
||||
* not a valid string representation of a double value. */
|
||||
int RM_StringToDouble(RedisModuleString *str, double *d) {
|
||||
@ -412,7 +444,13 @@ int RM_StringToDouble(RedisModuleString *str, double *d) {
|
||||
* 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,
|
||||
* citing the command name in the error message.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* if (argc != 3) return RedisModule_WrongArity(ctx);
|
||||
*/
|
||||
int RM_WrongArity(RedisModuleCtx *ctx) {
|
||||
addReplyErrorFormat(ctx->client,
|
||||
"wrong number of arguments for '%s' command",
|
||||
@ -420,7 +458,7 @@ int RM_WrongArity(RedisModuleCtx *ctx) {
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
/* Send an integer reply with the specified long long value.
|
||||
/* Send an integer reply to the client, with the specified long long value.
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll) {
|
||||
addReplyLongLong(ctx->client,ll);
|
||||
@ -428,8 +466,9 @@ int RM_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll) {
|
||||
}
|
||||
|
||||
/* Reply with an error or simple string (status message). Used to implement
|
||||
* ReplyWithSimpleString() and ReplyWithError(). */
|
||||
int RM_ReplyWithStatus(RedisModuleCtx *ctx, const char *msg, char *prefix) {
|
||||
* ReplyWithSimpleString() and ReplyWithError().
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int replyWithStatus(RedisModuleCtx *ctx, const char *msg, char *prefix) {
|
||||
sds strmsg = sdsnewlen(prefix,1);
|
||||
strmsg = sdscat(strmsg,msg);
|
||||
strmsg = sdscatlen(strmsg,"\r\n",2);
|
||||
@ -443,57 +482,80 @@ int RM_ReplyWithStatus(RedisModuleCtx *ctx, const char *msg, char *prefix) {
|
||||
* the initial error code. The function only provides the initial "-", so
|
||||
* the usage is, for example:
|
||||
*
|
||||
* RM_ReplyWithError(ctx,"ERR Wrong Type");
|
||||
* RM_ReplyWithError(ctx,"ERR Wrong Type");
|
||||
*
|
||||
* and not just:
|
||||
*
|
||||
* RM_ReplyWithError(ctx,"Wrong Type");
|
||||
* RM_ReplyWithError(ctx,"Wrong Type");
|
||||
*
|
||||
* The function always returns REDISMODULE_OK.
|
||||
*/
|
||||
int RM_ReplyWithError(RedisModuleCtx *ctx, const char *err) {
|
||||
return RM_ReplyWithStatus(ctx,err,"-");
|
||||
return replyWithStatus(ctx,err,"-");
|
||||
}
|
||||
|
||||
/* Reply with a simple string (+... \r\n in RESP protocol). This replies
|
||||
* are suitalbe only when sending a small non-binary string wiht small
|
||||
* overhead, like "OK" or similar replies. */
|
||||
* are suitable only when sending a small non-binary string with small
|
||||
* overhead, like "OK" or similar replies.
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg) {
|
||||
return RM_ReplyWithStatus(ctx,msg,"+");
|
||||
return replyWithStatus(ctx,msg,"+");
|
||||
}
|
||||
|
||||
/* Reply with an array type of 'len' elements. However 'len' other calls
|
||||
* to ReplyWith* style functions must follow in order to emit the elements
|
||||
* of the array. */
|
||||
* of the array.
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithArray(RedisModuleCtx *ctx, int len) {
|
||||
addReplyMultiBulkLen(ctx->client,len);
|
||||
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.
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithStringBuffer(RedisModuleCtx *ctx, const char *buf, size_t len) {
|
||||
addReplyBulkCBuffer(ctx->client,(char*)buf,len);
|
||||
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.
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str) {
|
||||
addReplyBulk(ctx->client,str);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
/* Reply with NULL. */
|
||||
/* Reply to the client with a NULL. In the RESP protocol a NULL is encoded
|
||||
* as the string "$-1\r\n".
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithNull(RedisModuleCtx *ctx) {
|
||||
addReply(ctx->client,shared.nullbulk);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
/* Reply exactly what a Redis command returned us with RM_Call(). */
|
||||
/* Reply exactly what a Redis command returned us with RedisModule_Call().
|
||||
* This function is useful when we use RedisModule_Call() in order to
|
||||
* execute some command, as we want to reply to the client exactly the
|
||||
* same reply we obtained by the command.
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithCallReply(RedisModuleCtx *ctx, RedisModuleCallReply *reply) {
|
||||
sds proto = sdsnewlen(reply->proto, reply->protolen);
|
||||
addReplySds(ctx->client,proto);
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
/* Send a string reply obtained converting the double 'd' into a string. */
|
||||
/* Send a string reply obtained converting the double 'd' into a bulk string.
|
||||
* This function is basically equivalent to converting a double into
|
||||
* a string into a C buffer, and then calling the function
|
||||
* RedisModule_ReplyWithStringBuffer() with the buffer and length.
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplyWithDouble(RedisModuleCtx *ctx, double d) {
|
||||
addReplyDouble(ctx->client,d);
|
||||
return REDISMODULE_OK;
|
||||
@ -515,13 +577,22 @@ void moduleReplicateMultiIfNeeded(RedisModuleCtx *ctx) {
|
||||
/* Replicate the specified command and arguments to slaves and AOF, as effect
|
||||
* of execution of the calling command implementation.
|
||||
*
|
||||
* The replicated commands are always wrapepd into the MULTI/EXEC that
|
||||
* The replicated commands are always wrapped into the MULTI/EXEC that
|
||||
* contains all the commands replicated in a given module command
|
||||
* execution. However the commands replicated with RM_Call()
|
||||
* are the first items, the ones replicated with RM_Replicate()
|
||||
* execution. However the commands replicated with RedisModule_Call()
|
||||
* are the first items, the ones replicated with RedisModule_Replicate()
|
||||
* 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.
|
||||
*
|
||||
* This command follows exactly the same interface of RedisModule_Call(),
|
||||
* so a set of format specifiers must be passed, followed by arguments
|
||||
* matching the provided format specifiers.
|
||||
*
|
||||
* Please refer to RedisModule_Call() for more information.
|
||||
*
|
||||
* The command returns REDISMODULE_ERR if the format specifiers are invalid
|
||||
* or the command name does not belong to a known command. */
|
||||
int RM_Replicate(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
|
||||
struct redisCommand *cmd;
|
||||
robj **argv = NULL;
|
||||
@ -549,9 +620,16 @@ int RM_Replicate(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...)
|
||||
}
|
||||
|
||||
/* This function will replicate the command exactly as it was invoked
|
||||
* by the client. This function will not wrap the command into
|
||||
* by the client. Note that this function will not wrap the command into
|
||||
* a MULTI/EXEC stanza, so it should not be mixed with other replication
|
||||
* commands. */
|
||||
* commands.
|
||||
*
|
||||
* Basically this form of replication is useful when you want to propagate
|
||||
* the command to the slaves and AOF file exactly as it was called, since
|
||||
* the command can just be re-executed to deterministically re-create the
|
||||
* new state starting from the old one.
|
||||
*
|
||||
* The function always returns REDISMODULE_OK. */
|
||||
int RM_ReplicateVerbatim(RedisModuleCtx *ctx) {
|
||||
alsoPropagate(ctx->client->cmd,ctx->client->db->id,
|
||||
ctx->client->argv,ctx->client->argc,
|
||||
@ -569,7 +647,15 @@ int RM_GetSelectedDb(RedisModuleCtx *ctx) {
|
||||
}
|
||||
|
||||
/* Change the currently selected DB. Returns an error if the id
|
||||
* is out of range. */
|
||||
* is out of range.
|
||||
*
|
||||
* Note that the client will retain the currently selected DB even after
|
||||
* the Redis command implemented by the module calling this function
|
||||
* returns.
|
||||
*
|
||||
* If the module command wishes to change something in a different DB and
|
||||
* returns back to the original one, it should call RedisModule_GetSelectedDb()
|
||||
* before in order to restore the old DB number before returning. */
|
||||
int RM_SelectDb(RedisModuleCtx *ctx, int newid) {
|
||||
int retval = selectDb(ctx->client,newid);
|
||||
return (retval == C_OK) ? REDISMODULE_OK : REDISMODULE_ERR;
|
||||
@ -587,7 +673,7 @@ int RM_SelectDb(RedisModuleCtx *ctx, int newid) {
|
||||
* 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
|
||||
* key does not exist, NULL is returned. However it is still safe to
|
||||
* call RM_CloseKey() and RM_KeyType() on a NULL
|
||||
* call RedisModule_CloseKey() and RedisModule_KeyType() on a NULL
|
||||
* value. */
|
||||
void *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
|
||||
RedisModuleKey *kp;
|
||||
@ -612,7 +698,7 @@ void *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
|
||||
kp->iter = NULL;
|
||||
kp->mode = mode;
|
||||
RM_ZsetRangeStop(kp);
|
||||
RM_AutoMemoryAdd(ctx,REDISMODULE_AM_KEY,kp);
|
||||
autoMemoryAdd(ctx,REDISMODULE_AM_KEY,kp);
|
||||
return (void*)kp;
|
||||
}
|
||||
|
||||
@ -622,7 +708,7 @@ void RM_CloseKey(RedisModuleKey *key) {
|
||||
if (key->mode & REDISMODULE_WRITE) signalModifiedKey(key->db,key->key);
|
||||
/* TODO: if (key->iter) RM_KeyIteratorStop(kp); */
|
||||
decrRefCount(key->key);
|
||||
RM_AutoMemoryFreed(key->ctx,REDISMODULE_AM_KEY,key);
|
||||
autoMemoryFreed(key->ctx,REDISMODULE_AM_KEY,key);
|
||||
zfree(key);
|
||||
}
|
||||
|
||||
@ -847,7 +933,7 @@ RedisModuleString *RM_ListPop(RedisModuleKey *key, int where) {
|
||||
robj *decoded = getDecodedObject(ele);
|
||||
decrRefCount(ele);
|
||||
moduleDelKeyIfEmpty(key);
|
||||
RM_AutoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,decoded);
|
||||
autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,decoded);
|
||||
return decoded;
|
||||
}
|
||||
|
||||
@ -1088,7 +1174,7 @@ RedisModuleString *RM_ZsetRangeCurrentElement(RedisModuleKey *key, double *score
|
||||
} else {
|
||||
serverPanic("Unsupported zset encoding");
|
||||
}
|
||||
RM_AutoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,str);
|
||||
autoMemoryAdd(key->ctx,REDISMODULE_AM_STRING,str);
|
||||
return str;
|
||||
}
|
||||
|
||||
@ -1363,7 +1449,7 @@ void RM_FreeCallReply_Rec(RedisModuleCallReply *reply, int freenested){
|
||||
* if called by the module API. */
|
||||
void RM_FreeCallReply(RedisModuleCallReply *reply) {
|
||||
RM_FreeCallReply_Rec(reply,0);
|
||||
RM_AutoMemoryFreed(reply->ctx,REDISMODULE_AM_REPLY,reply);
|
||||
autoMemoryFreed(reply->ctx,REDISMODULE_AM_REPLY,reply);
|
||||
}
|
||||
|
||||
/* Return the reply type. */
|
||||
@ -1572,7 +1658,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
|
||||
listDelNode(c->reply,listFirst(c->reply));
|
||||
}
|
||||
reply = moduleCreateCallReplyFromProto(ctx,proto);
|
||||
RM_AutoMemoryAdd(ctx,REDISMODULE_AM_REPLY,reply);
|
||||
autoMemoryAdd(ctx,REDISMODULE_AM_REPLY,reply);
|
||||
|
||||
cleanup:
|
||||
freeClient(c);
|
||||
|
Loading…
x
Reference in New Issue
Block a user