152 lines
5.6 KiB
C
152 lines
5.6 KiB
C
#ifndef __UTIL_H__
|
|
#define __UTIL_H__
|
|
|
|
#include <redismodule.h>
|
|
#include <stdarg.h>
|
|
|
|
/// make sure the response is not NULL or an error, and if it is sends the error to the client and
|
|
/// exit the current function
|
|
#define RMUTIL_ASSERT_NOERROR(ctx, r) \
|
|
if (r == NULL) { \
|
|
return RedisModule_ReplyWithError(ctx, "ERR reply is NULL"); \
|
|
} else if (RedisModule_CallReplyType(r) == REDISMODULE_REPLY_ERROR) { \
|
|
RedisModule_ReplyWithCallReply(ctx, r); \
|
|
return REDISMODULE_ERR; \
|
|
}
|
|
|
|
#define __rmutil_register_cmd(ctx, cmd, f, mode) \
|
|
if (RedisModule_CreateCommand(ctx, cmd, f, mode, 1, 1, 1) == REDISMODULE_ERR) \
|
|
return REDISMODULE_ERR;
|
|
|
|
#define RMUtil_RegisterReadCmd(ctx, cmd, f) __rmutil_register_cmd(ctx, cmd, f, "readonly")
|
|
|
|
#define RMUtil_RegisterWriteCmd(ctx, cmd, f) __rmutil_register_cmd(ctx, cmd, f, "write")
|
|
|
|
#define RMUtil_RegisterWriteDenyOOMCmd(ctx, cmd, f) __rmutil_register_cmd(ctx, cmd, f, "write deny-oom")
|
|
|
|
/* RedisModule utilities. */
|
|
|
|
/** DEPRECATED: Return the offset of an arg if it exists in the arg list, or 0 if it's not there */
|
|
int RMUtil_ArgExists(const char *arg, RedisModuleString **argv, int argc, int offset);
|
|
|
|
/* Same as argExists but returns -1 if not found. Use this, RMUtil_ArgExists is kept for backwards
|
|
compatibility. */
|
|
int RMUtil_ArgIndex(const char *arg, RedisModuleString **argv, int argc);
|
|
|
|
/**
|
|
Automatically conver the arg list to corresponding variable pointers according to a given format.
|
|
You pass it the command arg list and count, the starting offset, a parsing format, and pointers to
|
|
the variables.
|
|
The format is a string consisting of the following identifiers:
|
|
|
|
c -- pointer to a Null terminated C string pointer.
|
|
s -- pointer to a RedisModuleString
|
|
l -- pointer to Long long integer.
|
|
d -- pointer to a Double
|
|
* -- do not parse this argument at all
|
|
|
|
Example: If I want to parse args[1], args[2] as a long long and double, I do:
|
|
double d;
|
|
long long l;
|
|
RMUtil_ParseArgs(argv, argc, 1, "ld", &l, &d);
|
|
*/
|
|
int RMUtil_ParseArgs(RedisModuleString **argv, int argc, int offset, const char *fmt, ...);
|
|
|
|
/**
|
|
Same as RMUtil_ParseArgs, but only parses the arguments after `token`, if it was found.
|
|
This is useful for optional stuff like [LIMIT [offset] [limit]]
|
|
*/
|
|
int RMUtil_ParseArgsAfter(const char *token, RedisModuleString **argv, int argc, const char *fmt,
|
|
...);
|
|
|
|
int rmutil_vparseArgs(RedisModuleString **argv, int argc, int offset, const char *fmt, va_list ap);
|
|
|
|
#define RMUTIL_VARARGS_BADARG ((size_t)-1)
|
|
/**
|
|
* Parse arguments in the form of KEYWORD {len} {arg} .. {arg}_len.
|
|
* If keyword is present, returns the position within `argv` containing the arguments.
|
|
* Returns NULL if the keyword is not found.
|
|
* If a parse error has occurred, `nargs` is set to RMUTIL_VARARGS_BADARG, but
|
|
* the return value is not NULL.
|
|
*/
|
|
RedisModuleString **RMUtil_ParseVarArgs(RedisModuleString **argv, int argc, int offset,
|
|
const char *keyword, size_t *nargs);
|
|
|
|
/**
|
|
* Default implementation of an AoF rewrite function that simply calls DUMP/RESTORE
|
|
* internally. To use this function, pass it as the .aof_rewrite value in
|
|
* RedisModuleTypeMethods
|
|
*/
|
|
void RMUtil_DefaultAofRewrite(RedisModuleIO *aof, RedisModuleString *key, void *value);
|
|
|
|
// A single key/value entry in a redis info map
|
|
typedef struct {
|
|
char *key;
|
|
char *val;
|
|
} RMUtilInfoEntry;
|
|
|
|
// Representation of INFO command response, as a list of k/v pairs
|
|
typedef struct {
|
|
RMUtilInfoEntry *entries;
|
|
int numEntries;
|
|
} RMUtilInfo;
|
|
|
|
/**
|
|
* Get redis INFO result and parse it as RMUtilInfo.
|
|
* Returns NULL if something goes wrong.
|
|
* The resulting object needs to be freed with RMUtilRedisInfo_Free
|
|
*/
|
|
RMUtilInfo *RMUtil_GetRedisInfo(RedisModuleCtx *ctx);
|
|
|
|
/**
|
|
* Free an RMUtilInfo object and its entries
|
|
*/
|
|
void RMUtilRedisInfo_Free(RMUtilInfo *info);
|
|
|
|
/**
|
|
* Get an integer value from an info object. Returns 1 if the value was found and
|
|
* is an integer, 0 otherwise. the value is placed in 'val'
|
|
*/
|
|
int RMUtilInfo_GetInt(RMUtilInfo *info, const char *key, long long *val);
|
|
|
|
/**
|
|
* Get a string value from an info object. The value is placed in str.
|
|
* Returns 1 if the key was found, 0 if not
|
|
*/
|
|
int RMUtilInfo_GetString(RMUtilInfo *info, const char *key, const char **str);
|
|
|
|
/**
|
|
* Get a double value from an info object. Returns 1 if the value was found and is
|
|
* a correctly formatted double, 0 otherwise. the value is placed in 'd'
|
|
*/
|
|
int RMUtilInfo_GetDouble(RMUtilInfo *info, const char *key, double *d);
|
|
|
|
/*
|
|
* Returns a call reply array's element given by a space-delimited path. E.g.,
|
|
* the path "1 2 3" will return the 3rd element from the 2 element of the 1st
|
|
* element from an array (or NULL if not found)
|
|
*/
|
|
RedisModuleCallReply *RedisModule_CallReplyArrayElementByPath(RedisModuleCallReply *rep,
|
|
const char *path);
|
|
|
|
/**
|
|
* Extract the module type from an opened key.
|
|
*/
|
|
typedef enum {
|
|
RMUTIL_VALUE_OK = 0,
|
|
RMUTIL_VALUE_MISSING,
|
|
RMUTIL_VALUE_EMPTY,
|
|
RMUTIL_VALUE_MISMATCH
|
|
} RMUtil_TryGetValueStatus;
|
|
|
|
/**
|
|
* Tries to extract the module-specific type from the value.
|
|
* @param key an opened key (may be null)
|
|
* @param type the pointer to the type to match to
|
|
* @param[out] out if the value is present, will be set to it.
|
|
* @return a value in the @ref RMUtil_TryGetValueStatus enum.
|
|
*/
|
|
int RedisModule_TryGetValue(RedisModuleKey *key, const RedisModuleType *type, void **out);
|
|
|
|
#endif
|