mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
Modules: command <-> core interface modified to get flags & keys.
This commit is contained in:
parent
676a6a4d19
commit
227d68094b
4
src/db.c
4
src/db.c
@ -1124,7 +1124,9 @@ int *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, in
|
||||
* This function uses the command table if a command-specific helper function
|
||||
* is not required, otherwise it calls the command-specific function. */
|
||||
int *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {
|
||||
if (cmd->getkeys_proc) {
|
||||
if (cmd->flags & CMD_MODULE_GETKEYS) {
|
||||
return moduleGetCommandKeysViaAPI(cmd,argv,argc,numkeys);
|
||||
} else if (!(cmd->flags & CMD_MODULE) && cmd->getkeys_proc) {
|
||||
return cmd->getkeys_proc(cmd,argv,argc,numkeys);
|
||||
} else {
|
||||
return getKeysUsingCommandTable(cmd,argv,argc,numkeys);
|
||||
|
140
src/module.c
140
src/module.c
@ -52,12 +52,17 @@ struct RedisModuleCtx {
|
||||
int flags; /* REDISMODULE_CTX_... flags. */
|
||||
void **postponed_arrays; /* To set with RM_ReplySetArrayLength(). */
|
||||
int postponed_arrays_count; /* Number of entries in postponed_arrays. */
|
||||
|
||||
/* Used if there is the REDISMODULE_CTX_KEYS_POS_REQUEST flag set. */
|
||||
int *keys_pos;
|
||||
int keys_count;
|
||||
};
|
||||
typedef struct RedisModuleCtx RedisModuleCtx;
|
||||
|
||||
#define REDISMODULE_CTX_INIT {(void*)(unsigned long)&RM_GetApi, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
|
||||
#define REDISMODULE_CTX_INIT {(void*)(unsigned long)&RM_GetApi, NULL, NULL, NULL, 0, 0, 0, NULL, 0, NULL, 0}
|
||||
#define REDISMODULE_CTX_MULTI_EMITTED (1<<0)
|
||||
#define REDISMODULE_CTX_AUTO_MEMORY (1<<1)
|
||||
#define REDISMODULE_CTX_KEYS_POS_REQUEST (1<<2)
|
||||
|
||||
/* This represents a Redis key opened with RM_OpenKey(). */
|
||||
struct RedisModuleKey {
|
||||
@ -270,10 +275,92 @@ void RedisModuleCommandDispatcher(client *c) {
|
||||
moduleFreeContext(&ctx);
|
||||
}
|
||||
|
||||
/* This function returns the list of keys, with the same interface as the
|
||||
* 'getkeys' function of the native commands, for module commands that exported
|
||||
* the "getkeys-api" flag during the registration. This is done when the
|
||||
* list of keys are not at fixed positions, so that first/last/step cannot
|
||||
* be used.
|
||||
*
|
||||
* In order to accomplish its work, the module command is called, flagging
|
||||
* the context in a way that the command can recognize this is a special
|
||||
* "get keys" call by calling RedisModule_IsKeysPositionRequest(ctx). */
|
||||
int *moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {
|
||||
RedisModuleCommandProxy *cp = (void*)(unsigned long)cmd->getkeys_proc;
|
||||
RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
|
||||
|
||||
ctx.module = cp->module;
|
||||
ctx.client = NULL;
|
||||
ctx.flags |= REDISMODULE_CTX_KEYS_POS_REQUEST;
|
||||
cp->func(&ctx,(void**)argv,argc);
|
||||
int *res = ctx.keys_pos;
|
||||
if (numkeys) *numkeys = ctx.keys_count;
|
||||
moduleFreeContext(&ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Return non-zero if a module command, that was declared with the
|
||||
* flag "getkeys-api", is called in a special way to get the keys positions
|
||||
* and not to get executed. Otherwise zero is returned. */
|
||||
int RM_IsKeysPositionRequest(RedisModuleCtx *ctx) {
|
||||
return (ctx->flags & REDISMODULE_CTX_KEYS_POS_REQUEST) != 0;
|
||||
}
|
||||
|
||||
/* When a module command is called in order to obtain the position of
|
||||
* keys, since it was flagged as "getkeys-api" during the registration,
|
||||
* the command implementation checks for this special call using the
|
||||
* RedisModule_IsKeysPositionRequest() API and uses this function in
|
||||
* order to report keys, like in the following example:
|
||||
*
|
||||
* if (RedisModule_IsKeysPositionRequest(ctx)) {
|
||||
* RedisModule_KeyAtPos(ctx,1);
|
||||
* RedisModule_KeyAtPos(ctx,2);
|
||||
* }
|
||||
*
|
||||
* Note: in the example below the get keys API would not be needed since
|
||||
* keys are at fixed positions. This interface is only used for commands
|
||||
* with a more complex structure. */
|
||||
void RM_KeyAtPos(RedisModuleCtx *ctx, int pos) {
|
||||
if (!(ctx->flags & REDISMODULE_CTX_KEYS_POS_REQUEST)) return;
|
||||
if (pos <= 0) return;
|
||||
ctx->keys_pos = zrealloc(ctx->keys_pos,sizeof(int)*(ctx->keys_count+1));
|
||||
ctx->keys_pos[ctx->keys_count++] = pos;
|
||||
}
|
||||
|
||||
/* Helper for RM_CreateCommand(). Truns a string representing command
|
||||
* flags into the command flags used by the Redis core.
|
||||
*
|
||||
* It returns the set of flags, or -1 if unknown flags are found. */
|
||||
int commandFlagsFromString(char *s) {
|
||||
int count, j;
|
||||
int flags = 0;
|
||||
sds *tokens = sdssplitlen(s,strlen(s)," ",1,&count);
|
||||
for (j = 0; j < count; j++) {
|
||||
char *t = tokens[j];
|
||||
if (!strcasecmp(t,"write")) flags |= CMD_WRITE;
|
||||
else if (!strcasecmp(t,"readonly")) flags |= CMD_READONLY;
|
||||
else if (!strcasecmp(t,"admin")) flags |= CMD_ADMIN;
|
||||
else if (!strcasecmp(t,"deny-oom")) flags |= CMD_DENYOOM;
|
||||
else if (!strcasecmp(t,"deny-script")) flags |= CMD_NOSCRIPT;
|
||||
else if (!strcasecmp(t,"allow-loading")) flags |= CMD_LOADING;
|
||||
else if (!strcasecmp(t,"pubsub")) flags |= CMD_PUBSUB;
|
||||
else if (!strcasecmp(t,"random")) flags |= CMD_RANDOM;
|
||||
else if (!strcasecmp(t,"allow-stale")) flags |= CMD_STALE;
|
||||
else if (!strcasecmp(t,"no-monitor")) flags |= CMD_SKIP_MONITOR;
|
||||
else if (!strcasecmp(t,"fast")) flags |= CMD_FAST;
|
||||
else if (!strcasecmp(t,"getkeys-api")) flags |= CMD_MODULE_GETKEYS;
|
||||
else if (!strcasecmp(t,"no-cluster")) flags |= CMD_MODULE_NO_CLUSTER;
|
||||
else break;
|
||||
}
|
||||
sdsfreesplitres(tokens,count);
|
||||
if (j != count) return -1; /* Some token not processed correctly. */
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* 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 is returned.
|
||||
* name is already busy or a set of invalid flags were passed, otherwise
|
||||
* REDISMODULE_OK is returned and the new command is registered.
|
||||
*
|
||||
* This function must be called during the initialization of the module
|
||||
* inside the RedisModule_OnLoad() function. Calling this function outside
|
||||
@ -284,8 +371,45 @@ void RedisModuleCommandDispatcher(client *c) {
|
||||
* int MyCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
|
||||
*
|
||||
* And is supposed to always return REDISMODULE_OK.
|
||||
*
|
||||
* The set of flags 'strflags' specify the behavior of the command, and should
|
||||
* be passed as a C string compoesd of space separated words, like for
|
||||
* example "write deny-oom". The set of flags are:
|
||||
*
|
||||
* "write": The command may modify the data set (it may also read from it).
|
||||
* "readonly": The command returns data from keys but never writes.
|
||||
* "admin": The command is an administrative command (may change replication
|
||||
* or perform similar tasks).
|
||||
* "deny-oom": The command may use additional memory and should be denied during
|
||||
* out of memory conditions.
|
||||
* "deny-script": Don't allow this command in Lua scripts.
|
||||
* "allow-loading": Allow this command while the server is loading data. Only
|
||||
* commands not interacting with the data set should be allowed
|
||||
* to run in this mode. If not sure don't use this flag.
|
||||
* "pubsub": The command publishes things on Pub/Sub channels.
|
||||
* "random": The command may have different outputs even starting from the
|
||||
* same input arguments and key values.
|
||||
* "allow-stale": The command is allowed to run on slaves that don't serve stale
|
||||
* data. Don't use if you don't know what this means.
|
||||
* "no-monitor": Don't propoagate the command on monitor. Use this if the command
|
||||
* has sensible data among the arguments.
|
||||
* "fast": The command time complexity is not greater than O(log(N)) where
|
||||
* N is the size of the collection or anything else representing
|
||||
* the normal scalability issue with the command.
|
||||
* "getkeys-api": The command implements the interface to return the arguments
|
||||
* that are keys. Used when start/stop/step is not enough because
|
||||
* of the command syntax.
|
||||
* "no-cluster": The command should not register in Redis Cluster since is not
|
||||
* designed to work with it because, for example, is unable to
|
||||
* report the position of the keys, programmatically creates key
|
||||
* names, or any other reason.
|
||||
*/
|
||||
int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc) {
|
||||
int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) {
|
||||
int flags = strflags ? commandFlagsFromString((char*)strflags) : 0;
|
||||
if (flags == -1) return REDISMODULE_ERR;
|
||||
if ((flags & CMD_MODULE_NO_CLUSTER) && server.cluster_enabled)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
struct redisCommand *rediscmd;
|
||||
RedisModuleCommandProxy *cp;
|
||||
sds cmdname = sdsnew(name);
|
||||
@ -310,11 +434,11 @@ int RM_CreateCommand(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc c
|
||||
cp->rediscmd->name = cmdname;
|
||||
cp->rediscmd->proc = RedisModuleCommandDispatcher;
|
||||
cp->rediscmd->arity = -1;
|
||||
cp->rediscmd->flags = 0;
|
||||
cp->rediscmd->flags = flags | CMD_MODULE;
|
||||
cp->rediscmd->getkeys_proc = (redisGetKeysProc*)(unsigned long)cp;
|
||||
cp->rediscmd->firstkey = 1;
|
||||
cp->rediscmd->lastkey = 1;
|
||||
cp->rediscmd->keystep = 1;
|
||||
cp->rediscmd->firstkey = firstkey;
|
||||
cp->rediscmd->lastkey = lastkey;
|
||||
cp->rediscmd->keystep = keystep;
|
||||
cp->rediscmd->microseconds = 0;
|
||||
cp->rediscmd->calls = 0;
|
||||
dictAdd(server.commands,sdsdup(cmdname),cp->rediscmd);
|
||||
@ -2129,6 +2253,8 @@ void moduleRegisterCoreAPI(void) {
|
||||
REGISTER_API(ZsetRangeEndReached);
|
||||
REGISTER_API(HashSet);
|
||||
REGISTER_API(HashGet);
|
||||
REGISTER_API(IsKeysPositionRequest);
|
||||
REGISTER_API(KeyAtPos);
|
||||
}
|
||||
|
||||
/* Global initialization at Redis startup. */
|
||||
|
@ -761,7 +761,6 @@ Work in progress. Implement and document the following API:
|
||||
|
||||
RedisModule_IsKeysPositionRequest(ctx);
|
||||
RedisModule_KeyAtPos(ctx,pos);
|
||||
RedisModule_KeyAtRange(ctx,start,stop,step);
|
||||
|
||||
Command implementations, on keys position request, must reply with
|
||||
`REDISMODULE_KEYPOS_OK` to signal the request was processed, otherwise
|
||||
|
@ -455,63 +455,64 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx) {
|
||||
== REDISMODULE_ERR) return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.simple",
|
||||
HelloSimple_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloSimple_RedisCommand,"readonly",0,0,0) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.push.native",
|
||||
HelloPushNative_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloPushNative_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.push.call",
|
||||
HelloPushCall_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloPushCall_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.push.call2",
|
||||
HelloPushCall2_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloPushCall2_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.list.sum.len",
|
||||
HelloListSumLen_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloListSumLen_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.list.splice",
|
||||
HelloListSplice_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloListSplice_RedisCommand,"write deny-oom",1,2,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.list.splice.auto",
|
||||
HelloListSpliceAuto_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloListSpliceAuto_RedisCommand,
|
||||
"write deny-oom",1,2,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.rand.array",
|
||||
HelloRandArray_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloRandArray_RedisCommand,"readonly",0,0,0) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.repl1",
|
||||
HelloRepl1_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloRepl1_RedisCommand,"write",0,0,0) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.repl2",
|
||||
HelloRepl2_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloRepl2_RedisCommand,"write",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.toggle.case",
|
||||
HelloToggleCase_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloToggleCase_RedisCommand,"write",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.more.expire",
|
||||
HelloMoreExpire_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloMoreExpire_RedisCommand,"write",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.zsumrange",
|
||||
HelloZsumRange_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloZsumRange_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.lexrange",
|
||||
HelloLexRange_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloLexRange_RedisCommand,"readonly",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
if (RedisModule_CreateCommand(ctx,"hello.hcopy",
|
||||
HelloHCopy_RedisCommand) == REDISMODULE_ERR)
|
||||
HelloHCopy_RedisCommand,"write deny-oom",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
return REDISMODULE_OK;
|
||||
|
@ -87,7 +87,7 @@ typedef int (*RedisModuleCmdFunc) (RedisModuleCtx *ctx, RedisModuleString **argv
|
||||
#define REDISMODULE_API_FUNC(x) (*x)
|
||||
|
||||
int REDISMODULE_API_FUNC(RedisModule_GetApi)(const char *, void *);
|
||||
int REDISMODULE_API_FUNC(RedisModule_CreateCommand)(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc);
|
||||
int REDISMODULE_API_FUNC(RedisModule_CreateCommand)(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep);
|
||||
int REDISMODULE_API_FUNC(RedisModule_SetModuleAttribs)(RedisModuleCtx *ctx, const char *name, int ver, int apiver);
|
||||
int REDISMODULE_API_FUNC(RedisModule_WrongArity)(RedisModuleCtx *ctx);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ReplyWithLongLong)(RedisModuleCtx *ctx, long long ll);
|
||||
@ -147,6 +147,8 @@ int REDISMODULE_API_FUNC(RedisModule_ZsetRangePrev)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_ZsetRangeEndReached)(RedisModuleKey *key);
|
||||
int REDISMODULE_API_FUNC(RedisModule_HashSet)(RedisModuleKey *key, int flags, ...);
|
||||
int REDISMODULE_API_FUNC(RedisModule_HashGet)(RedisModuleKey *key, int flags, ...);
|
||||
int REDISMODULE_API_FUNC(RedisModule_IsKeysPositionRequest)(RedisModuleCtx *ctx);
|
||||
void REDISMODULE_API_FUNC(RedisModule_KeyAtPos)(RedisModuleCtx *ctx, int pos);
|
||||
|
||||
/* This is included inline inside each Redis module. */
|
||||
static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) {
|
||||
@ -213,6 +215,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
|
||||
REDISMODULE_GET_API(ZsetRangeEndReached);
|
||||
REDISMODULE_GET_API(HashSet);
|
||||
REDISMODULE_GET_API(HashGet);
|
||||
REDISMODULE_GET_API(IsKeysPositionRequest);
|
||||
REDISMODULE_GET_API(KeyAtPos);
|
||||
|
||||
RedisModule_SetModuleAttribs(ctx,name,ver,apiver);
|
||||
return REDISMODULE_OK;
|
||||
|
@ -2761,7 +2761,9 @@ void addReplyCommand(client *c, struct redisCommand *cmd) {
|
||||
flagcount += addReplyCommandFlag(c,cmd,CMD_SKIP_MONITOR, "skip_monitor");
|
||||
flagcount += addReplyCommandFlag(c,cmd,CMD_ASKING, "asking");
|
||||
flagcount += addReplyCommandFlag(c,cmd,CMD_FAST, "fast");
|
||||
if (cmd->getkeys_proc) {
|
||||
if ((cmd->getkeys_proc && !(cmd->flags & CMD_MODULE)) ||
|
||||
cmd->flags & CMD_MODULE_GETKEYS)
|
||||
{
|
||||
addReplyStatus(c, "movablekeys");
|
||||
flagcount += 1;
|
||||
}
|
||||
|
31
src/server.h
31
src/server.h
@ -178,20 +178,22 @@ typedef long long mstime_t; /* millisecond time type. */
|
||||
|
||||
/* Command flags. Please check the command table defined in the redis.c file
|
||||
* for more information about the meaning of every flag. */
|
||||
#define CMD_WRITE 1 /* "w" flag */
|
||||
#define CMD_READONLY 2 /* "r" flag */
|
||||
#define CMD_DENYOOM 4 /* "m" flag */
|
||||
#define CMD_NOT_USED_1 8 /* no longer used flag */
|
||||
#define CMD_ADMIN 16 /* "a" flag */
|
||||
#define CMD_PUBSUB 32 /* "p" flag */
|
||||
#define CMD_NOSCRIPT 64 /* "s" flag */
|
||||
#define CMD_RANDOM 128 /* "R" flag */
|
||||
#define CMD_SORT_FOR_SCRIPT 256 /* "S" flag */
|
||||
#define CMD_LOADING 512 /* "l" flag */
|
||||
#define CMD_STALE 1024 /* "t" flag */
|
||||
#define CMD_SKIP_MONITOR 2048 /* "M" flag */
|
||||
#define CMD_ASKING 4096 /* "k" flag */
|
||||
#define CMD_FAST 8192 /* "F" flag */
|
||||
#define CMD_WRITE (1<<0) /* "w" flag */
|
||||
#define CMD_READONLY (1<<1) /* "r" flag */
|
||||
#define CMD_DENYOOM (1<<2) /* "m" flag */
|
||||
#define CMD_MODULE (1<<3) /* Command exported by module. */
|
||||
#define CMD_ADMIN (1<<4) /* "a" flag */
|
||||
#define CMD_PUBSUB (1<<5) /* "p" flag */
|
||||
#define CMD_NOSCRIPT (1<<6) /* "s" flag */
|
||||
#define CMD_RANDOM (1<<7) /* "R" flag */
|
||||
#define CMD_SORT_FOR_SCRIPT (1<<8) /* "S" flag */
|
||||
#define CMD_LOADING (1<<9) /* "l" flag */
|
||||
#define CMD_STALE (1<<10) /* "t" flag */
|
||||
#define CMD_SKIP_MONITOR (1<<11) /* "M" flag */
|
||||
#define CMD_ASKING (1<<12) /* "k" flag */
|
||||
#define CMD_FAST (1<<13) /* "F" flag */
|
||||
#define CMD_MODULE_GETKEYS (1<<14) /* Use the modules getkeys interface. */
|
||||
#define CMD_MODULE_NO_CLUSTER (1<<15) /* Deny on Redis Cluster. */
|
||||
|
||||
/* Defines related to the dump file format. To store 32 bits lengths for short
|
||||
* keys requires a lot of space, so we check the most significant 2 bits of
|
||||
@ -1098,6 +1100,7 @@ extern dictType modulesDictType;
|
||||
void moduleInitModulesSystem(void);
|
||||
int moduleLoad(const char *path);
|
||||
void moduleLoadFromQueue(void);
|
||||
int *moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);
|
||||
|
||||
/* Utils */
|
||||
long long ustime(void);
|
||||
|
Loading…
Reference in New Issue
Block a user