From 41b1b5df183aa4bd2043413394debdfa6d40d762 Mon Sep 17 00:00:00 2001 From: YaacovHazan Date: Wed, 2 Apr 2025 16:59:16 +0300 Subject: [PATCH] Add vector-sets module The vector-sets module is a part of Redis Core and is available by default, just like any other data type in Redis. As a result, when building Redis from the source, the vector-sets module is also compiled as part of the Redis binary and loaded at server start-up. This new data type added as a preview currently doesn't support all the capabilities in Redis like: 32-bit OS C99 Short-read that might end with memory leak AOF rewirte defrag --- .github/workflows/daily.yml | 2 +- modules/common.mk | 4 +- modules/vector-sets/LICENSE | 2 - modules/vector-sets/Makefile | 2 +- modules/vector-sets/README.md | 6 +- modules/vector-sets/examples/cli-tool/cli.py | 8 + .../vector-sets/examples/glove-100/insert.py | 8 + .../vector-sets/examples/glove-100/recall.py | 8 + modules/vector-sets/examples/movies/insert.py | 8 + modules/vector-sets/expr.c | 10 +- modules/vector-sets/hnsw.c | 38 +- modules/vector-sets/hnsw.h | 7 +- modules/vector-sets/redismodule.h | 1704 ----------------- modules/vector-sets/test.py | 9 +- modules/vector-sets/vset.c | 35 +- modules/vector-sets/w2v.c | 6 +- redis-full.conf | 376 ++++ src/Makefile | 17 +- src/config.c | 3 + src/module.c | 27 +- src/server.c | 1 + src/server.h | 2 + utils/req-res-log-validator.py | 12 + 23 files changed, 539 insertions(+), 1756 deletions(-) delete mode 100644 modules/vector-sets/LICENSE delete mode 100644 modules/vector-sets/redismodule.h create mode 100644 redis-full.conf diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index 8d71ce650..6d1cc79c6 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -632,7 +632,7 @@ jobs: repository: ${{ env.GITHUB_REPOSITORY }} ref: ${{ env.GITHUB_HEAD_REF }} - name: make - run: make SANITIZER=undefined REDIS_CFLAGS='-DREDIS_TEST -Werror' LUA_DEBUG=yes # we (ab)use this flow to also check Lua C API violations + run: make SANITIZER=undefined REDIS_CFLAGS='-DREDIS_TEST -Werror' SKIP_VEC_SETS=yes LUA_DEBUG=yes # we (ab)use this flow to also check Lua C API violations - name: testprep run: | sudo apt-get update diff --git a/modules/common.mk b/modules/common.mk index bf705df8d..bb5f65cc6 100644 --- a/modules/common.mk +++ b/modules/common.mk @@ -25,6 +25,7 @@ all: $(TARGET_MODULE) $(TARGET_MODULE): get_source $(MAKE) -C $(SRC_DIR) + cp ${TARGET_MODULE} ./ get_source: $(SRC_DIR)/.prepared @@ -35,8 +36,9 @@ $(SRC_DIR)/.prepared: clean: -$(MAKE) -C $(SRC_DIR) clean + rm ./*.so -distclean: +distclean: clean -$(MAKE) -C $(SRC_DIR) distclean pristine: diff --git a/modules/vector-sets/LICENSE b/modules/vector-sets/LICENSE deleted file mode 100644 index 79fb7e399..000000000 --- a/modules/vector-sets/LICENSE +++ /dev/null @@ -1,2 +0,0 @@ -This code is Copyright (c) 2024-Present, Redis Ltd. -All Rights Reserved. diff --git a/modules/vector-sets/Makefile b/modules/vector-sets/Makefile index 407ed08ce..808b9e828 100644 --- a/modules/vector-sets/Makefile +++ b/modules/vector-sets/Makefile @@ -53,7 +53,7 @@ all: vset.so .c.xo: $(CC) -I. $(CFLAGS) $(SHOBJ_CFLAGS) -fPIC -c $< -o $@ -vset.xo: redismodule.h expr.c +vset.xo: ../../src/redismodule.h expr.c vset.so: vset.xo hnsw.xo cJSON.xo $(CC) -o $@ $^ $(SHOBJ_LDFLAGS) $(LIBS) $(SAN) -lc diff --git a/modules/vector-sets/README.md b/modules/vector-sets/README.md index 1ed1cb2cf..43038d089 100644 --- a/modules/vector-sets/README.md +++ b/modules/vector-sets/README.md @@ -156,7 +156,7 @@ Because vector sets perform insertion time normalization and optional quantization, the returned vector could be approximated. `VEMB` will take care to de-quantized and de-normalize the vector before returning it. -It is possible to ask VEMB to return raw data, that is, the interal representation used by the vector: fp32, int8, or a bitmap for binary quantization. This behavior is triggered by the `RAW` option of of VEMB: +It is possible to ask VEMB to return raw data, that is, the internal representation used by the vector: fp32, int8, or a bitmap for binary quantization. This behavior is triggered by the `RAW` option of of VEMB: VEMB word_embedding apple RAW @@ -530,10 +530,10 @@ Notably, this pattern can be implemented in a way that avoids paying the sum of Vector Sets, or better, HNSWs, the underlying data structure used by Vector Sets, combined with the features provided by the Vector Sets themselves (quantization, random projection, filtering, ...) form an implementation that has a non-trivial space of parameters that can be tuned. Despite to the complexity of the implementation and of vector similarity problems, here there is a list of simple ideas that can drive the user to pick the best settings: -* 8 bit quantization (the default) is almost always a win. It reduces the memory usage of vectors by a factor of 4, yet the performance penality in terms of recall is minimal. It also reduces insertion and search time by around 2 times or more. +* 8 bit quantization (the default) is almost always a win. It reduces the memory usage of vectors by a factor of 4, yet the performance penalty in terms of recall is minimal. It also reduces insertion and search time by around 2 times or more. * Binary quantization is much more extreme: it makes vector sets a lot faster, but increases the recall error in a sensible way, for instance from 95% to 80% if all the parameters remain the same. Yet, the speedup is really big, and the memory usage of vectors, compaerd to full precision vectors, 32 times smaller. * Vectors memory usage are not the only responsible for Vector Set high memory usage per entry: nodes contain, on average `M*2 + M*0.33` pointers, where M is by default 16 (but can be tuned in `VADD`, see the `M` option). Also each node has the string item and the optional JSON attributes: those should be as small as possible in order to avoid contributing more to the memory usage. -* The `M` parameter should be incresed to 32 or more only when a near perfect recall is really needed. +* The `M` parameter should be increased to 32 or more only when a near perfect recall is really needed. * It is possible to gain space (less memory usage) sacrificing time (more CPU time) by using a low `M` (the default of 16, for instance) and a high `EF` (the effort parameter of `VSIM`) in order to scan the graph more deeply. * When memory usage is seriosu concern, and there is the suspect the vectors we are storing don't contain as much information - at least for our use case - to justify the number of components they feature, random projection (the `REDUCE` option of `VADD`) could be tested to see if dimensionality reduction is possible with acceptable precision loss. diff --git a/modules/vector-sets/examples/cli-tool/cli.py b/modules/vector-sets/examples/cli-tool/cli.py index a60c5facc..66825f2ff 100755 --- a/modules/vector-sets/examples/cli-tool/cli.py +++ b/modules/vector-sets/examples/cli-tool/cli.py @@ -1,3 +1,11 @@ +# +# Copyright (c) 2009-Present, Redis Ltd. +# All rights reserved. +# +# Licensed under your choice of the Redis Source Available License 2.0 +# (RSALv2) or the Server Side Public License v1 (SSPLv1). +# + #!/usr/bin/env python3 import redis import requests diff --git a/modules/vector-sets/examples/glove-100/insert.py b/modules/vector-sets/examples/glove-100/insert.py index fe9658343..53ad90fd9 100644 --- a/modules/vector-sets/examples/glove-100/insert.py +++ b/modules/vector-sets/examples/glove-100/insert.py @@ -1,3 +1,11 @@ +# +# Copyright (c) 2009-Present, Redis Ltd. +# All rights reserved. +# +# Licensed under your choice of the Redis Source Available License 2.0 +# (RSALv2) or the Server Side Public License v1 (SSPLv1). +# + import h5py import redis from tqdm import tqdm diff --git a/modules/vector-sets/examples/glove-100/recall.py b/modules/vector-sets/examples/glove-100/recall.py index 28982b3e9..a5b556ec4 100644 --- a/modules/vector-sets/examples/glove-100/recall.py +++ b/modules/vector-sets/examples/glove-100/recall.py @@ -1,3 +1,11 @@ +# +# Copyright (c) 2009-Present, Redis Ltd. +# All rights reserved. +# +# Licensed under your choice of the Redis Source Available License 2.0 +# (RSALv2) or the Server Side Public License v1 (SSPLv1). +# + import h5py import redis import numpy as np diff --git a/modules/vector-sets/examples/movies/insert.py b/modules/vector-sets/examples/movies/insert.py index 576243667..1a2c5dcf0 100644 --- a/modules/vector-sets/examples/movies/insert.py +++ b/modules/vector-sets/examples/movies/insert.py @@ -1,3 +1,11 @@ +# +# Copyright (c) 2009-Present, Redis Ltd. +# All rights reserved. +# +# Licensed under your choice of the Redis Source Available License 2.0 +# (RSALv2) or the Server Side Public License v1 (SSPLv1). +# + import csv import requests import redis diff --git a/modules/vector-sets/expr.c b/modules/vector-sets/expr.c index d9712921e..e46951fd2 100644 --- a/modules/vector-sets/expr.c +++ b/modules/vector-sets/expr.c @@ -3,7 +3,11 @@ * general code to be used when we want to tell if a given object (with fields) * passes or fails a given test for scalars, strings, ... * - * Copyright(C) 2024-Present, Redis Ltd. All Rights Reserved. + * Copyright (c) 2009-Present, Redis Ltd. + * All rights reserved. + * + * Licensed under your choice of the Redis Source Available License 2.0 + * (RSALv2) or the Server Side Public License v1 (SSPLv1). * Originally authored by: Salvatore Sanfilippo. */ @@ -83,7 +87,7 @@ typedef struct exprstate { char *expr; /* Expression string to compile. Note that * expression token strings point directly to this * string. */ - char *p; // Currnet position inside 'expr', while parsing. + char *p; // Current position inside 'expr', while parsing. // Virtual machine state. exprstack values_stack; @@ -685,7 +689,7 @@ double exprTokenToNum(exprtoken *t) { } } -/* Conver obejct to true/false (0 or 1) */ +/* Convert object to true/false (0 or 1) */ double exprTokenToBool(exprtoken *t) { if (t->token_type == EXPR_TOKEN_NUM) { return t->num != 0; diff --git a/modules/vector-sets/hnsw.c b/modules/vector-sets/hnsw.c index a9a2695ad..eb37221b9 100644 --- a/modules/vector-sets/hnsw.c +++ b/modules/vector-sets/hnsw.c @@ -13,7 +13,7 @@ * be not close enough to replace old links in candidate. * * 2. We normalize on-insert, making cosine similarity and dot product the - * same. This means we can't use euclidian distance or alike here. + * same. This means we can't use euclidean distance or alike here. * Together with quantization, this provides an important speedup that * makes HNSW more practical. * @@ -25,7 +25,11 @@ * bidirectional), and reliking the nodes orphaned of one link among * them. * - * Copyright(C) 2024-Present, Redis Ltd. All Rights Reserved. + * Copyright (c) 2009-Present, Redis Ltd. + * All rights reserved. + * + * Licensed under your choice of the Redis Source Available License 2.0 + * (RSALv2) or the Server Side Public License v1 (SSPLv1). * Originally authored by: Salvatore Sanfilippo. */ @@ -109,7 +113,7 @@ typedef struct { } pqueue; /* The HNSW algorithms access the pqueue conceptually from nearest (index 0) - * to farest (larger indexes) node, so the following macros are used to + * to farthest (larger indexes) node, so the following macros are used to * access the pqueue in this fashion, even if the internal order is * actually reversed. */ #define pq_get_node(q,i) ((q)->items[(q)->count-(i+1)].node) @@ -209,7 +213,7 @@ float vectors_distance_float(const float *x, const float *y, uint32_t dim) { } /* Handle the remaining elements. These are a minority in the case - * of a smal vector, don't optimze this part. */ + * of a small vector, don't optimize this part. */ for (; i < dim; i++) dot0 += x[i] * y[i]; /* The following line may be counter intuitive. The dot product of @@ -897,7 +901,7 @@ void hnsw_update_worst_neighbor_on_remove(HNSW *index, hnswNode *node, uint32_t } } -/* We have a list of candidate nodes to link to the new node, when iserting +/* We have a list of candidate nodes to link to the new node, when inserting * one. This function selects which nodes to link and performs the linking. * * Parameters: @@ -906,14 +910,14 @@ void hnsw_update_worst_neighbor_on_remove(HNSW *index, hnswNode *node, uint32_t * new node 'new_node'. * - 'required_links' is as many links we would like our new_node to get * at the specified layer. - * - 'aggressive' changes the startegy used to find good neighbors as follows: + * - 'aggressive' changes the strategy used to find good neighbors as follows: * * This function is called with aggressive=0 for all the layers, including * layer 0. When called like that, it will use the diversity of links and * quality of links checks before linking our new node with some candidate. * * However if the insert function finds that at layer 0, with aggressive=0, - * few connections were made, it calls this function again with agressiveness + * few connections were made, it calls this function again with aggressiveness * levels greater up to 2. * * At aggressive=1, the diversity checks are disabled, and the candidate @@ -925,7 +929,7 @@ void hnsw_update_worst_neighbor_on_remove(HNSW *index, hnswNode *node, uint32_t * a connection (to make space for our new node link). In this case: * * 1. If such "dropped" node would remain with too little links, we try with - * some different neighbor instead, however as the 'aggressive' paramter + * some different neighbor instead, however as the 'aggressive' parameter * has incremental values (0, 1, 2) we are more and more willing to leave * the dropped node with fever connections. * 2. If aggressive=2, we will scan the candidate neighbor node links to @@ -1047,7 +1051,7 @@ void select_neighbors(HNSW *index, pqueue *candidates, hnswNode *new_node, { /* Let's see if we can find at least a candidate link that * would remain with a few connections. Track the one - * that is the farest away (worst distance) from our candidate + * that is the farthest away (worst distance) from our candidate * neighbor (in order to remove the less interesting link). */ worst_node = NULL; uint32_t worst_idx = 0; @@ -1192,7 +1196,7 @@ void hnsw_reconnect_nodes(HNSW *index, hnswNode **nodes, int count, uint32_t lay /* Step 1: Build the distance matrix between all nodes. * Since distance(i,j) = distance(j,i), we only compute the upper triangle * and mirror it to the lower triangle. */ - float *distances = hmalloc(count * count * sizeof(float)); + float *distances = hmalloc((unsigned long) count * count * sizeof(float)); if (!distances) return; for (int i = 0; i < count; i++) { @@ -1206,7 +1210,7 @@ void hnsw_reconnect_nodes(HNSW *index, hnswNode **nodes, int count, uint32_t lay /* Step 2: Calculate row averages (will be used in scoring): * please note that we just calculate row averages and not - * colums averages since the matrix is symmetrical, so those + * columns averages since the matrix is symmetrical, so those * are the same: check the image in the top comment if you have any * doubt about this. */ float *row_avgs = hmalloc(count * sizeof(float)); @@ -1231,7 +1235,7 @@ void hnsw_reconnect_nodes(HNSW *index, hnswNode **nodes, int count, uint32_t lay * good is a given i,j nodes connection, with how badly connecting * i,j will affect the remaining quality of connections left to * pair the other nodes. */ - float *scores = hmalloc(count * count * sizeof(float)); + float *scores = hmalloc((unsigned long) count * count * sizeof(float)); if (!scores) { hfree(distances); hfree(row_avgs); @@ -1397,7 +1401,7 @@ void hnsw_reconnect_nodes(HNSW *index, hnswNode **nodes, int count, uint32_t lay // If still no connection, search the broader graph. if (nodes[i]->layers[layer].num_links != wanted_links) { - debugmsg("No force linking possible with local candidats\n"); + debugmsg("No force linking possible with local candidates\n"); pq_free(candidates); // Find entry point for target layer by descending through levels. @@ -1414,7 +1418,7 @@ void hnsw_reconnect_nodes(HNSW *index, hnswNode **nodes, int count, uint32_t lay if (curr_ep) { /* Search this layer for candidates. - * Use the defalt EF_C in this case, since it's not an + * Use the default EF_C in this case, since it's not an * "insert" operation, and we don't know the user * specified "EF". */ candidates = search_layer(index, nodes[i], curr_ep, HNSW_EF_C, layer, 0); @@ -1576,7 +1580,7 @@ int hnsw_delete_node(HNSW *index, hnswNode *node, void(*free_value)(void*value)) } /* ============================ Threaded API ================================ - * Concurent readers should use the following API to get a slot assigned + * Concurrent readers should use the following API to get a slot assigned * (and a lock, too), do their read-only call, and unlock the slot. * * There is a reason why read operations don't implement opaque transparent @@ -2348,7 +2352,7 @@ hnswNode *hnsw_cursor_next(hnswCursor *cursor) { } /* Called by hnsw_unlink_node() if there is at least an active cursor. - * Will scan the cursors to see if any cursor is going to yeld this + * Will scan the cursors to see if any cursor is going to yield this * one, and in this case, updates the current element to the next. */ void hnsw_cursor_element_deleted(HNSW *index, hnswNode *deleted) { hnswCursor *x = index->cursors; @@ -2539,7 +2543,7 @@ int hnsw_validate_graph(HNSW *index, uint64_t *connected_nodes, int *reciprocal_ * * This is just a debugging function that reports stuff in the standard * output, part of the implementation because this kind of functions - * provide some visiblity on what happens inside the HNSW. + * provide some visibility on what happens inside the HNSW. */ void hnsw_test_graph_recall(HNSW *index, int test_ef, int verbose) { // Stats diff --git a/modules/vector-sets/hnsw.h b/modules/vector-sets/hnsw.h index 877302e50..44a946fb4 100644 --- a/modules/vector-sets/hnsw.h +++ b/modules/vector-sets/hnsw.h @@ -2,7 +2,12 @@ * HNSW (Hierarchical Navigable Small World) Implementation * Based on the paper by Yu. A. Malkov, D. A. Yashunin * - * Copyright(C) 2024-Pesent Redis Ltd. All Rights Reserved. + * Copyright (c) 2009-Present, Redis Ltd. + * All rights reserved. + * + * Licensed under your choice of the Redis Source Available License 2.0 + * (RSALv2) or the Server Side Public License v1 (SSPLv1). + * Originally authored by: Salvatore Sanfilippo. */ #ifndef HNSW_H diff --git a/modules/vector-sets/redismodule.h b/modules/vector-sets/redismodule.h deleted file mode 100644 index b84913b1e..000000000 --- a/modules/vector-sets/redismodule.h +++ /dev/null @@ -1,1704 +0,0 @@ -#ifndef REDISMODULE_H -#define REDISMODULE_H - -#include -#include -#include -#include - - -typedef struct RedisModuleString RedisModuleString; -typedef struct RedisModuleKey RedisModuleKey; - -/* -------------- Defines NOT common between core and modules ------------- */ - -#if defined REDISMODULE_CORE -/* Things only defined for the modules core (server), not exported to modules - * that include this file. */ - -#define RedisModuleString robj - -#endif /* defined REDISMODULE_CORE */ - -#if !defined REDISMODULE_CORE && !defined REDISMODULE_CORE_MODULE -/* Things defined for modules, but not for core-modules. */ - -typedef long long mstime_t; -typedef long long ustime_t; - -#endif /* !defined REDISMODULE_CORE && !defined REDISMODULE_CORE_MODULE */ - -/* ---------------- Defines common between core and modules --------------- */ - -/* Error status return values. */ -#define REDISMODULE_OK 0 -#define REDISMODULE_ERR 1 - -/* Module Based Authentication status return values. */ -#define REDISMODULE_AUTH_HANDLED 0 -#define REDISMODULE_AUTH_NOT_HANDLED 1 - -/* API versions. */ -#define REDISMODULE_APIVER_1 1 - -/* Version of the RedisModuleTypeMethods structure. Once the RedisModuleTypeMethods - * structure is changed, this version number needs to be changed synchronistically. */ -#define REDISMODULE_TYPE_METHOD_VERSION 5 - -/* API flags and constants */ -#define REDISMODULE_READ (1<<0) -#define REDISMODULE_WRITE (1<<1) - -/* RedisModule_OpenKey extra flags for the 'mode' argument. - * Avoid touching the LRU/LFU of the key when opened. */ -#define REDISMODULE_OPEN_KEY_NOTOUCH (1<<16) -/* Don't trigger keyspace event on key misses. */ -#define REDISMODULE_OPEN_KEY_NONOTIFY (1<<17) -/* Don't update keyspace hits/misses counters. */ -#define REDISMODULE_OPEN_KEY_NOSTATS (1<<18) -/* Avoid deleting lazy expired keys. */ -#define REDISMODULE_OPEN_KEY_NOEXPIRE (1<<19) -/* Avoid any effects from fetching the key */ -#define REDISMODULE_OPEN_KEY_NOEFFECTS (1<<20) -/* Allow access expired key that haven't deleted yet */ -#define REDISMODULE_OPEN_KEY_ACCESS_EXPIRED (1<<21) - -/* Mask of all REDISMODULE_OPEN_KEY_* values. Any new mode should be added to this list. - * Should not be used directly by the module, use RM_GetOpenKeyModesAll instead. - * Located here so when we will add new modes we will not forget to update it. */ -#define _REDISMODULE_OPEN_KEY_ALL REDISMODULE_READ | REDISMODULE_WRITE | REDISMODULE_OPEN_KEY_NOTOUCH | REDISMODULE_OPEN_KEY_NONOTIFY | REDISMODULE_OPEN_KEY_NOSTATS | REDISMODULE_OPEN_KEY_NOEXPIRE | REDISMODULE_OPEN_KEY_NOEFFECTS | REDISMODULE_OPEN_KEY_ACCESS_EXPIRED - -/* List push and pop */ -#define REDISMODULE_LIST_HEAD 0 -#define REDISMODULE_LIST_TAIL 1 - -/* Key types. */ -#define REDISMODULE_KEYTYPE_EMPTY 0 -#define REDISMODULE_KEYTYPE_STRING 1 -#define REDISMODULE_KEYTYPE_LIST 2 -#define REDISMODULE_KEYTYPE_HASH 3 -#define REDISMODULE_KEYTYPE_SET 4 -#define REDISMODULE_KEYTYPE_ZSET 5 -#define REDISMODULE_KEYTYPE_MODULE 6 -#define REDISMODULE_KEYTYPE_STREAM 7 - -/* Reply types. */ -#define REDISMODULE_REPLY_UNKNOWN -1 -#define REDISMODULE_REPLY_STRING 0 -#define REDISMODULE_REPLY_ERROR 1 -#define REDISMODULE_REPLY_INTEGER 2 -#define REDISMODULE_REPLY_ARRAY 3 -#define REDISMODULE_REPLY_NULL 4 -#define REDISMODULE_REPLY_MAP 5 -#define REDISMODULE_REPLY_SET 6 -#define REDISMODULE_REPLY_BOOL 7 -#define REDISMODULE_REPLY_DOUBLE 8 -#define REDISMODULE_REPLY_BIG_NUMBER 9 -#define REDISMODULE_REPLY_VERBATIM_STRING 10 -#define REDISMODULE_REPLY_ATTRIBUTE 11 -#define REDISMODULE_REPLY_PROMISE 12 - -/* Postponed array length. */ -#define REDISMODULE_POSTPONED_ARRAY_LEN -1 /* Deprecated, please use REDISMODULE_POSTPONED_LEN */ -#define REDISMODULE_POSTPONED_LEN -1 - -/* Expire */ -#define REDISMODULE_NO_EXPIRE -1 - -/* Sorted set API flags. */ -#define REDISMODULE_ZADD_XX (1<<0) -#define REDISMODULE_ZADD_NX (1<<1) -#define REDISMODULE_ZADD_ADDED (1<<2) -#define REDISMODULE_ZADD_UPDATED (1<<3) -#define REDISMODULE_ZADD_NOP (1<<4) -#define REDISMODULE_ZADD_GT (1<<5) -#define REDISMODULE_ZADD_LT (1<<6) - -/* Hash API flags. */ -#define REDISMODULE_HASH_NONE 0 -#define REDISMODULE_HASH_NX (1<<0) -#define REDISMODULE_HASH_XX (1<<1) -#define REDISMODULE_HASH_CFIELDS (1<<2) -#define REDISMODULE_HASH_EXISTS (1<<3) -#define REDISMODULE_HASH_COUNT_ALL (1<<4) - -#define REDISMODULE_CONFIG_DEFAULT 0 /* This is the default for a module config. */ -#define REDISMODULE_CONFIG_IMMUTABLE (1ULL<<0) /* Can this value only be set at startup? */ -#define REDISMODULE_CONFIG_SENSITIVE (1ULL<<1) /* Does this value contain sensitive information */ -#define REDISMODULE_CONFIG_HIDDEN (1ULL<<4) /* This config is hidden in `config get ` (used for tests/debugging) */ -#define REDISMODULE_CONFIG_PROTECTED (1ULL<<5) /* Becomes immutable if enable-protected-configs is enabled. */ -#define REDISMODULE_CONFIG_DENY_LOADING (1ULL<<6) /* This config is forbidden during loading. */ - -#define REDISMODULE_CONFIG_MEMORY (1ULL<<7) /* Indicates if this value can be set as a memory value */ -#define REDISMODULE_CONFIG_BITFLAGS (1ULL<<8) /* Indicates if this value can be set as a multiple enum values */ - -/* StreamID type. */ -typedef struct RedisModuleStreamID { - uint64_t ms; - uint64_t seq; -} RedisModuleStreamID; - -/* StreamAdd() flags. */ -#define REDISMODULE_STREAM_ADD_AUTOID (1<<0) -/* StreamIteratorStart() flags. */ -#define REDISMODULE_STREAM_ITERATOR_EXCLUSIVE (1<<0) -#define REDISMODULE_STREAM_ITERATOR_REVERSE (1<<1) -/* StreamIteratorTrim*() flags. */ -#define REDISMODULE_STREAM_TRIM_APPROX (1<<0) - -/* Context Flags: Info about the current context returned by - * RM_GetContextFlags(). */ - -/* The command is running in the context of a Lua script */ -#define REDISMODULE_CTX_FLAGS_LUA (1<<0) -/* The command is running inside a Redis transaction */ -#define REDISMODULE_CTX_FLAGS_MULTI (1<<1) -/* The instance is a master */ -#define REDISMODULE_CTX_FLAGS_MASTER (1<<2) -/* The instance is a slave */ -#define REDISMODULE_CTX_FLAGS_SLAVE (1<<3) -/* The instance is read-only (usually meaning it's a slave as well) */ -#define REDISMODULE_CTX_FLAGS_READONLY (1<<4) -/* The instance is running in cluster mode */ -#define REDISMODULE_CTX_FLAGS_CLUSTER (1<<5) -/* The instance has AOF enabled */ -#define REDISMODULE_CTX_FLAGS_AOF (1<<6) -/* The instance has RDB enabled */ -#define REDISMODULE_CTX_FLAGS_RDB (1<<7) -/* The instance has Maxmemory set */ -#define REDISMODULE_CTX_FLAGS_MAXMEMORY (1<<8) -/* Maxmemory is set and has an eviction policy that may delete keys */ -#define REDISMODULE_CTX_FLAGS_EVICT (1<<9) -/* Redis is out of memory according to the maxmemory flag. */ -#define REDISMODULE_CTX_FLAGS_OOM (1<<10) -/* Less than 25% of memory available according to maxmemory. */ -#define REDISMODULE_CTX_FLAGS_OOM_WARNING (1<<11) -/* The command was sent over the replication link. */ -#define REDISMODULE_CTX_FLAGS_REPLICATED (1<<12) -/* Redis is currently loading either from AOF or RDB. */ -#define REDISMODULE_CTX_FLAGS_LOADING (1<<13) -/* The replica has no link with its master, note that - * there is the inverse flag as well: - * - * REDISMODULE_CTX_FLAGS_REPLICA_IS_ONLINE - * - * The two flags are exclusive, one or the other can be set. */ -#define REDISMODULE_CTX_FLAGS_REPLICA_IS_STALE (1<<14) -/* The replica is trying to connect with the master. - * (REPL_STATE_CONNECT and REPL_STATE_CONNECTING states) */ -#define REDISMODULE_CTX_FLAGS_REPLICA_IS_CONNECTING (1<<15) -/* THe replica is receiving an RDB file from its master. */ -#define REDISMODULE_CTX_FLAGS_REPLICA_IS_TRANSFERRING (1<<16) -/* The replica is online, receiving updates from its master. */ -#define REDISMODULE_CTX_FLAGS_REPLICA_IS_ONLINE (1<<17) -/* There is currently some background process active. */ -#define REDISMODULE_CTX_FLAGS_ACTIVE_CHILD (1<<18) -/* The next EXEC will fail due to dirty CAS (touched keys). */ -#define REDISMODULE_CTX_FLAGS_MULTI_DIRTY (1<<19) -/* Redis is currently running inside background child process. */ -#define REDISMODULE_CTX_FLAGS_IS_CHILD (1<<20) -/* The current client does not allow blocking, either called from - * within multi, lua, or from another module using RM_Call */ -#define REDISMODULE_CTX_FLAGS_DENY_BLOCKING (1<<21) -/* The current client uses RESP3 protocol */ -#define REDISMODULE_CTX_FLAGS_RESP3 (1<<22) -/* Redis is currently async loading database for diskless replication. */ -#define REDISMODULE_CTX_FLAGS_ASYNC_LOADING (1<<23) -/* Redis is starting. */ -#define REDISMODULE_CTX_FLAGS_SERVER_STARTUP (1<<24) - -/* Next context flag, must be updated when adding new flags above! -This flag should not be used directly by the module. - * Use RedisModule_GetContextFlagsAll instead. */ -#define _REDISMODULE_CTX_FLAGS_NEXT (1<<25) - -/* Keyspace changes notification classes. Every class is associated with a - * character for configuration purposes. - * NOTE: These have to be in sync with NOTIFY_* in server.h */ -#define REDISMODULE_NOTIFY_KEYSPACE (1<<0) /* K */ -#define REDISMODULE_NOTIFY_KEYEVENT (1<<1) /* E */ -#define REDISMODULE_NOTIFY_GENERIC (1<<2) /* g */ -#define REDISMODULE_NOTIFY_STRING (1<<3) /* $ */ -#define REDISMODULE_NOTIFY_LIST (1<<4) /* l */ -#define REDISMODULE_NOTIFY_SET (1<<5) /* s */ -#define REDISMODULE_NOTIFY_HASH (1<<6) /* h */ -#define REDISMODULE_NOTIFY_ZSET (1<<7) /* z */ -#define REDISMODULE_NOTIFY_EXPIRED (1<<8) /* x */ -#define REDISMODULE_NOTIFY_EVICTED (1<<9) /* e */ -#define REDISMODULE_NOTIFY_STREAM (1<<10) /* t */ -#define REDISMODULE_NOTIFY_KEY_MISS (1<<11) /* m (Note: This one is excluded from REDISMODULE_NOTIFY_ALL on purpose) */ -#define REDISMODULE_NOTIFY_LOADED (1<<12) /* module only key space notification, indicate a key loaded from rdb */ -#define REDISMODULE_NOTIFY_MODULE (1<<13) /* d, module key space notification */ -#define REDISMODULE_NOTIFY_NEW (1<<14) /* n, new key notification */ - -/* Next notification flag, must be updated when adding new flags above! -This flag should not be used directly by the module. - * Use RedisModule_GetKeyspaceNotificationFlagsAll instead. */ -#define _REDISMODULE_NOTIFY_NEXT (1<<15) - -#define REDISMODULE_NOTIFY_ALL (REDISMODULE_NOTIFY_GENERIC | REDISMODULE_NOTIFY_STRING | REDISMODULE_NOTIFY_LIST | REDISMODULE_NOTIFY_SET | REDISMODULE_NOTIFY_HASH | REDISMODULE_NOTIFY_ZSET | REDISMODULE_NOTIFY_EXPIRED | REDISMODULE_NOTIFY_EVICTED | REDISMODULE_NOTIFY_STREAM | REDISMODULE_NOTIFY_MODULE) /* A */ - -/* A special pointer that we can use between the core and the module to signal - * field deletion, and that is impossible to be a valid pointer. */ -#define REDISMODULE_HASH_DELETE ((RedisModuleString*)(long)1) - -/* Error messages. */ -#define REDISMODULE_ERRORMSG_WRONGTYPE "WRONGTYPE Operation against a key holding the wrong kind of value" - -#define REDISMODULE_POSITIVE_INFINITE (1.0/0.0) -#define REDISMODULE_NEGATIVE_INFINITE (-1.0/0.0) - -/* Cluster API defines. */ -#define REDISMODULE_NODE_ID_LEN 40 -#define REDISMODULE_NODE_MYSELF (1<<0) -#define REDISMODULE_NODE_MASTER (1<<1) -#define REDISMODULE_NODE_SLAVE (1<<2) -#define REDISMODULE_NODE_PFAIL (1<<3) -#define REDISMODULE_NODE_FAIL (1<<4) -#define REDISMODULE_NODE_NOFAILOVER (1<<5) - -#define REDISMODULE_CLUSTER_FLAG_NONE 0 -#define REDISMODULE_CLUSTER_FLAG_NO_FAILOVER (1<<1) -#define REDISMODULE_CLUSTER_FLAG_NO_REDIRECTION (1<<2) - -#define REDISMODULE_NOT_USED(V) ((void) V) - -/* Logging level strings */ -#define REDISMODULE_LOGLEVEL_DEBUG "debug" -#define REDISMODULE_LOGLEVEL_VERBOSE "verbose" -#define REDISMODULE_LOGLEVEL_NOTICE "notice" -#define REDISMODULE_LOGLEVEL_WARNING "warning" - -/* Bit flags for aux_save_triggers and the aux_load and aux_save callbacks */ -#define REDISMODULE_AUX_BEFORE_RDB (1<<0) -#define REDISMODULE_AUX_AFTER_RDB (1<<1) - -/* RM_Yield flags */ -#define REDISMODULE_YIELD_FLAG_NONE (1<<0) -#define REDISMODULE_YIELD_FLAG_CLIENTS (1<<1) - -/* RM_BlockClientOnKeysWithFlags flags */ -#define REDISMODULE_BLOCK_UNBLOCK_DEFAULT (0) -#define REDISMODULE_BLOCK_UNBLOCK_DELETED (1<<0) - -/* This type represents a timer handle, and is returned when a timer is - * registered and used in order to invalidate a timer. It's just a 64 bit - * number, because this is how each timer is represented inside the radix tree - * of timers that are going to expire, sorted by expire time. */ -typedef uint64_t RedisModuleTimerID; - -/* CommandFilter Flags */ - -/* Do filter RedisModule_Call() commands initiated by module itself. */ -#define REDISMODULE_CMDFILTER_NOSELF (1<<0) - -/* Declare that the module can handle errors with RedisModule_SetModuleOptions. */ -#define REDISMODULE_OPTIONS_HANDLE_IO_ERRORS (1<<0) - -/* When set, Redis will not call RedisModule_SignalModifiedKey(), implicitly in - * RedisModule_CloseKey, and the module needs to do that when manually when keys - * are modified from the user's perspective, to invalidate WATCH. */ -#define REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED (1<<1) - -/* Declare that the module can handle diskless async replication with RedisModule_SetModuleOptions. */ -#define REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD (1<<2) - -/* Declare that the module want to get nested key space notifications. - * If enabled, the module is responsible to break endless loop. */ -#define REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS (1<<3) - -/* Next option flag, must be updated when adding new module flags above! - * This flag should not be used directly by the module. - * Use RedisModule_GetModuleOptionsAll instead. */ -#define _REDISMODULE_OPTIONS_FLAGS_NEXT (1<<4) - -/* Definitions for RedisModule_SetCommandInfo. */ - -typedef enum { - REDISMODULE_ARG_TYPE_STRING, - REDISMODULE_ARG_TYPE_INTEGER, - REDISMODULE_ARG_TYPE_DOUBLE, - REDISMODULE_ARG_TYPE_KEY, /* A string, but represents a keyname */ - REDISMODULE_ARG_TYPE_PATTERN, - REDISMODULE_ARG_TYPE_UNIX_TIME, - REDISMODULE_ARG_TYPE_PURE_TOKEN, - REDISMODULE_ARG_TYPE_ONEOF, /* Must have sub-arguments */ - REDISMODULE_ARG_TYPE_BLOCK /* Must have sub-arguments */ -} RedisModuleCommandArgType; - -#define REDISMODULE_CMD_ARG_NONE (0) -#define REDISMODULE_CMD_ARG_OPTIONAL (1<<0) /* The argument is optional (like GET in SET command) */ -#define REDISMODULE_CMD_ARG_MULTIPLE (1<<1) /* The argument may repeat itself (like key in DEL) */ -#define REDISMODULE_CMD_ARG_MULTIPLE_TOKEN (1<<2) /* The argument may repeat itself, and so does its token (like `GET pattern` in SORT) */ -#define _REDISMODULE_CMD_ARG_NEXT (1<<3) - -typedef enum { - REDISMODULE_KSPEC_BS_INVALID = 0, /* Must be zero. An implicitly value of - * zero is provided when the field is - * absent in a struct literal. */ - REDISMODULE_KSPEC_BS_UNKNOWN, - REDISMODULE_KSPEC_BS_INDEX, - REDISMODULE_KSPEC_BS_KEYWORD -} RedisModuleKeySpecBeginSearchType; - -typedef enum { - REDISMODULE_KSPEC_FK_OMITTED = 0, /* Used when the field is absent in a - * struct literal. Don't use this value - * explicitly. */ - REDISMODULE_KSPEC_FK_UNKNOWN, - REDISMODULE_KSPEC_FK_RANGE, - REDISMODULE_KSPEC_FK_KEYNUM -} RedisModuleKeySpecFindKeysType; - -/* Key-spec flags. For details, see the documentation of - * RedisModule_SetCommandInfo and the key-spec flags in server.h. */ -#define REDISMODULE_CMD_KEY_RO (1ULL<<0) -#define REDISMODULE_CMD_KEY_RW (1ULL<<1) -#define REDISMODULE_CMD_KEY_OW (1ULL<<2) -#define REDISMODULE_CMD_KEY_RM (1ULL<<3) -#define REDISMODULE_CMD_KEY_ACCESS (1ULL<<4) -#define REDISMODULE_CMD_KEY_UPDATE (1ULL<<5) -#define REDISMODULE_CMD_KEY_INSERT (1ULL<<6) -#define REDISMODULE_CMD_KEY_DELETE (1ULL<<7) -#define REDISMODULE_CMD_KEY_NOT_KEY (1ULL<<8) -#define REDISMODULE_CMD_KEY_INCOMPLETE (1ULL<<9) -#define REDISMODULE_CMD_KEY_VARIABLE_FLAGS (1ULL<<10) - -/* Channel flags, for details see the documentation of - * RedisModule_ChannelAtPosWithFlags. */ -#define REDISMODULE_CMD_CHANNEL_PATTERN (1ULL<<0) -#define REDISMODULE_CMD_CHANNEL_PUBLISH (1ULL<<1) -#define REDISMODULE_CMD_CHANNEL_SUBSCRIBE (1ULL<<2) -#define REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE (1ULL<<3) - -typedef struct RedisModuleCommandArg { - const char *name; - RedisModuleCommandArgType type; - int key_spec_index; /* If type is KEY, this is a zero-based index of - * the key_spec in the command. For other types, - * you may specify -1. */ - const char *token; /* If type is PURE_TOKEN, this is the token. */ - const char *summary; - const char *since; - int flags; /* The REDISMODULE_CMD_ARG_* macros. */ - const char *deprecated_since; - struct RedisModuleCommandArg *subargs; - const char *display_text; -} RedisModuleCommandArg; - -typedef struct { - const char *since; - const char *changes; -} RedisModuleCommandHistoryEntry; - -typedef struct { - const char *notes; - uint64_t flags; /* REDISMODULE_CMD_KEY_* macros. */ - RedisModuleKeySpecBeginSearchType begin_search_type; - union { - struct { - /* The index from which we start the search for keys */ - int pos; - } index; - struct { - /* The keyword that indicates the beginning of key args */ - const char *keyword; - /* An index in argv from which to start searching. - * Can be negative, which means start search from the end, in reverse - * (Example: -2 means to start in reverse from the penultimate arg) */ - int startfrom; - } keyword; - } bs; - RedisModuleKeySpecFindKeysType find_keys_type; - union { - struct { - /* Index of the last key relative to the result of the begin search - * step. Can be negative, in which case it's not relative. -1 - * indicating till the last argument, -2 one before the last and so - * on. */ - int lastkey; - /* How many args should we skip after finding a key, in order to - * find the next one. */ - int keystep; - /* If lastkey is -1, we use limit to stop the search by a factor. 0 - * and 1 mean no limit. 2 means 1/2 of the remaining args, 3 means - * 1/3, and so on. */ - int limit; - } range; - struct { - /* Index of the argument containing the number of keys to come - * relative to the result of the begin search step */ - int keynumidx; - /* Index of the fist key. (Usually it's just after keynumidx, in - * which case it should be set to keynumidx + 1.) */ - int firstkey; - /* How many args should we skip after finding a key, in order to - * find the next one, relative to the result of the begin search - * step. */ - int keystep; - } keynum; - } fk; -} RedisModuleCommandKeySpec; - -typedef struct { - int version; - size_t sizeof_historyentry; - size_t sizeof_keyspec; - size_t sizeof_arg; -} RedisModuleCommandInfoVersion; - -static const RedisModuleCommandInfoVersion RedisModule_CurrentCommandInfoVersion = { - .version = 1, - .sizeof_historyentry = sizeof(RedisModuleCommandHistoryEntry), - .sizeof_keyspec = sizeof(RedisModuleCommandKeySpec), - .sizeof_arg = sizeof(RedisModuleCommandArg) -}; - -#define REDISMODULE_COMMAND_INFO_VERSION (&RedisModule_CurrentCommandInfoVersion) - -typedef struct { - /* Always set version to REDISMODULE_COMMAND_INFO_VERSION */ - const RedisModuleCommandInfoVersion *version; - /* Version 1 fields (added in Redis 7.0.0) */ - const char *summary; /* Summary of the command */ - const char *complexity; /* Complexity description */ - const char *since; /* Debut module version of the command */ - RedisModuleCommandHistoryEntry *history; /* History */ - /* A string of space-separated tips meant for clients/proxies regarding this - * command */ - const char *tips; - /* Number of arguments, it is possible to use -N to say >= N */ - int arity; - RedisModuleCommandKeySpec *key_specs; - RedisModuleCommandArg *args; -} RedisModuleCommandInfo; - -/* Eventloop definitions. */ -#define REDISMODULE_EVENTLOOP_READABLE 1 -#define REDISMODULE_EVENTLOOP_WRITABLE 2 -typedef void (*RedisModuleEventLoopFunc)(int fd, void *user_data, int mask); -typedef void (*RedisModuleEventLoopOneShotFunc)(void *user_data); - -/* Server events definitions. - * Those flags should not be used directly by the module, instead - * the module should use RedisModuleEvent_* variables. - * Note: This must be synced with moduleEventVersions */ -#define REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED 0 -#define REDISMODULE_EVENT_PERSISTENCE 1 -#define REDISMODULE_EVENT_FLUSHDB 2 -#define REDISMODULE_EVENT_LOADING 3 -#define REDISMODULE_EVENT_CLIENT_CHANGE 4 -#define REDISMODULE_EVENT_SHUTDOWN 5 -#define REDISMODULE_EVENT_REPLICA_CHANGE 6 -#define REDISMODULE_EVENT_MASTER_LINK_CHANGE 7 -#define REDISMODULE_EVENT_CRON_LOOP 8 -#define REDISMODULE_EVENT_MODULE_CHANGE 9 -#define REDISMODULE_EVENT_LOADING_PROGRESS 10 -#define REDISMODULE_EVENT_SWAPDB 11 -#define REDISMODULE_EVENT_REPL_BACKUP 12 /* Deprecated since Redis 7.0, not used anymore. */ -#define REDISMODULE_EVENT_FORK_CHILD 13 -#define REDISMODULE_EVENT_REPL_ASYNC_LOAD 14 -#define REDISMODULE_EVENT_EVENTLOOP 15 -#define REDISMODULE_EVENT_CONFIG 16 -#define REDISMODULE_EVENT_KEY 17 -#define _REDISMODULE_EVENT_NEXT 18 /* Next event flag, should be updated if a new event added. */ - -typedef struct RedisModuleEvent { - uint64_t id; /* REDISMODULE_EVENT_... defines. */ - uint64_t dataver; /* Version of the structure we pass as 'data'. */ -} RedisModuleEvent; - -struct RedisModuleCtx; -struct RedisModuleDefragCtx; -typedef void (*RedisModuleEventCallback)(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64_t subevent, void *data); - -/* IMPORTANT: When adding a new version of one of below structures that contain - * event data (RedisModuleFlushInfoV1 for example) we have to avoid renaming the - * old RedisModuleEvent structure. - * For example, if we want to add RedisModuleFlushInfoV2, the RedisModuleEvent - * structures should be: - * RedisModuleEvent_FlushDB = { - * REDISMODULE_EVENT_FLUSHDB, - * 1 - * }, - * RedisModuleEvent_FlushDBV2 = { - * REDISMODULE_EVENT_FLUSHDB, - * 2 - * } - * and NOT: - * RedisModuleEvent_FlushDBV1 = { - * REDISMODULE_EVENT_FLUSHDB, - * 1 - * }, - * RedisModuleEvent_FlushDB = { - * REDISMODULE_EVENT_FLUSHDB, - * 2 - * } - * The reason for that is forward-compatibility: We want that module that - * compiled with a new redismodule.h to be able to work with a old server, - * unless the author explicitly decided to use the newer event type. - */ -static const RedisModuleEvent - RedisModuleEvent_ReplicationRoleChanged = { - REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED, - 1 - }, - RedisModuleEvent_Persistence = { - REDISMODULE_EVENT_PERSISTENCE, - 1 - }, - RedisModuleEvent_FlushDB = { - REDISMODULE_EVENT_FLUSHDB, - 1 - }, - RedisModuleEvent_Loading = { - REDISMODULE_EVENT_LOADING, - 1 - }, - RedisModuleEvent_ClientChange = { - REDISMODULE_EVENT_CLIENT_CHANGE, - 1 - }, - RedisModuleEvent_Shutdown = { - REDISMODULE_EVENT_SHUTDOWN, - 1 - }, - RedisModuleEvent_ReplicaChange = { - REDISMODULE_EVENT_REPLICA_CHANGE, - 1 - }, - RedisModuleEvent_CronLoop = { - REDISMODULE_EVENT_CRON_LOOP, - 1 - }, - RedisModuleEvent_MasterLinkChange = { - REDISMODULE_EVENT_MASTER_LINK_CHANGE, - 1 - }, - RedisModuleEvent_ModuleChange = { - REDISMODULE_EVENT_MODULE_CHANGE, - 1 - }, - RedisModuleEvent_LoadingProgress = { - REDISMODULE_EVENT_LOADING_PROGRESS, - 1 - }, - RedisModuleEvent_SwapDB = { - REDISMODULE_EVENT_SWAPDB, - 1 - }, - /* Deprecated since Redis 7.0, not used anymore. */ - __attribute__ ((deprecated)) - RedisModuleEvent_ReplBackup = { - REDISMODULE_EVENT_REPL_BACKUP, - 1 - }, - RedisModuleEvent_ReplAsyncLoad = { - REDISMODULE_EVENT_REPL_ASYNC_LOAD, - 1 - }, - RedisModuleEvent_ForkChild = { - REDISMODULE_EVENT_FORK_CHILD, - 1 - }, - RedisModuleEvent_EventLoop = { - REDISMODULE_EVENT_EVENTLOOP, - 1 - }, - RedisModuleEvent_Config = { - REDISMODULE_EVENT_CONFIG, - 1 - }, - RedisModuleEvent_Key = { - REDISMODULE_EVENT_KEY, - 1 - }; - -/* Those are values that are used for the 'subevent' callback argument. */ -#define REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START 0 -#define REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START 1 -#define REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START 2 -#define REDISMODULE_SUBEVENT_PERSISTENCE_ENDED 3 -#define REDISMODULE_SUBEVENT_PERSISTENCE_FAILED 4 -#define REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START 5 -#define _REDISMODULE_SUBEVENT_PERSISTENCE_NEXT 6 - -#define REDISMODULE_SUBEVENT_LOADING_RDB_START 0 -#define REDISMODULE_SUBEVENT_LOADING_AOF_START 1 -#define REDISMODULE_SUBEVENT_LOADING_REPL_START 2 -#define REDISMODULE_SUBEVENT_LOADING_ENDED 3 -#define REDISMODULE_SUBEVENT_LOADING_FAILED 4 -#define _REDISMODULE_SUBEVENT_LOADING_NEXT 5 - -#define REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED 0 -#define REDISMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED 1 -#define _REDISMODULE_SUBEVENT_CLIENT_CHANGE_NEXT 2 - -#define REDISMODULE_SUBEVENT_MASTER_LINK_UP 0 -#define REDISMODULE_SUBEVENT_MASTER_LINK_DOWN 1 -#define _REDISMODULE_SUBEVENT_MASTER_NEXT 2 - -#define REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE 0 -#define REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE 1 -#define _REDISMODULE_SUBEVENT_REPLICA_CHANGE_NEXT 2 - -#define REDISMODULE_EVENT_REPLROLECHANGED_NOW_MASTER 0 -#define REDISMODULE_EVENT_REPLROLECHANGED_NOW_REPLICA 1 -#define _REDISMODULE_EVENT_REPLROLECHANGED_NEXT 2 - -#define REDISMODULE_SUBEVENT_FLUSHDB_START 0 -#define REDISMODULE_SUBEVENT_FLUSHDB_END 1 -#define _REDISMODULE_SUBEVENT_FLUSHDB_NEXT 2 - -#define REDISMODULE_SUBEVENT_MODULE_LOADED 0 -#define REDISMODULE_SUBEVENT_MODULE_UNLOADED 1 -#define _REDISMODULE_SUBEVENT_MODULE_NEXT 2 - -#define REDISMODULE_SUBEVENT_CONFIG_CHANGE 0 -#define _REDISMODULE_SUBEVENT_CONFIG_NEXT 1 - -#define REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB 0 -#define REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF 1 -#define _REDISMODULE_SUBEVENT_LOADING_PROGRESS_NEXT 2 - -/* Replication Backup events are deprecated since Redis 7.0 and are never fired. */ -#define REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE 0 -#define REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE 1 -#define REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD 2 -#define _REDISMODULE_SUBEVENT_REPL_BACKUP_NEXT 3 - -#define REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED 0 -#define REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED 1 -#define REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_COMPLETED 2 -#define _REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_NEXT 3 - -#define REDISMODULE_SUBEVENT_FORK_CHILD_BORN 0 -#define REDISMODULE_SUBEVENT_FORK_CHILD_DIED 1 -#define _REDISMODULE_SUBEVENT_FORK_CHILD_NEXT 2 - -#define REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP 0 -#define REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP 1 -#define _REDISMODULE_SUBEVENT_EVENTLOOP_NEXT 2 - -#define REDISMODULE_SUBEVENT_KEY_DELETED 0 -#define REDISMODULE_SUBEVENT_KEY_EXPIRED 1 -#define REDISMODULE_SUBEVENT_KEY_EVICTED 2 -#define REDISMODULE_SUBEVENT_KEY_OVERWRITTEN 3 -#define _REDISMODULE_SUBEVENT_KEY_NEXT 4 - -#define _REDISMODULE_SUBEVENT_SHUTDOWN_NEXT 0 -#define _REDISMODULE_SUBEVENT_CRON_LOOP_NEXT 0 -#define _REDISMODULE_SUBEVENT_SWAPDB_NEXT 0 - -/* RedisModuleClientInfo flags. */ -#define REDISMODULE_CLIENTINFO_FLAG_SSL (1<<0) -#define REDISMODULE_CLIENTINFO_FLAG_PUBSUB (1<<1) -#define REDISMODULE_CLIENTINFO_FLAG_BLOCKED (1<<2) -#define REDISMODULE_CLIENTINFO_FLAG_TRACKING (1<<3) -#define REDISMODULE_CLIENTINFO_FLAG_UNIXSOCKET (1<<4) -#define REDISMODULE_CLIENTINFO_FLAG_MULTI (1<<5) - -/* Here we take all the structures that the module pass to the core - * and the other way around. Notably the list here contains the structures - * used by the hooks API RedisModule_RegisterToServerEvent(). - * - * The structures always start with a 'version' field. This is useful - * when we want to pass a reference to the structure to the core APIs, - * for the APIs to fill the structure. In that case, the structure 'version' - * field is initialized before passing it to the core, so that the core is - * able to cast the pointer to the appropriate structure version. In this - * way we obtain ABI compatibility. - * - * Here we'll list all the structure versions in case they evolve over time, - * however using a define, we'll make sure to use the last version as the - * public name for the module to use. */ - -#define REDISMODULE_CLIENTINFO_VERSION 1 -typedef struct RedisModuleClientInfo { - uint64_t version; /* Version of this structure for ABI compat. */ - uint64_t flags; /* REDISMODULE_CLIENTINFO_FLAG_* */ - uint64_t id; /* Client ID. */ - char addr[46]; /* IPv4 or IPv6 address. */ - uint16_t port; /* TCP port. */ - uint16_t db; /* Selected DB. */ -} RedisModuleClientInfoV1; - -#define RedisModuleClientInfo RedisModuleClientInfoV1 - -#define REDISMODULE_CLIENTINFO_INITIALIZER_V1 { .version = 1 } - -#define REDISMODULE_REPLICATIONINFO_VERSION 1 -typedef struct RedisModuleReplicationInfo { - uint64_t version; /* Not used since this structure is never passed - from the module to the core right now. Here - for future compatibility. */ - int master; /* true if master, false if replica */ - char *masterhost; /* master instance hostname for NOW_REPLICA */ - int masterport; /* master instance port for NOW_REPLICA */ - char *replid1; /* Main replication ID */ - char *replid2; /* Secondary replication ID */ - uint64_t repl1_offset; /* Main replication offset */ - uint64_t repl2_offset; /* Offset of replid2 validity */ -} RedisModuleReplicationInfoV1; - -#define RedisModuleReplicationInfo RedisModuleReplicationInfoV1 - -#define REDISMODULE_FLUSHINFO_VERSION 1 -typedef struct RedisModuleFlushInfo { - uint64_t version; /* Not used since this structure is never passed - from the module to the core right now. Here - for future compatibility. */ - int32_t sync; /* Synchronous or threaded flush?. */ - int32_t dbnum; /* Flushed database number, -1 for ALL. */ -} RedisModuleFlushInfoV1; - -#define RedisModuleFlushInfo RedisModuleFlushInfoV1 - -#define REDISMODULE_MODULE_CHANGE_VERSION 1 -typedef struct RedisModuleModuleChange { - uint64_t version; /* Not used since this structure is never passed - from the module to the core right now. Here - for future compatibility. */ - const char* module_name;/* Name of module loaded or unloaded. */ - int32_t module_version; /* Module version. */ -} RedisModuleModuleChangeV1; - -#define RedisModuleModuleChange RedisModuleModuleChangeV1 - -#define REDISMODULE_CONFIGCHANGE_VERSION 1 -typedef struct RedisModuleConfigChange { - uint64_t version; /* Not used since this structure is never passed - from the module to the core right now. Here - for future compatibility. */ - uint32_t num_changes; /* how many redis config options were changed */ - const char **config_names; /* the config names that were changed */ -} RedisModuleConfigChangeV1; - -#define RedisModuleConfigChange RedisModuleConfigChangeV1 - -#define REDISMODULE_CRON_LOOP_VERSION 1 -typedef struct RedisModuleCronLoopInfo { - uint64_t version; /* Not used since this structure is never passed - from the module to the core right now. Here - for future compatibility. */ - int32_t hz; /* Approximate number of events per second. */ -} RedisModuleCronLoopV1; - -#define RedisModuleCronLoop RedisModuleCronLoopV1 - -#define REDISMODULE_LOADING_PROGRESS_VERSION 1 -typedef struct RedisModuleLoadingProgressInfo { - uint64_t version; /* Not used since this structure is never passed - from the module to the core right now. Here - for future compatibility. */ - int32_t hz; /* Approximate number of events per second. */ - int32_t progress; /* Approximate progress between 0 and 1024, or -1 - * if unknown. */ -} RedisModuleLoadingProgressV1; - -#define RedisModuleLoadingProgress RedisModuleLoadingProgressV1 - -#define REDISMODULE_SWAPDBINFO_VERSION 1 -typedef struct RedisModuleSwapDbInfo { - uint64_t version; /* Not used since this structure is never passed - from the module to the core right now. Here - for future compatibility. */ - int32_t dbnum_first; /* Swap Db first dbnum */ - int32_t dbnum_second; /* Swap Db second dbnum */ -} RedisModuleSwapDbInfoV1; - -#define RedisModuleSwapDbInfo RedisModuleSwapDbInfoV1 - -#define REDISMODULE_KEYINFO_VERSION 1 -typedef struct RedisModuleKeyInfo { - uint64_t version; /* Not used since this structure is never passed - from the module to the core right now. Here - for future compatibility. */ - RedisModuleKey *key; /* Opened key. */ -} RedisModuleKeyInfoV1; - -#define RedisModuleKeyInfo RedisModuleKeyInfoV1 - -typedef enum { - REDISMODULE_ACL_LOG_AUTH = 0, /* Authentication failure */ - REDISMODULE_ACL_LOG_CMD, /* Command authorization failure */ - REDISMODULE_ACL_LOG_KEY, /* Key authorization failure */ - REDISMODULE_ACL_LOG_CHANNEL /* Channel authorization failure */ -} RedisModuleACLLogEntryReason; - -/* Incomplete structures needed by both the core and modules. */ -typedef struct RedisModuleIO RedisModuleIO; -typedef struct RedisModuleDigest RedisModuleDigest; -typedef struct RedisModuleInfoCtx RedisModuleInfoCtx; -typedef struct RedisModuleDefragCtx RedisModuleDefragCtx; - -/* Function pointers needed by both the core and modules, these needs to be - * exposed since you can't cast a function pointer to (void *). */ -typedef void (*RedisModuleInfoFunc)(RedisModuleInfoCtx *ctx, int for_crash_report); -typedef void (*RedisModuleDefragFunc)(RedisModuleDefragCtx *ctx); -typedef void (*RedisModuleUserChangedFunc) (uint64_t client_id, void *privdata); - -/* ------------------------- End of common defines ------------------------ */ - -/* ----------- The rest of the defines are only for modules ----------------- */ -#if !defined REDISMODULE_CORE || defined REDISMODULE_CORE_MODULE -/* Things defined for modules and core-modules. */ - -/* Macro definitions specific to individual compilers */ -#ifndef REDISMODULE_ATTR_UNUSED -# ifdef __GNUC__ -# define REDISMODULE_ATTR_UNUSED __attribute__((unused)) -# else -# define REDISMODULE_ATTR_UNUSED -# endif -#endif - -#ifndef REDISMODULE_ATTR_PRINTF -# ifdef __GNUC__ -# define REDISMODULE_ATTR_PRINTF(idx,cnt) __attribute__((format(printf,idx,cnt))) -# else -# define REDISMODULE_ATTR_PRINTF(idx,cnt) -# endif -#endif - -#ifndef REDISMODULE_ATTR_COMMON -# if defined(__GNUC__) && !(defined(__clang__) && defined(__cplusplus)) -# define REDISMODULE_ATTR_COMMON __attribute__((__common__)) -# else -# define REDISMODULE_ATTR_COMMON -# endif -#endif - -/* Incomplete structures for compiler checks but opaque access. */ -typedef struct RedisModuleCtx RedisModuleCtx; -typedef struct RedisModuleCommand RedisModuleCommand; -typedef struct RedisModuleCallReply RedisModuleCallReply; -typedef struct RedisModuleType RedisModuleType; -typedef struct RedisModuleBlockedClient RedisModuleBlockedClient; -typedef struct RedisModuleClusterInfo RedisModuleClusterInfo; -typedef struct RedisModuleDict RedisModuleDict; -typedef struct RedisModuleDictIter RedisModuleDictIter; -typedef struct RedisModuleCommandFilterCtx RedisModuleCommandFilterCtx; -typedef struct RedisModuleCommandFilter RedisModuleCommandFilter; -typedef struct RedisModuleServerInfoData RedisModuleServerInfoData; -typedef struct RedisModuleScanCursor RedisModuleScanCursor; -typedef struct RedisModuleUser RedisModuleUser; -typedef struct RedisModuleKeyOptCtx RedisModuleKeyOptCtx; -typedef struct RedisModuleRdbStream RedisModuleRdbStream; - -typedef int (*RedisModuleCmdFunc)(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); -typedef void (*RedisModuleDisconnectFunc)(RedisModuleCtx *ctx, RedisModuleBlockedClient *bc); -typedef int (*RedisModuleNotificationFunc)(RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key); -typedef void (*RedisModulePostNotificationJobFunc) (RedisModuleCtx *ctx, void *pd); -typedef void *(*RedisModuleTypeLoadFunc)(RedisModuleIO *rdb, int encver); -typedef void (*RedisModuleTypeSaveFunc)(RedisModuleIO *rdb, void *value); -typedef int (*RedisModuleTypeAuxLoadFunc)(RedisModuleIO *rdb, int encver, int when); -typedef void (*RedisModuleTypeAuxSaveFunc)(RedisModuleIO *rdb, int when); -typedef void (*RedisModuleTypeRewriteFunc)(RedisModuleIO *aof, RedisModuleString *key, void *value); -typedef size_t (*RedisModuleTypeMemUsageFunc)(const void *value); -typedef size_t (*RedisModuleTypeMemUsageFunc2)(RedisModuleKeyOptCtx *ctx, const void *value, size_t sample_size); -typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value); -typedef void (*RedisModuleTypeFreeFunc)(void *value); -typedef size_t (*RedisModuleTypeFreeEffortFunc)(RedisModuleString *key, const void *value); -typedef size_t (*RedisModuleTypeFreeEffortFunc2)(RedisModuleKeyOptCtx *ctx, const void *value); -typedef void (*RedisModuleTypeUnlinkFunc)(RedisModuleString *key, const void *value); -typedef void (*RedisModuleTypeUnlinkFunc2)(RedisModuleKeyOptCtx *ctx, const void *value); -typedef void *(*RedisModuleTypeCopyFunc)(RedisModuleString *fromkey, RedisModuleString *tokey, const void *value); -typedef void *(*RedisModuleTypeCopyFunc2)(RedisModuleKeyOptCtx *ctx, const void *value); -typedef int (*RedisModuleTypeDefragFunc)(RedisModuleDefragCtx *ctx, RedisModuleString *key, void **value); -typedef void (*RedisModuleClusterMessageReceiver)(RedisModuleCtx *ctx, const char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len); -typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data); -typedef void (*RedisModuleCommandFilterFunc) (RedisModuleCommandFilterCtx *filter); -typedef void (*RedisModuleForkDoneHandler) (int exitcode, int bysignal, void *user_data); -typedef void (*RedisModuleScanCB)(RedisModuleCtx *ctx, RedisModuleString *keyname, RedisModuleKey *key, void *privdata); -typedef void (*RedisModuleScanKeyCB)(RedisModuleKey *key, RedisModuleString *field, RedisModuleString *value, void *privdata); -typedef RedisModuleString * (*RedisModuleConfigGetStringFunc)(const char *name, void *privdata); -typedef long long (*RedisModuleConfigGetNumericFunc)(const char *name, void *privdata); -typedef int (*RedisModuleConfigGetBoolFunc)(const char *name, void *privdata); -typedef int (*RedisModuleConfigGetEnumFunc)(const char *name, void *privdata); -typedef int (*RedisModuleConfigSetStringFunc)(const char *name, RedisModuleString *val, void *privdata, RedisModuleString **err); -typedef int (*RedisModuleConfigSetNumericFunc)(const char *name, long long val, void *privdata, RedisModuleString **err); -typedef int (*RedisModuleConfigSetBoolFunc)(const char *name, int val, void *privdata, RedisModuleString **err); -typedef int (*RedisModuleConfigSetEnumFunc)(const char *name, int val, void *privdata, RedisModuleString **err); -typedef int (*RedisModuleConfigApplyFunc)(RedisModuleCtx *ctx, void *privdata, RedisModuleString **err); -typedef void (*RedisModuleOnUnblocked)(RedisModuleCtx *ctx, RedisModuleCallReply *reply, void *private_data); -typedef int (*RedisModuleAuthCallback)(RedisModuleCtx *ctx, RedisModuleString *username, RedisModuleString *password, RedisModuleString **err); - -typedef struct RedisModuleTypeMethods { - uint64_t version; - RedisModuleTypeLoadFunc rdb_load; - RedisModuleTypeSaveFunc rdb_save; - RedisModuleTypeRewriteFunc aof_rewrite; - RedisModuleTypeMemUsageFunc mem_usage; - RedisModuleTypeDigestFunc digest; - RedisModuleTypeFreeFunc free; - RedisModuleTypeAuxLoadFunc aux_load; - RedisModuleTypeAuxSaveFunc aux_save; - int aux_save_triggers; - RedisModuleTypeFreeEffortFunc free_effort; - RedisModuleTypeUnlinkFunc unlink; - RedisModuleTypeCopyFunc copy; - RedisModuleTypeDefragFunc defrag; - RedisModuleTypeMemUsageFunc2 mem_usage2; - RedisModuleTypeFreeEffortFunc2 free_effort2; - RedisModuleTypeUnlinkFunc2 unlink2; - RedisModuleTypeCopyFunc2 copy2; - RedisModuleTypeAuxSaveFunc aux_save2; -} RedisModuleTypeMethods; - -#define REDISMODULE_GET_API(name) \ - RedisModule_GetApi("RedisModule_" #name, ((void **)&RedisModule_ ## name)) - -/* Default API declaration prefix (not 'extern' for backwards compatibility) */ -#ifndef REDISMODULE_API -#define REDISMODULE_API -#endif - -/* Default API declaration suffix (compiler attributes) */ -#ifndef REDISMODULE_ATTR -#define REDISMODULE_ATTR REDISMODULE_ATTR_COMMON -#endif - -REDISMODULE_API void * (*RedisModule_Alloc)(size_t bytes) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_TryAlloc)(size_t bytes) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_Realloc)(void *ptr, size_t bytes) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_TryRealloc)(void *ptr, size_t bytes) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_Free)(void *ptr) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_Calloc)(size_t nmemb, size_t size) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_TryCalloc)(size_t nmemb, size_t size) REDISMODULE_ATTR; -REDISMODULE_API char * (*RedisModule_Strdup)(const char *str) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetApi)(const char *, void *) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CreateCommand)(RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCommand *(*RedisModule_GetCommand)(RedisModuleCtx *ctx, const char *name) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CreateSubcommand)(RedisModuleCommand *parent, const char *name, RedisModuleCmdFunc cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetCommandInfo)(RedisModuleCommand *command, const RedisModuleCommandInfo *info) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetCommandACLCategories)(RedisModuleCommand *command, const char *ctgrsflags) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_AddACLCategory)(RedisModuleCtx *ctx, const char *name) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SetModuleAttribs)(RedisModuleCtx *ctx, const char *name, int ver, int apiver) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_IsModuleNameBusy)(const char *name) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_WrongArity)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithLongLong)(RedisModuleCtx *ctx, long long ll) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetSelectedDb)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SelectDb)(RedisModuleCtx *ctx, int newid) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_KeyExists)(RedisModuleCtx *ctx, RedisModuleString *keyname) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleKey * (*RedisModule_OpenKey)(RedisModuleCtx *ctx, RedisModuleString *keyname, int mode) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetOpenKeyModesAll)(void) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_CloseKey)(RedisModuleKey *kp) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_KeyType)(RedisModuleKey *kp) REDISMODULE_ATTR; -REDISMODULE_API size_t (*RedisModule_ValueLength)(RedisModuleKey *kp) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ListPush)(RedisModuleKey *kp, int where, RedisModuleString *ele) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_ListPop)(RedisModuleKey *key, int where) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_ListGet)(RedisModuleKey *key, long index) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ListSet)(RedisModuleKey *key, long index, RedisModuleString *value) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ListInsert)(RedisModuleKey *key, long index, RedisModuleString *value) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ListDelete)(RedisModuleKey *key, long index) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCallReply * (*RedisModule_Call)(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) REDISMODULE_ATTR; -REDISMODULE_API const char * (*RedisModule_CallReplyProto)(RedisModuleCallReply *reply, size_t *len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_FreeCallReply)(RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CallReplyType)(RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API long long (*RedisModule_CallReplyInteger)(RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API double (*RedisModule_CallReplyDouble)(RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CallReplyBool)(RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API const char* (*RedisModule_CallReplyBigNumber)(RedisModuleCallReply *reply, size_t *len) REDISMODULE_ATTR; -REDISMODULE_API const char* (*RedisModule_CallReplyVerbatim)(RedisModuleCallReply *reply, size_t *len, const char **format) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCallReply * (*RedisModule_CallReplySetElement)(RedisModuleCallReply *reply, size_t idx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CallReplyMapElement)(RedisModuleCallReply *reply, size_t idx, RedisModuleCallReply **key, RedisModuleCallReply **val) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CallReplyAttributeElement)(RedisModuleCallReply *reply, size_t idx, RedisModuleCallReply **key, RedisModuleCallReply **val) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_CallReplyPromiseSetUnblockHandler)(RedisModuleCallReply *reply, RedisModuleOnUnblocked on_unblock, void *private_data) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CallReplyPromiseAbort)(RedisModuleCallReply *reply, void **private_data) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCallReply * (*RedisModule_CallReplyAttribute)(RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API size_t (*RedisModule_CallReplyLength)(RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCallReply * (*RedisModule_CallReplyArrayElement)(RedisModuleCallReply *reply, size_t idx) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateString)(RedisModuleCtx *ctx, const char *ptr, size_t len) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromLongLong)(RedisModuleCtx *ctx, long long ll) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromULongLong)(RedisModuleCtx *ctx, unsigned long long ull) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromDouble)(RedisModuleCtx *ctx, double d) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromLongDouble)(RedisModuleCtx *ctx, long double ld, int humanfriendly) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromString)(RedisModuleCtx *ctx, const RedisModuleString *str) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromStreamID)(RedisModuleCtx *ctx, const RedisModuleStreamID *id) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringPrintf)(RedisModuleCtx *ctx, const char *fmt, ...) REDISMODULE_ATTR_PRINTF(2,3) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_FreeString)(RedisModuleCtx *ctx, RedisModuleString *str) REDISMODULE_ATTR; -REDISMODULE_API const char * (*RedisModule_StringPtrLen)(const RedisModuleString *str, size_t *len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithError)(RedisModuleCtx *ctx, const char *err) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithErrorFormat)(RedisModuleCtx *ctx, const char *fmt, ...) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithSimpleString)(RedisModuleCtx *ctx, const char *msg) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithArray)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithMap)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithSet)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithAttribute)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithNullArray)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithEmptyArray)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ReplySetArrayLength)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ReplySetMapLength)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ReplySetSetLength)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ReplySetAttributeLength)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ReplySetPushLength)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithStringBuffer)(RedisModuleCtx *ctx, const char *buf, size_t len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithCString)(RedisModuleCtx *ctx, const char *buf) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithString)(RedisModuleCtx *ctx, RedisModuleString *str) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithEmptyString)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithVerbatimString)(RedisModuleCtx *ctx, const char *buf, size_t len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithVerbatimStringType)(RedisModuleCtx *ctx, const char *buf, size_t len, const char *ext) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithNull)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithBool)(RedisModuleCtx *ctx, int b) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithLongDouble)(RedisModuleCtx *ctx, long double d) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithDouble)(RedisModuleCtx *ctx, double d) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithBigNumber)(RedisModuleCtx *ctx, const char *bignum, size_t len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplyWithCallReply)(RedisModuleCtx *ctx, RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringToLongLong)(const RedisModuleString *str, long long *ll) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringToULongLong)(const RedisModuleString *str, unsigned long long *ull) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringToDouble)(const RedisModuleString *str, double *d) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringToLongDouble)(const RedisModuleString *str, long double *d) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringToStreamID)(const RedisModuleString *str, RedisModuleStreamID *id) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_AutoMemory)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_Replicate)(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ReplicateVerbatim)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API const char * (*RedisModule_CallReplyStringPtr)(RedisModuleCallReply *reply, size_t *len) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromCallReply)(RedisModuleCallReply *reply) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DeleteKey)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_UnlinkKey)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringSet)(RedisModuleKey *key, RedisModuleString *str) REDISMODULE_ATTR; -REDISMODULE_API char * (*RedisModule_StringDMA)(RedisModuleKey *key, size_t *len, int mode) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringTruncate)(RedisModuleKey *key, size_t newlen) REDISMODULE_ATTR; -REDISMODULE_API mstime_t (*RedisModule_GetExpire)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetExpire)(RedisModuleKey *key, mstime_t expire) REDISMODULE_ATTR; -REDISMODULE_API mstime_t (*RedisModule_GetAbsExpire)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetAbsExpire)(RedisModuleKey *key, mstime_t expire) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ResetDataset)(int restart_aof, int async) REDISMODULE_ATTR; -REDISMODULE_API unsigned long long (*RedisModule_DbSize)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_RandomKey)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetAdd)(RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetIncrby)(RedisModuleKey *key, double score, RedisModuleString *ele, int *flagsptr, double *newscore) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetScore)(RedisModuleKey *key, RedisModuleString *ele, double *score) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetRem)(RedisModuleKey *key, RedisModuleString *ele, int *deleted) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ZsetRangeStop)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetFirstInScoreRange)(RedisModuleKey *key, double min, double max, int minex, int maxex) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetLastInScoreRange)(RedisModuleKey *key, double min, double max, int minex, int maxex) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetFirstInLexRange)(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetLastInLexRange)(RedisModuleKey *key, RedisModuleString *min, RedisModuleString *max) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_ZsetRangeCurrentElement)(RedisModuleKey *key, double *score) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetRangeNext)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetRangePrev)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ZsetRangeEndReached)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_HashSet)(RedisModuleKey *key, int flags, ...) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_HashGet)(RedisModuleKey *key, int flags, ...) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StreamAdd)(RedisModuleKey *key, int flags, RedisModuleStreamID *id, RedisModuleString **argv, int64_t numfields) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StreamDelete)(RedisModuleKey *key, RedisModuleStreamID *id) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StreamIteratorStart)(RedisModuleKey *key, int flags, RedisModuleStreamID *startid, RedisModuleStreamID *endid) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StreamIteratorStop)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StreamIteratorNextID)(RedisModuleKey *key, RedisModuleStreamID *id, long *numfields) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StreamIteratorNextField)(RedisModuleKey *key, RedisModuleString **field_ptr, RedisModuleString **value_ptr) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StreamIteratorDelete)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API long long (*RedisModule_StreamTrimByLength)(RedisModuleKey *key, int flags, long long length) REDISMODULE_ATTR; -REDISMODULE_API long long (*RedisModule_StreamTrimByID)(RedisModuleKey *key, int flags, RedisModuleStreamID *id) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_IsKeysPositionRequest)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_KeyAtPos)(RedisModuleCtx *ctx, int pos) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_KeyAtPosWithFlags)(RedisModuleCtx *ctx, int pos, int flags) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_IsChannelsPositionRequest)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ChannelAtPosWithFlags)(RedisModuleCtx *ctx, int pos, int flags) REDISMODULE_ATTR; -REDISMODULE_API unsigned long long (*RedisModule_GetClientId)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_GetClientUserNameById)(RedisModuleCtx *ctx, uint64_t id) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetClientInfoById)(void *ci, uint64_t id) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_GetClientNameById)(RedisModuleCtx *ctx, uint64_t id) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetClientNameById)(uint64_t id, RedisModuleString *name) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_PublishMessage)(RedisModuleCtx *ctx, RedisModuleString *channel, RedisModuleString *message) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_PublishMessageShard)(RedisModuleCtx *ctx, RedisModuleString *channel, RedisModuleString *message) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetContextFlags)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_AvoidReplicaTraffic)(void) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_PoolAlloc)(RedisModuleCtx *ctx, size_t bytes) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleType * (*RedisModule_CreateDataType)(RedisModuleCtx *ctx, const char *name, int encver, RedisModuleTypeMethods *typemethods) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ModuleTypeSetValue)(RedisModuleKey *key, RedisModuleType *mt, void *value) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ModuleTypeReplaceValue)(RedisModuleKey *key, RedisModuleType *mt, void *new_value, void **old_value) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleType * (*RedisModule_ModuleTypeGetType)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_ModuleTypeGetValue)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_IsIOError)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SetModuleOptions)(RedisModuleCtx *ctx, int options) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SignalModifiedKey)(RedisModuleCtx *ctx, RedisModuleString *keyname) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SaveUnsigned)(RedisModuleIO *io, uint64_t value) REDISMODULE_ATTR; -REDISMODULE_API uint64_t (*RedisModule_LoadUnsigned)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SaveSigned)(RedisModuleIO *io, int64_t value) REDISMODULE_ATTR; -REDISMODULE_API int64_t (*RedisModule_LoadSigned)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_EmitAOF)(RedisModuleIO *io, const char *cmdname, const char *fmt, ...) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SaveString)(RedisModuleIO *io, RedisModuleString *s) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SaveStringBuffer)(RedisModuleIO *io, const char *str, size_t len) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_LoadString)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API char * (*RedisModule_LoadStringBuffer)(RedisModuleIO *io, size_t *lenptr) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SaveDouble)(RedisModuleIO *io, double value) REDISMODULE_ATTR; -REDISMODULE_API double (*RedisModule_LoadDouble)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SaveFloat)(RedisModuleIO *io, float value) REDISMODULE_ATTR; -REDISMODULE_API float (*RedisModule_LoadFloat)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SaveLongDouble)(RedisModuleIO *io, long double value) REDISMODULE_ATTR; -REDISMODULE_API long double (*RedisModule_LoadLongDouble)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_LoadDataTypeFromString)(const RedisModuleString *str, const RedisModuleType *mt) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_LoadDataTypeFromStringEncver)(const RedisModuleString *str, const RedisModuleType *mt, int encver) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_SaveDataTypeToString)(RedisModuleCtx *ctx, void *data, const RedisModuleType *mt) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_Log)(RedisModuleCtx *ctx, const char *level, const char *fmt, ...) REDISMODULE_ATTR REDISMODULE_ATTR_PRINTF(3,4); -REDISMODULE_API void (*RedisModule_LogIOError)(RedisModuleIO *io, const char *levelstr, const char *fmt, ...) REDISMODULE_ATTR REDISMODULE_ATTR_PRINTF(3,4); -REDISMODULE_API void (*RedisModule__Assert)(const char *estr, const char *file, int line) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_LatencyAddSample)(const char *event, mstime_t latency) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringAppendBuffer)(RedisModuleCtx *ctx, RedisModuleString *str, const char *buf, size_t len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_TrimStringAllocation)(RedisModuleString *str) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_RetainString)(RedisModuleCtx *ctx, RedisModuleString *str) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_HoldString)(RedisModuleCtx *ctx, RedisModuleString *str) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StringCompare)(const RedisModuleString *a, const RedisModuleString *b) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCtx * (*RedisModule_GetContextFromIO)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API const RedisModuleString * (*RedisModule_GetKeyNameFromIO)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API const RedisModuleString * (*RedisModule_GetKeyNameFromModuleKey)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetDbIdFromModuleKey)(RedisModuleKey *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetDbIdFromIO)(RedisModuleIO *io) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetDbIdFromOptCtx)(RedisModuleKeyOptCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetToDbIdFromOptCtx)(RedisModuleKeyOptCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API const RedisModuleString * (*RedisModule_GetKeyNameFromOptCtx)(RedisModuleKeyOptCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API const RedisModuleString * (*RedisModule_GetToKeyNameFromOptCtx)(RedisModuleKeyOptCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API mstime_t (*RedisModule_Milliseconds)(void) REDISMODULE_ATTR; -REDISMODULE_API uint64_t (*RedisModule_MonotonicMicroseconds)(void) REDISMODULE_ATTR; -REDISMODULE_API ustime_t (*RedisModule_Microseconds)(void) REDISMODULE_ATTR; -REDISMODULE_API ustime_t (*RedisModule_CachedMicroseconds)(void) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_DigestAddStringBuffer)(RedisModuleDigest *md, const char *ele, size_t len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_DigestAddLongLong)(RedisModuleDigest *md, long long ele) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_DigestEndSequence)(RedisModuleDigest *md) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetDbIdFromDigest)(RedisModuleDigest *dig) REDISMODULE_ATTR; -REDISMODULE_API const RedisModuleString * (*RedisModule_GetKeyNameFromDigest)(RedisModuleDigest *dig) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleDict * (*RedisModule_CreateDict)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_FreeDict)(RedisModuleCtx *ctx, RedisModuleDict *d) REDISMODULE_ATTR; -REDISMODULE_API uint64_t (*RedisModule_DictSize)(RedisModuleDict *d) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictSetC)(RedisModuleDict *d, void *key, size_t keylen, void *ptr) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictReplaceC)(RedisModuleDict *d, void *key, size_t keylen, void *ptr) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictSet)(RedisModuleDict *d, RedisModuleString *key, void *ptr) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictReplace)(RedisModuleDict *d, RedisModuleString *key, void *ptr) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_DictGetC)(RedisModuleDict *d, void *key, size_t keylen, int *nokey) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_DictGet)(RedisModuleDict *d, RedisModuleString *key, int *nokey) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictDelC)(RedisModuleDict *d, void *key, size_t keylen, void *oldval) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictDel)(RedisModuleDict *d, RedisModuleString *key, void *oldval) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleDictIter * (*RedisModule_DictIteratorStartC)(RedisModuleDict *d, const char *op, void *key, size_t keylen) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleDictIter * (*RedisModule_DictIteratorStart)(RedisModuleDict *d, const char *op, RedisModuleString *key) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_DictIteratorStop)(RedisModuleDictIter *di) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictIteratorReseekC)(RedisModuleDictIter *di, const char *op, void *key, size_t keylen) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictIteratorReseek)(RedisModuleDictIter *di, const char *op, RedisModuleString *key) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_DictNextC)(RedisModuleDictIter *di, size_t *keylen, void **dataptr) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_DictPrevC)(RedisModuleDictIter *di, size_t *keylen, void **dataptr) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_DictNext)(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_DictPrev)(RedisModuleCtx *ctx, RedisModuleDictIter *di, void **dataptr) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictCompareC)(RedisModuleDictIter *di, const char *op, void *key, size_t keylen) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DictCompare)(RedisModuleDictIter *di, const char *op, RedisModuleString *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RegisterInfoFunc)(RedisModuleCtx *ctx, RedisModuleInfoFunc cb) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_RegisterAuthCallback)(RedisModuleCtx *ctx, RedisModuleAuthCallback cb) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_InfoAddSection)(RedisModuleInfoCtx *ctx, const char *name) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_InfoBeginDictField)(RedisModuleInfoCtx *ctx, const char *name) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_InfoEndDictField)(RedisModuleInfoCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_InfoAddFieldString)(RedisModuleInfoCtx *ctx, const char *field, RedisModuleString *value) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_InfoAddFieldCString)(RedisModuleInfoCtx *ctx, const char *field,const char *value) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_InfoAddFieldDouble)(RedisModuleInfoCtx *ctx, const char *field, double value) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_InfoAddFieldLongLong)(RedisModuleInfoCtx *ctx, const char *field, long long value) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_InfoAddFieldULongLong)(RedisModuleInfoCtx *ctx, const char *field, unsigned long long value) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleServerInfoData * (*RedisModule_GetServerInfo)(RedisModuleCtx *ctx, const char *section) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_FreeServerInfo)(RedisModuleCtx *ctx, RedisModuleServerInfoData *data) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_ServerInfoGetField)(RedisModuleCtx *ctx, RedisModuleServerInfoData *data, const char* field) REDISMODULE_ATTR; -REDISMODULE_API const char * (*RedisModule_ServerInfoGetFieldC)(RedisModuleServerInfoData *data, const char* field) REDISMODULE_ATTR; -REDISMODULE_API long long (*RedisModule_ServerInfoGetFieldSigned)(RedisModuleServerInfoData *data, const char* field, int *out_err) REDISMODULE_ATTR; -REDISMODULE_API unsigned long long (*RedisModule_ServerInfoGetFieldUnsigned)(RedisModuleServerInfoData *data, const char* field, int *out_err) REDISMODULE_ATTR; -REDISMODULE_API double (*RedisModule_ServerInfoGetFieldDouble)(RedisModuleServerInfoData *data, const char* field, int *out_err) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SubscribeToServerEvent)(RedisModuleCtx *ctx, RedisModuleEvent event, RedisModuleEventCallback callback) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetLRU)(RedisModuleKey *key, mstime_t lru_idle) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetLRU)(RedisModuleKey *key, mstime_t *lru_idle) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetLFU)(RedisModuleKey *key, long long lfu_freq) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetLFU)(RedisModuleKey *key, long long *lfu_freq) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleBlockedClient * (*RedisModule_BlockClientOnKeys)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms, RedisModuleString **keys, int numkeys, void *privdata) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleBlockedClient * (*RedisModule_BlockClientOnKeysWithFlags)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms, RedisModuleString **keys, int numkeys, void *privdata, int flags) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SignalKeyAsReady)(RedisModuleCtx *ctx, RedisModuleString *key) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_GetBlockedClientReadyKey)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleScanCursor * (*RedisModule_ScanCursorCreate)(void) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ScanCursorRestart)(RedisModuleScanCursor *cursor) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ScanCursorDestroy)(RedisModuleScanCursor *cursor) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_Scan)(RedisModuleCtx *ctx, RedisModuleScanCursor *cursor, RedisModuleScanCB fn, void *privdata) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ScanKey)(RedisModuleKey *key, RedisModuleScanCursor *cursor, RedisModuleScanKeyCB fn, void *privdata) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetContextFlagsAll)(void) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetModuleOptionsAll)(void) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetKeyspaceNotificationFlagsAll)(void) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_IsSubEventSupported)(RedisModuleEvent event, uint64_t subevent) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetServerVersion)(void) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetTypeMethodVersion)(void) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_Yield)(RedisModuleCtx *ctx, int flags, const char *busy_reply) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleBlockedClient * (*RedisModule_BlockClient)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_BlockClientGetPrivateData)(RedisModuleBlockedClient *blocked_client) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_BlockClientSetPrivateData)(RedisModuleBlockedClient *blocked_client, void *private_data) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleBlockedClient * (*RedisModule_BlockClientOnAuth)(RedisModuleCtx *ctx, RedisModuleAuthCallback reply_callback, void (*free_privdata)(RedisModuleCtx*,void*)) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_UnblockClient)(RedisModuleBlockedClient *bc, void *privdata) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_IsBlockedReplyRequest)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_IsBlockedTimeoutRequest)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_GetBlockedClientPrivateData)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleBlockedClient * (*RedisModule_GetBlockedClientHandle)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_AbortBlock)(RedisModuleBlockedClient *bc) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_BlockedClientMeasureTimeStart)(RedisModuleBlockedClient *bc) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_BlockedClientMeasureTimeEnd)(RedisModuleBlockedClient *bc) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCtx * (*RedisModule_GetThreadSafeContext)(RedisModuleBlockedClient *bc) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCtx * (*RedisModule_GetDetachedThreadSafeContext)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_FreeThreadSafeContext)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ThreadSafeContextLock)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ThreadSafeContextTryLock)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ThreadSafeContextUnlock)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SubscribeToKeyspaceEvents)(RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc cb) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_AddPostNotificationJob)(RedisModuleCtx *ctx, RedisModulePostNotificationJobFunc callback, void *pd, void (*free_pd)(void*)) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_NotifyKeyspaceEvent)(RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetNotifyKeyspaceEvents)(void) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_BlockedClientDisconnected)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_RegisterClusterMessageReceiver)(RedisModuleCtx *ctx, uint8_t type, RedisModuleClusterMessageReceiver callback) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SendClusterMessage)(RedisModuleCtx *ctx, const char *target_id, uint8_t type, const char *msg, uint32_t len) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetClusterNodeInfo)(RedisModuleCtx *ctx, const char *id, char *ip, char *master_id, int *port, int *flags) REDISMODULE_ATTR; -REDISMODULE_API char ** (*RedisModule_GetClusterNodesList)(RedisModuleCtx *ctx, size_t *numnodes) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_FreeClusterNodesList)(char **ids) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleTimerID (*RedisModule_CreateTimer)(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_StopTimer)(RedisModuleCtx *ctx, RedisModuleTimerID id, void **data) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetTimerInfo)(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remaining, void **data) REDISMODULE_ATTR; -REDISMODULE_API const char * (*RedisModule_GetMyClusterID)(void) REDISMODULE_ATTR; -REDISMODULE_API size_t (*RedisModule_GetClusterSize)(void) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_GetRandomBytes)(unsigned char *dst, size_t len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_GetRandomHexChars)(char *dst, size_t len) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SetDisconnectCallback)(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SetClusterFlags)(RedisModuleCtx *ctx, uint64_t flags) REDISMODULE_ATTR; -REDISMODULE_API unsigned int (*RedisModule_ClusterKeySlot)(RedisModuleString *key) REDISMODULE_ATTR; -REDISMODULE_API const char *(*RedisModule_ClusterCanonicalKeyNameInSlot)(unsigned int slot) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ExportSharedAPI)(RedisModuleCtx *ctx, const char *apiname, void *func) REDISMODULE_ATTR; -REDISMODULE_API void * (*RedisModule_GetSharedAPI)(RedisModuleCtx *ctx, const char *apiname) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleCommandFilter * (*RedisModule_RegisterCommandFilter)(RedisModuleCtx *ctx, RedisModuleCommandFilterFunc cb, int flags) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_UnregisterCommandFilter)(RedisModuleCtx *ctx, RedisModuleCommandFilter *filter) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CommandFilterArgsCount)(RedisModuleCommandFilterCtx *fctx) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_CommandFilterArgGet)(RedisModuleCommandFilterCtx *fctx, int pos) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CommandFilterArgInsert)(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CommandFilterArgReplace)(RedisModuleCommandFilterCtx *fctx, int pos, RedisModuleString *arg) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_CommandFilterArgDelete)(RedisModuleCommandFilterCtx *fctx, int pos) REDISMODULE_ATTR; -REDISMODULE_API unsigned long long (*RedisModule_CommandFilterGetClientId)(RedisModuleCommandFilterCtx *fctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_Fork)(RedisModuleForkDoneHandler cb, void *user_data) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SendChildHeartbeat)(double progress) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ExitFromChild)(int retcode) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_KillForkChild)(int child_pid) REDISMODULE_ATTR; -REDISMODULE_API float (*RedisModule_GetUsedMemoryRatio)(void) REDISMODULE_ATTR; -REDISMODULE_API size_t (*RedisModule_MallocSize)(void* ptr) REDISMODULE_ATTR; -REDISMODULE_API size_t (*RedisModule_MallocUsableSize)(void *ptr) REDISMODULE_ATTR; -REDISMODULE_API size_t (*RedisModule_MallocSizeString)(RedisModuleString* str) REDISMODULE_ATTR; -REDISMODULE_API size_t (*RedisModule_MallocSizeDict)(RedisModuleDict* dict) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleUser * (*RedisModule_CreateModuleUser)(const char *name) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_FreeModuleUser)(RedisModuleUser *user) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_SetContextUser)(RedisModuleCtx *ctx, const RedisModuleUser *user) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetModuleUserACL)(RedisModuleUser *user, const char* acl) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_SetModuleUserACLString)(RedisModuleCtx * ctx, RedisModuleUser *user, const char* acl, RedisModuleString **error) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_GetModuleUserACLString)(RedisModuleUser *user) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_GetCurrentUserName)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleUser * (*RedisModule_GetModuleUserFromUserName)(RedisModuleString *name) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ACLCheckCommandPermissions)(RedisModuleUser *user, RedisModuleString **argv, int argc) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ACLCheckKeyPermissions)(RedisModuleUser *user, RedisModuleString *key, int flags) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_ACLCheckChannelPermissions)(RedisModuleUser *user, RedisModuleString *ch, int literal) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ACLAddLogEntry)(RedisModuleCtx *ctx, RedisModuleUser *user, RedisModuleString *object, RedisModuleACLLogEntryReason reason) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_ACLAddLogEntryByUserName)(RedisModuleCtx *ctx, RedisModuleString *user, RedisModuleString *object, RedisModuleACLLogEntryReason reason) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_AuthenticateClientWithACLUser)(RedisModuleCtx *ctx, const char *name, size_t len, RedisModuleUserChangedFunc callback, void *privdata, uint64_t *client_id) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_AuthenticateClientWithUser)(RedisModuleCtx *ctx, RedisModuleUser *user, RedisModuleUserChangedFunc callback, void *privdata, uint64_t *client_id) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DeauthenticateAndCloseClient)(RedisModuleCtx *ctx, uint64_t client_id) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RedactClientCommandArgument)(RedisModuleCtx *ctx, int pos) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString * (*RedisModule_GetClientCertificate)(RedisModuleCtx *ctx, uint64_t id) REDISMODULE_ATTR; -REDISMODULE_API int *(*RedisModule_GetCommandKeys)(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int *num_keys) REDISMODULE_ATTR; -REDISMODULE_API int *(*RedisModule_GetCommandKeysWithFlags)(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int *num_keys, int **out_flags) REDISMODULE_ATTR; -REDISMODULE_API const char *(*RedisModule_GetCurrentCommandName)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RegisterDefragFunc)(RedisModuleCtx *ctx, RedisModuleDefragFunc func) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RegisterDefragCallbacks)(RedisModuleCtx *ctx, RedisModuleDefragFunc start, RedisModuleDefragFunc end) REDISMODULE_ATTR; -REDISMODULE_API void *(*RedisModule_DefragAlloc)(RedisModuleDefragCtx *ctx, void *ptr) REDISMODULE_ATTR; -REDISMODULE_API void *(*RedisModule_DefragAllocRaw)(RedisModuleDefragCtx *ctx, size_t size) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_DefragFreeRaw)(RedisModuleDefragCtx *ctx, void *ptr) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleString *(*RedisModule_DefragRedisModuleString)(RedisModuleDefragCtx *ctx, RedisModuleString *str) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DefragShouldStop)(RedisModuleDefragCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DefragCursorSet)(RedisModuleDefragCtx *ctx, unsigned long cursor) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_DefragCursorGet)(RedisModuleDefragCtx *ctx, unsigned long *cursor) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_GetDbIdFromDefragCtx)(RedisModuleDefragCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API const RedisModuleString * (*RedisModule_GetKeyNameFromDefragCtx)(RedisModuleDefragCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_EventLoopAdd)(int fd, int mask, RedisModuleEventLoopFunc func, void *user_data) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_EventLoopDel)(int fd, int mask) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_EventLoopAddOneShot)(RedisModuleEventLoopOneShotFunc func, void *user_data) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RegisterBoolConfig)(RedisModuleCtx *ctx, const char *name, int default_val, unsigned int flags, RedisModuleConfigGetBoolFunc getfn, RedisModuleConfigSetBoolFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RegisterNumericConfig)(RedisModuleCtx *ctx, const char *name, long long default_val, unsigned int flags, long long min, long long max, RedisModuleConfigGetNumericFunc getfn, RedisModuleConfigSetNumericFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RegisterStringConfig)(RedisModuleCtx *ctx, const char *name, const char *default_val, unsigned int flags, RedisModuleConfigGetStringFunc getfn, RedisModuleConfigSetStringFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RegisterEnumConfig)(RedisModuleCtx *ctx, const char *name, int default_val, unsigned int flags, const char **enum_values, const int *int_values, int num_enum_vals, RedisModuleConfigGetEnumFunc getfn, RedisModuleConfigSetEnumFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_LoadConfigs)(RedisModuleCtx *ctx) REDISMODULE_ATTR; -REDISMODULE_API RedisModuleRdbStream *(*RedisModule_RdbStreamCreateFromFile)(const char *filename) REDISMODULE_ATTR; -REDISMODULE_API void (*RedisModule_RdbStreamFree)(RedisModuleRdbStream *stream) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RdbLoad)(RedisModuleCtx *ctx, RedisModuleRdbStream *stream, int flags) REDISMODULE_ATTR; -REDISMODULE_API int (*RedisModule_RdbSave)(RedisModuleCtx *ctx, RedisModuleRdbStream *stream, int flags) REDISMODULE_ATTR; - -#define RedisModule_IsAOFClient(id) ((id) == UINT64_MAX) - -/* This is included inline inside each Redis module. */ -static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) REDISMODULE_ATTR_UNUSED; -static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) { - void *getapifuncptr = ((void**)ctx)[0]; - RedisModule_GetApi = (int (*)(const char *, void *)) (unsigned long)getapifuncptr; - REDISMODULE_GET_API(Alloc); - REDISMODULE_GET_API(TryAlloc); - REDISMODULE_GET_API(Calloc); - REDISMODULE_GET_API(TryCalloc); - REDISMODULE_GET_API(Free); - REDISMODULE_GET_API(Realloc); - REDISMODULE_GET_API(TryRealloc); - REDISMODULE_GET_API(Strdup); - REDISMODULE_GET_API(CreateCommand); - REDISMODULE_GET_API(GetCommand); - REDISMODULE_GET_API(CreateSubcommand); - REDISMODULE_GET_API(SetCommandInfo); - REDISMODULE_GET_API(SetCommandACLCategories); - REDISMODULE_GET_API(AddACLCategory); - REDISMODULE_GET_API(SetModuleAttribs); - REDISMODULE_GET_API(IsModuleNameBusy); - REDISMODULE_GET_API(WrongArity); - REDISMODULE_GET_API(ReplyWithLongLong); - REDISMODULE_GET_API(ReplyWithError); - REDISMODULE_GET_API(ReplyWithErrorFormat); - REDISMODULE_GET_API(ReplyWithSimpleString); - REDISMODULE_GET_API(ReplyWithArray); - REDISMODULE_GET_API(ReplyWithMap); - REDISMODULE_GET_API(ReplyWithSet); - REDISMODULE_GET_API(ReplyWithAttribute); - REDISMODULE_GET_API(ReplyWithNullArray); - REDISMODULE_GET_API(ReplyWithEmptyArray); - REDISMODULE_GET_API(ReplySetArrayLength); - REDISMODULE_GET_API(ReplySetMapLength); - REDISMODULE_GET_API(ReplySetSetLength); - REDISMODULE_GET_API(ReplySetAttributeLength); - REDISMODULE_GET_API(ReplySetPushLength); - REDISMODULE_GET_API(ReplyWithStringBuffer); - REDISMODULE_GET_API(ReplyWithCString); - REDISMODULE_GET_API(ReplyWithString); - REDISMODULE_GET_API(ReplyWithEmptyString); - REDISMODULE_GET_API(ReplyWithVerbatimString); - REDISMODULE_GET_API(ReplyWithVerbatimStringType); - REDISMODULE_GET_API(ReplyWithNull); - REDISMODULE_GET_API(ReplyWithBool); - REDISMODULE_GET_API(ReplyWithCallReply); - REDISMODULE_GET_API(ReplyWithDouble); - REDISMODULE_GET_API(ReplyWithBigNumber); - REDISMODULE_GET_API(ReplyWithLongDouble); - REDISMODULE_GET_API(GetSelectedDb); - REDISMODULE_GET_API(SelectDb); - REDISMODULE_GET_API(KeyExists); - REDISMODULE_GET_API(OpenKey); - REDISMODULE_GET_API(GetOpenKeyModesAll); - REDISMODULE_GET_API(CloseKey); - REDISMODULE_GET_API(KeyType); - REDISMODULE_GET_API(ValueLength); - REDISMODULE_GET_API(ListPush); - REDISMODULE_GET_API(ListPop); - REDISMODULE_GET_API(ListGet); - REDISMODULE_GET_API(ListSet); - REDISMODULE_GET_API(ListInsert); - REDISMODULE_GET_API(ListDelete); - REDISMODULE_GET_API(StringToLongLong); - REDISMODULE_GET_API(StringToULongLong); - REDISMODULE_GET_API(StringToDouble); - REDISMODULE_GET_API(StringToLongDouble); - REDISMODULE_GET_API(StringToStreamID); - REDISMODULE_GET_API(Call); - REDISMODULE_GET_API(CallReplyProto); - REDISMODULE_GET_API(FreeCallReply); - REDISMODULE_GET_API(CallReplyInteger); - REDISMODULE_GET_API(CallReplyDouble); - REDISMODULE_GET_API(CallReplyBool); - REDISMODULE_GET_API(CallReplyBigNumber); - REDISMODULE_GET_API(CallReplyVerbatim); - REDISMODULE_GET_API(CallReplySetElement); - REDISMODULE_GET_API(CallReplyMapElement); - REDISMODULE_GET_API(CallReplyAttributeElement); - REDISMODULE_GET_API(CallReplyPromiseSetUnblockHandler); - REDISMODULE_GET_API(CallReplyPromiseAbort); - REDISMODULE_GET_API(CallReplyAttribute); - REDISMODULE_GET_API(CallReplyType); - REDISMODULE_GET_API(CallReplyLength); - REDISMODULE_GET_API(CallReplyArrayElement); - REDISMODULE_GET_API(CallReplyStringPtr); - REDISMODULE_GET_API(CreateStringFromCallReply); - REDISMODULE_GET_API(CreateString); - REDISMODULE_GET_API(CreateStringFromLongLong); - REDISMODULE_GET_API(CreateStringFromULongLong); - REDISMODULE_GET_API(CreateStringFromDouble); - REDISMODULE_GET_API(CreateStringFromLongDouble); - REDISMODULE_GET_API(CreateStringFromString); - REDISMODULE_GET_API(CreateStringFromStreamID); - REDISMODULE_GET_API(CreateStringPrintf); - REDISMODULE_GET_API(FreeString); - REDISMODULE_GET_API(StringPtrLen); - REDISMODULE_GET_API(AutoMemory); - REDISMODULE_GET_API(Replicate); - REDISMODULE_GET_API(ReplicateVerbatim); - REDISMODULE_GET_API(DeleteKey); - REDISMODULE_GET_API(UnlinkKey); - REDISMODULE_GET_API(StringSet); - REDISMODULE_GET_API(StringDMA); - REDISMODULE_GET_API(StringTruncate); - REDISMODULE_GET_API(GetExpire); - REDISMODULE_GET_API(SetExpire); - REDISMODULE_GET_API(GetAbsExpire); - REDISMODULE_GET_API(SetAbsExpire); - REDISMODULE_GET_API(ResetDataset); - REDISMODULE_GET_API(DbSize); - REDISMODULE_GET_API(RandomKey); - REDISMODULE_GET_API(ZsetAdd); - REDISMODULE_GET_API(ZsetIncrby); - REDISMODULE_GET_API(ZsetScore); - REDISMODULE_GET_API(ZsetRem); - REDISMODULE_GET_API(ZsetRangeStop); - REDISMODULE_GET_API(ZsetFirstInScoreRange); - REDISMODULE_GET_API(ZsetLastInScoreRange); - REDISMODULE_GET_API(ZsetFirstInLexRange); - REDISMODULE_GET_API(ZsetLastInLexRange); - REDISMODULE_GET_API(ZsetRangeCurrentElement); - REDISMODULE_GET_API(ZsetRangeNext); - REDISMODULE_GET_API(ZsetRangePrev); - REDISMODULE_GET_API(ZsetRangeEndReached); - REDISMODULE_GET_API(HashSet); - REDISMODULE_GET_API(HashGet); - REDISMODULE_GET_API(StreamAdd); - REDISMODULE_GET_API(StreamDelete); - REDISMODULE_GET_API(StreamIteratorStart); - REDISMODULE_GET_API(StreamIteratorStop); - REDISMODULE_GET_API(StreamIteratorNextID); - REDISMODULE_GET_API(StreamIteratorNextField); - REDISMODULE_GET_API(StreamIteratorDelete); - REDISMODULE_GET_API(StreamTrimByLength); - REDISMODULE_GET_API(StreamTrimByID); - REDISMODULE_GET_API(IsKeysPositionRequest); - REDISMODULE_GET_API(KeyAtPos); - REDISMODULE_GET_API(KeyAtPosWithFlags); - REDISMODULE_GET_API(IsChannelsPositionRequest); - REDISMODULE_GET_API(ChannelAtPosWithFlags); - REDISMODULE_GET_API(GetClientId); - REDISMODULE_GET_API(GetClientUserNameById); - REDISMODULE_GET_API(GetContextFlags); - REDISMODULE_GET_API(AvoidReplicaTraffic); - REDISMODULE_GET_API(PoolAlloc); - REDISMODULE_GET_API(CreateDataType); - REDISMODULE_GET_API(ModuleTypeSetValue); - REDISMODULE_GET_API(ModuleTypeReplaceValue); - REDISMODULE_GET_API(ModuleTypeGetType); - REDISMODULE_GET_API(ModuleTypeGetValue); - REDISMODULE_GET_API(IsIOError); - REDISMODULE_GET_API(SetModuleOptions); - REDISMODULE_GET_API(SignalModifiedKey); - REDISMODULE_GET_API(SaveUnsigned); - REDISMODULE_GET_API(LoadUnsigned); - REDISMODULE_GET_API(SaveSigned); - REDISMODULE_GET_API(LoadSigned); - REDISMODULE_GET_API(SaveString); - REDISMODULE_GET_API(SaveStringBuffer); - REDISMODULE_GET_API(LoadString); - REDISMODULE_GET_API(LoadStringBuffer); - REDISMODULE_GET_API(SaveDouble); - REDISMODULE_GET_API(LoadDouble); - REDISMODULE_GET_API(SaveFloat); - REDISMODULE_GET_API(LoadFloat); - REDISMODULE_GET_API(SaveLongDouble); - REDISMODULE_GET_API(LoadLongDouble); - REDISMODULE_GET_API(SaveDataTypeToString); - REDISMODULE_GET_API(LoadDataTypeFromString); - REDISMODULE_GET_API(LoadDataTypeFromStringEncver); - REDISMODULE_GET_API(EmitAOF); - REDISMODULE_GET_API(Log); - REDISMODULE_GET_API(LogIOError); - REDISMODULE_GET_API(_Assert); - REDISMODULE_GET_API(LatencyAddSample); - REDISMODULE_GET_API(StringAppendBuffer); - REDISMODULE_GET_API(TrimStringAllocation); - REDISMODULE_GET_API(RetainString); - REDISMODULE_GET_API(HoldString); - REDISMODULE_GET_API(StringCompare); - REDISMODULE_GET_API(GetContextFromIO); - REDISMODULE_GET_API(GetKeyNameFromIO); - REDISMODULE_GET_API(GetKeyNameFromModuleKey); - REDISMODULE_GET_API(GetDbIdFromModuleKey); - REDISMODULE_GET_API(GetDbIdFromIO); - REDISMODULE_GET_API(GetKeyNameFromOptCtx); - REDISMODULE_GET_API(GetToKeyNameFromOptCtx); - REDISMODULE_GET_API(GetDbIdFromOptCtx); - REDISMODULE_GET_API(GetToDbIdFromOptCtx); - REDISMODULE_GET_API(Milliseconds); - REDISMODULE_GET_API(MonotonicMicroseconds); - REDISMODULE_GET_API(Microseconds); - REDISMODULE_GET_API(CachedMicroseconds); - REDISMODULE_GET_API(DigestAddStringBuffer); - REDISMODULE_GET_API(DigestAddLongLong); - REDISMODULE_GET_API(DigestEndSequence); - REDISMODULE_GET_API(GetKeyNameFromDigest); - REDISMODULE_GET_API(GetDbIdFromDigest); - REDISMODULE_GET_API(CreateDict); - REDISMODULE_GET_API(FreeDict); - REDISMODULE_GET_API(DictSize); - REDISMODULE_GET_API(DictSetC); - REDISMODULE_GET_API(DictReplaceC); - REDISMODULE_GET_API(DictSet); - REDISMODULE_GET_API(DictReplace); - REDISMODULE_GET_API(DictGetC); - REDISMODULE_GET_API(DictGet); - REDISMODULE_GET_API(DictDelC); - REDISMODULE_GET_API(DictDel); - REDISMODULE_GET_API(DictIteratorStartC); - REDISMODULE_GET_API(DictIteratorStart); - REDISMODULE_GET_API(DictIteratorStop); - REDISMODULE_GET_API(DictIteratorReseekC); - REDISMODULE_GET_API(DictIteratorReseek); - REDISMODULE_GET_API(DictNextC); - REDISMODULE_GET_API(DictPrevC); - REDISMODULE_GET_API(DictNext); - REDISMODULE_GET_API(DictPrev); - REDISMODULE_GET_API(DictCompare); - REDISMODULE_GET_API(DictCompareC); - REDISMODULE_GET_API(RegisterInfoFunc); - REDISMODULE_GET_API(RegisterAuthCallback); - REDISMODULE_GET_API(InfoAddSection); - REDISMODULE_GET_API(InfoBeginDictField); - REDISMODULE_GET_API(InfoEndDictField); - REDISMODULE_GET_API(InfoAddFieldString); - REDISMODULE_GET_API(InfoAddFieldCString); - REDISMODULE_GET_API(InfoAddFieldDouble); - REDISMODULE_GET_API(InfoAddFieldLongLong); - REDISMODULE_GET_API(InfoAddFieldULongLong); - REDISMODULE_GET_API(GetServerInfo); - REDISMODULE_GET_API(FreeServerInfo); - REDISMODULE_GET_API(ServerInfoGetField); - REDISMODULE_GET_API(ServerInfoGetFieldC); - REDISMODULE_GET_API(ServerInfoGetFieldSigned); - REDISMODULE_GET_API(ServerInfoGetFieldUnsigned); - REDISMODULE_GET_API(ServerInfoGetFieldDouble); - REDISMODULE_GET_API(GetClientInfoById); - REDISMODULE_GET_API(GetClientNameById); - REDISMODULE_GET_API(SetClientNameById); - REDISMODULE_GET_API(PublishMessage); - REDISMODULE_GET_API(PublishMessageShard); - REDISMODULE_GET_API(SubscribeToServerEvent); - REDISMODULE_GET_API(SetLRU); - REDISMODULE_GET_API(GetLRU); - REDISMODULE_GET_API(SetLFU); - REDISMODULE_GET_API(GetLFU); - REDISMODULE_GET_API(BlockClientOnKeys); - REDISMODULE_GET_API(BlockClientOnKeysWithFlags); - REDISMODULE_GET_API(SignalKeyAsReady); - REDISMODULE_GET_API(GetBlockedClientReadyKey); - REDISMODULE_GET_API(ScanCursorCreate); - REDISMODULE_GET_API(ScanCursorRestart); - REDISMODULE_GET_API(ScanCursorDestroy); - REDISMODULE_GET_API(Scan); - REDISMODULE_GET_API(ScanKey); - REDISMODULE_GET_API(GetContextFlagsAll); - REDISMODULE_GET_API(GetModuleOptionsAll); - REDISMODULE_GET_API(GetKeyspaceNotificationFlagsAll); - REDISMODULE_GET_API(IsSubEventSupported); - REDISMODULE_GET_API(GetServerVersion); - REDISMODULE_GET_API(GetTypeMethodVersion); - REDISMODULE_GET_API(Yield); - REDISMODULE_GET_API(GetThreadSafeContext); - REDISMODULE_GET_API(GetDetachedThreadSafeContext); - REDISMODULE_GET_API(FreeThreadSafeContext); - REDISMODULE_GET_API(ThreadSafeContextLock); - REDISMODULE_GET_API(ThreadSafeContextTryLock); - REDISMODULE_GET_API(ThreadSafeContextUnlock); - REDISMODULE_GET_API(BlockClient); - REDISMODULE_GET_API(BlockClientGetPrivateData); - REDISMODULE_GET_API(BlockClientSetPrivateData); - REDISMODULE_GET_API(BlockClientOnAuth); - REDISMODULE_GET_API(UnblockClient); - REDISMODULE_GET_API(IsBlockedReplyRequest); - REDISMODULE_GET_API(IsBlockedTimeoutRequest); - REDISMODULE_GET_API(GetBlockedClientPrivateData); - REDISMODULE_GET_API(GetBlockedClientHandle); - REDISMODULE_GET_API(AbortBlock); - REDISMODULE_GET_API(BlockedClientMeasureTimeStart); - REDISMODULE_GET_API(BlockedClientMeasureTimeEnd); - REDISMODULE_GET_API(SetDisconnectCallback); - REDISMODULE_GET_API(SubscribeToKeyspaceEvents); - REDISMODULE_GET_API(AddPostNotificationJob); - REDISMODULE_GET_API(NotifyKeyspaceEvent); - REDISMODULE_GET_API(GetNotifyKeyspaceEvents); - REDISMODULE_GET_API(BlockedClientDisconnected); - REDISMODULE_GET_API(RegisterClusterMessageReceiver); - REDISMODULE_GET_API(SendClusterMessage); - REDISMODULE_GET_API(GetClusterNodeInfo); - REDISMODULE_GET_API(GetClusterNodesList); - REDISMODULE_GET_API(FreeClusterNodesList); - REDISMODULE_GET_API(CreateTimer); - REDISMODULE_GET_API(StopTimer); - REDISMODULE_GET_API(GetTimerInfo); - REDISMODULE_GET_API(GetMyClusterID); - REDISMODULE_GET_API(GetClusterSize); - REDISMODULE_GET_API(GetRandomBytes); - REDISMODULE_GET_API(GetRandomHexChars); - REDISMODULE_GET_API(SetClusterFlags); - REDISMODULE_GET_API(ClusterKeySlot); - REDISMODULE_GET_API(ClusterCanonicalKeyNameInSlot); - REDISMODULE_GET_API(ExportSharedAPI); - REDISMODULE_GET_API(GetSharedAPI); - REDISMODULE_GET_API(RegisterCommandFilter); - REDISMODULE_GET_API(UnregisterCommandFilter); - REDISMODULE_GET_API(CommandFilterArgsCount); - REDISMODULE_GET_API(CommandFilterArgGet); - REDISMODULE_GET_API(CommandFilterArgInsert); - REDISMODULE_GET_API(CommandFilterArgReplace); - REDISMODULE_GET_API(CommandFilterArgDelete); - REDISMODULE_GET_API(CommandFilterGetClientId); - REDISMODULE_GET_API(Fork); - REDISMODULE_GET_API(SendChildHeartbeat); - REDISMODULE_GET_API(ExitFromChild); - REDISMODULE_GET_API(KillForkChild); - REDISMODULE_GET_API(GetUsedMemoryRatio); - REDISMODULE_GET_API(MallocSize); - REDISMODULE_GET_API(MallocUsableSize); - REDISMODULE_GET_API(MallocSizeString); - REDISMODULE_GET_API(MallocSizeDict); - REDISMODULE_GET_API(CreateModuleUser); - REDISMODULE_GET_API(FreeModuleUser); - REDISMODULE_GET_API(SetContextUser); - REDISMODULE_GET_API(SetModuleUserACL); - REDISMODULE_GET_API(SetModuleUserACLString); - REDISMODULE_GET_API(GetModuleUserACLString); - REDISMODULE_GET_API(GetCurrentUserName); - REDISMODULE_GET_API(GetModuleUserFromUserName); - REDISMODULE_GET_API(ACLCheckCommandPermissions); - REDISMODULE_GET_API(ACLCheckKeyPermissions); - REDISMODULE_GET_API(ACLCheckChannelPermissions); - REDISMODULE_GET_API(ACLAddLogEntry); - REDISMODULE_GET_API(ACLAddLogEntryByUserName); - REDISMODULE_GET_API(DeauthenticateAndCloseClient); - REDISMODULE_GET_API(AuthenticateClientWithACLUser); - REDISMODULE_GET_API(AuthenticateClientWithUser); - REDISMODULE_GET_API(RedactClientCommandArgument); - REDISMODULE_GET_API(GetClientCertificate); - REDISMODULE_GET_API(GetCommandKeys); - REDISMODULE_GET_API(GetCommandKeysWithFlags); - REDISMODULE_GET_API(GetCurrentCommandName); - REDISMODULE_GET_API(RegisterDefragFunc); - REDISMODULE_GET_API(RegisterDefragCallbacks); - REDISMODULE_GET_API(DefragAlloc); - REDISMODULE_GET_API(DefragAllocRaw); - REDISMODULE_GET_API(DefragFreeRaw); - REDISMODULE_GET_API(DefragRedisModuleString); - REDISMODULE_GET_API(DefragShouldStop); - REDISMODULE_GET_API(DefragCursorSet); - REDISMODULE_GET_API(DefragCursorGet); - REDISMODULE_GET_API(GetKeyNameFromDefragCtx); - REDISMODULE_GET_API(GetDbIdFromDefragCtx); - REDISMODULE_GET_API(EventLoopAdd); - REDISMODULE_GET_API(EventLoopDel); - REDISMODULE_GET_API(EventLoopAddOneShot); - REDISMODULE_GET_API(RegisterBoolConfig); - REDISMODULE_GET_API(RegisterNumericConfig); - REDISMODULE_GET_API(RegisterStringConfig); - REDISMODULE_GET_API(RegisterEnumConfig); - REDISMODULE_GET_API(LoadConfigs); - REDISMODULE_GET_API(RdbStreamCreateFromFile); - REDISMODULE_GET_API(RdbStreamFree); - REDISMODULE_GET_API(RdbLoad); - REDISMODULE_GET_API(RdbSave); - - if (RedisModule_IsModuleNameBusy && RedisModule_IsModuleNameBusy(name)) return REDISMODULE_ERR; - RedisModule_SetModuleAttribs(ctx,name,ver,apiver); - return REDISMODULE_OK; -} - -#define RedisModule_Assert(_e) ((_e)?(void)0 : (RedisModule__Assert(#_e,__FILE__,__LINE__),exit(1))) - -#define RMAPI_FUNC_SUPPORTED(func) (func != NULL) - -#endif /* REDISMODULE_CORE */ -#endif /* REDISMODULE_H */ diff --git a/modules/vector-sets/test.py b/modules/vector-sets/test.py index 2e38ba013..7d9f0c1fc 100755 --- a/modules/vector-sets/test.py +++ b/modules/vector-sets/test.py @@ -2,8 +2,13 @@ # # Vector set tests. # A Redis instance should be running in the default port. -# Copyright(C) 2024-2025 Salvatore Sanfilippo. -# All Rights Reserved. +# +# Copyright (c) 2009-Present, Redis Ltd. +# All rights reserved. +# +# Licensed under your choice of the Redis Source Available License 2.0 +# (RSALv2) or the Server Side Public License v1 (SSPLv1). +# #!/usr/bin/env python3 import redis diff --git a/modules/vector-sets/vset.c b/modules/vector-sets/vset.c index c83a4a485..f98753535 100644 --- a/modules/vector-sets/vset.c +++ b/modules/vector-sets/vset.c @@ -1,7 +1,11 @@ /* Redis implementation for vector sets. The data structure itself * is implemented in hnsw.c. * - * Copyright(C) 2024-Present, Redis Ltd. All Rights Reserved. + * Copyright (c) 2009-Present, Redis Ltd. + * All rights reserved. + * + * Licensed under your choice of the Redis Source Available License 2.0 + * (RSALv2) or the Server Side Public License v1 (SSPLv1). * Originally authored by: Salvatore Sanfilippo. * * ======================== Understand threading model ========================= @@ -35,7 +39,7 @@ * the lock and immediately releases it, with the effect of waiting all the * background threads still running from ending their execution. * - * Note that no ther thread can be spawned, since we only call + * Note that no thread can be spawned, since we only call * vectorSetWaitAllBackgroundClients() from the main Redis thread, that * is also the only thread spawning other threads. * @@ -66,7 +70,7 @@ * time in vectorSetWaitAllBackgroundClients(). This prevents removal * of objects that are about to be taken by threads. * - * Note that other competing soltuions could be used to fix the problem + * Note that other competing solutions could be used to fix the problem * but have their set of issues, however they are worth documenting here * and evaluating in the future: * @@ -100,7 +104,7 @@ #define _USE_MATH_DEFINES #define _POSIX_C_SOURCE 200809L -#include "redismodule.h" +#include "../../src/redismodule.h" #include #include #include @@ -178,7 +182,7 @@ static inline uint32_t bit_count(uint32_t n) { * Note that compared to other approaches (random gaussian weights), what * we have here is deterministic, it means that our replicas will have * the same set of weights. Also this approach seems to work much better - * in pratice, and the distances between elements are better guaranteed. + * in practice, and the distances between elements are better guaranteed. * * Note that we still save the projection matrix in the RDB file, because * in the future we may change the weights generation, and we want everything @@ -315,7 +319,7 @@ int vectorSetInsert(struct vsetObject *o, float *vec, int8_t *qvec, float qrange RedisModule_DictReplace(o->dict,val,node); /* If attrib != NULL, the user wants that in case of an update we - * update the attribute as well (otherwise it reamins as it was). + * update the attribute as well (otherwise it remains as it was). * Note that the order of operations is conceinved so that it * works in case the old attrib and the new attrib pointer is the * same. */ @@ -371,7 +375,7 @@ int vectorSetInsert(struct vsetObject *o, float *vec, int8_t *qvec, float qrange float *parseVector(RedisModuleString **argv, int argc, int start_idx, size_t *dim, uint32_t *reduce_dim, int *consumed_args) { - int consumed = 0; // Argumnets consumed. + int consumed = 0; // Arguments consumed /* Check for REDUCE option first. */ if (reduce_dim) *reduce_dim = 0; @@ -504,7 +508,7 @@ int VADD_CASReply(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { /* Also, if the element was already inserted, we just pretend * the other insert won. We don't even start a threaded VADD - * if this was an udpate, since the deletion of the element itself + * if this was an update, since the deletion of the element itself * in order to perform the update would invalidate the CAS state. */ if (vset && RedisModule_DictGet(vset->dict,val,NULL) != NULL) vset = NULL; @@ -540,7 +544,7 @@ int VADD_CASReply(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { } RedisModule_DictSet(vset->dict,val,newnode); val = NULL; // Don't free it later. - attrib = NULL; // Dont' free it later. + attrib = NULL; // Don't free it later. RedisModule_ReplicateVerbatim(ctx); } @@ -648,7 +652,7 @@ int VADD_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { cas = 0; /* Do synchronous insert at creation, otherwise the * key would be left empty until the threaded part * does not return. It's also pointless to try try - * doing threaded first elemetn insertion. */ + * doing threaded first element insertion. */ vset = createVectorSetObject(reduce_dim ? reduce_dim : dim, quant_type, hnsw_create_M); if (vset == NULL) { // We can't fail for OOM in Redis, but the mutex initialization @@ -729,7 +733,7 @@ int VADD_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { } /* For existing keys don't do CAS updates. For how things work now, the - * CAS state would be invalidated by the detetion before adding back. */ + * CAS state would be invalidated by the deletion before adding back. */ if (cas && RedisModule_DictGet(vset->dict,val,NULL) != NULL) cas = 0; @@ -1072,7 +1076,7 @@ int VSIM_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (filter_ef == 0) filter_ef = count * 100; // Max filter visited nodes. /* Disable threaded for MULTI/EXEC and Lua, or if explicitly - * requsted by the user via the NOTHREAD option. */ + * requested by the user via the NOTHREAD option. */ if (no_thread || (RedisModule_GetContextFlags(ctx) & (REDISMODULE_CTX_FLAGS_LUA| REDISMODULE_CTX_FLAGS_MULTI))) @@ -1910,6 +1914,9 @@ int ONLOAD(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (RedisModule_Init(ctx,"vectorset",1,REDISMODULE_APIVER_1) == REDISMODULE_ERR) return REDISMODULE_ERR; + /* TODO: Added to pass CI, need to make changes in order to support these options */ + RedisModule_SetModuleOptions(ctx, REDISMODULE_OPTIONS_HANDLE_IO_ERRORS|REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD); + RedisModuleTypeMethods tm = { .version = REDISMODULE_TYPE_METHOD_VERSION, .rdb_load = VectorSetRdbLoad, @@ -1972,3 +1979,7 @@ int ONLOAD(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { return REDISMODULE_OK; } + +int VectorSets_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + return RedisModule_OnLoad(ctx, argv, argc); +} diff --git a/modules/vector-sets/w2v.c b/modules/vector-sets/w2v.c index 8d7614d2e..3a8ef054c 100644 --- a/modules/vector-sets/w2v.c +++ b/modules/vector-sets/w2v.c @@ -2,7 +2,11 @@ * HNSW (Hierarchical Navigable Small World) Implementation * Based on the paper by Yu. A. Malkov, D. A. Yashunin * - * Copyright(C) 2024-Present, Redis Ltd. All Rights Reserved. + * Copyright (c) 2009-Present, Redis Ltd. + * All rights reserved. + * + * Licensed under your choice of the Redis Source Available License 2.0 + * (RSALv2) or the Server Side Public License v1 (SSPLv1). * Originally authored by: Salvatore Sanfilippo */ diff --git a/redis-full.conf b/redis-full.conf new file mode 100644 index 000000000..5b58a30bb --- /dev/null +++ b/redis-full.conf @@ -0,0 +1,376 @@ +include redis.conf + +loadmodule ./modules/redisbloom/redisbloom.so +loadmodule ./modules/redisearch/redisearch.so +loadmodule ./modules/redisjson/rejson.so +loadmodule ./modules/redistimeseries/redistimeseries.so + +############################## QUERY ENGINE CONFIG ############################ + +# Keep numeric ranges in numeric tree parent nodes of leafs for `x` generations. +# numeric, valid range: [0, 2], default: 0 +# +# search-_numeric-ranges-parents 0 + +# The number of iterations to run while performing background indexing +# before we call usleep(1) (sleep for 1 micro-second) and make sure that we +# allow redis to process other commands. +# numeric, valid range: [1, UINT32_MAX], default: 100 +# +# search-bg-index-sleep-gap 100 + +# The default dialect used in search queries. +# numeric, valid range: [1, 4], default: 1 +# +# search-default-dialect 1 + +# the fork gc will only start to clean when the number of not cleaned document +# will exceed this threshold. +# numeric, valid range: [1, LLONG_MAX], default: 100 +# +# search-fork-gc-clean-threshold 100 + +# interval (in seconds) in which to retry running the forkgc after failure. +# numeric, valid range: [1, LLONG_MAX], default: 5 +# +# search-fork-gc-retry-interval 5 + +# interval (in seconds) in which to run the fork gc (relevant only when fork +# gc is used). +# numeric, valid range: [1, LLONG_MAX], default: 30 +# +# search-fork-gc-run-interval 30 + +# the amount of seconds for the fork GC to sleep before exiting. +# numeric, valid range: [0, LLONG_MAX], default: 0 +# +# search-fork-gc-sleep-before-exit 0 + +# Scan this many documents at a time during every GC iteration. +# numeric, valid range: [1, LLONG_MAX], default: 100 +# +# search-gc-scan-size 100 + +# Max number of cursors for a given index that can be opened inside of a shard. +# numeric, valid range: [0, LLONG_MAX], default: 128 +# +# search-index-cursor-limit 128 + +# Maximum number of results from ft.aggregate command. +# numeric, valid range: [0, (1ULL << 31)], default: 1ULL << 31 +# +# search-max-aggregate-results 2147483648 + +# Maximum prefix expansions to be used in a query. +# numeric, valid range: [1, LLONG_MAX], default: 200 +# +# search-max-prefix-expansions 200 + +# Maximum runtime document table size (for this process). +# numeric, valid range: [1, 100000000], default: 1000000 +# +# search-max-doctablesize 1000000 + +# max idle time allowed to be set for cursor, setting it high might cause +# high memory consumption. +# numeric, valid range: [1, LLONG_MAX], default: 300000 +# +# search-cursor-max-idle 300000 + +# Maximum number of results from ft.search command. +# numeric, valid range: [0, 1ULL << 31], default: 1000000 +# +# search-max-search-results 1000000 + +# Number of worker threads to use for background tasks when the server is +# in an operation event. +# numeric, valid range: [1, 16], default: 4 +# +# search-min-operation-workers 4 + +# Minimum length of term to be considered for phonetic matching. +# numeric, valid range: [1, LLONG_MAX], default: 3 +# +# search-min-phonetic-term-len 3 + +# the minimum prefix for expansions (`*`). +# numeric, valid range: [1, LLONG_MAX], default: 2 +# +# search-min-prefix 2 + +# the minimum word length to stem. +# numeric, valid range: [2, UINT32_MAX], default: 4 +# +# search-min-stem-len 4 + +# Delta used to increase positional offsets between array +# slots for multi text values. +# Can control the level of separation between phrases in different +# array slots (related to the SLOP parameter of ft.search command)" +# numeric, valid range: [1, UINT32_MAX], default: 100 +# +# search-multi-text-slop 100 + +# Used for setting the buffer limit threshold for vector similarity tiered +# HNSW index, so that if we are using WORKERS for indexing, and the +# number of vectors waiting in the buffer to be indexed exceeds this limit, +# we insert new vectors directly into HNSW. +# numeric, valid range: [0, LLONG_MAX], default: 1024 +# +# search-tiered-hnsw-buffer-limit 1024 + +# Query timeout. +# numeric, valid range: [1, LLONG_MAX], default: 500 +# +# search-timeout 500 + +# minimum number of iterators in a union from which the iterator will +# will switch to heap-based implementation. +# numeric, valid range: [1, LLONG_MAX], default: 20 +# switch to heap based implementation. +# +# search-union-iterator-heap 20 + +# The maximum memory resize for vector similarity indexes (in bytes). +# numeric, valid range: [0, UINT32_MAX], default: 0 +# +# search-vss-max-resize 0 + +# Number of worker threads to use for query processing and background tasks. +# numeric, valid range: [0, 16], default: 0 +# This configuration also affects the number of connections per shard. +# +# search-workers 0 + +# The number of high priority tasks to be executed at any given time by the +# worker thread pool, before executing low priority tasks. After this number +# of high priority tasks are being executed, the worker thread pool will +# execute high and low priority tasks alternately. +# numeric, valid range: [0, LLONG_MAX], default: 1 +# +# search-workers-priority-bias-threshold 1 + +# Load extension scoring/expansion module. Immutable. +# string, default: "" +# +# search-ext-load "" + +# Path to Chinese dictionary configuration file (for Chinese tokenization). Immutable. +# string, default: "" +# +# search-friso-ini "" + +# Action to perform when search timeout is exceeded (choose RETURN or FAIL). +# enum, valid values: ["return", "fail"], default: "fail" +# +# search-on-timeout fail + +# Determine whether some index resources are free on a second thread. +# bool, default: yes +# +# search-_free-resource-on-thread yes + +# Enable legacy compression of double to float. +# bool, default: no +# +# search-_numeric-compress no + +# Disable print of time for ft.profile. For testing only. +# bool, default: yes +# +# search-_print-profile-clock yes + +# Intersection iterator orders the children iterators by their relative estimated +# number of results in ascending order, so that if we see first iterators with +# a lower count of results we will skip a larger number of results, which +# translates into faster iteration. If this flag is set, we use this +# optimization in a way where union iterators are being factorize by the number +# of their own children, so that we sort by the number of children times the +# overall estimated number of results instead. +# bool, default: no +# +# search-_prioritize-intersect-union-children no + +# Set to run without memory pools. +# bool, default: no +# +# search-no-mem-pools no + +# Disable garbage collection (for this process). +# bool, default: no +# +# search-no-gc no + +# Enable commands filter which optimize indexing on partial hash updates. +# bool, default: no +# +# search-partial-indexed-docs no + +# Disable compression for DocID inverted index. Boost CPU performance. +# bool, default: no +# +# search-raw-docid-encoding no + +# Number of search threads in the coordinator thread pool. +# numeric, valid range: [1, LLONG_MAX], default: 20 +# +# search-threads 20 + +# Timeout for topology validation (in milliseconds). After this timeout, +# any pending requests will be processed, even if the topology is not fully connected. +# numeric, valid range: [0, LLONG_MAX], default: 30000 +# +# search-topology-validation-timeout 30000 + + +############################## TIME SERIES CONFIG ############################# + +# The maximal number of per-shard threads for cross-key queries when using cluster mode +# (TS.MRANGE, TS.MREVRANGE, TS.MGET, and TS.QUERYINDEX). +# Note: increasing this value may either increase or decrease the performance. +# integer, valid range: [1..16], default: 3 +# This is a load-time configuration parameter. +# +# ts-num-threads 3 + + +# Default compaction rules for newly created key with TS.ADD, TS.INCRBY, and TS.DECRBY. +# Has no effect on keys created with TS.CREATE. +# This default value is applied to each new time series upon its creation. +# string, see documentation for rules format, default: no compaction rules +# +# ts-compaction-policy "" + +# Default chunk encoding for automatically-created compacted time series. +# This default value is applied to each new compacted time series automatically +# created when ts-compaction-policy is specified. +# valid values: COMPRESSED, UNCOMPRESSED, default: COMPRESSED +# +# ts-encoding COMPRESSED + + +# Default retention period, in milliseconds. 0 means no expiration. +# This default value is applied to each new time series upon its creation. +# If ts-compaction-policy is specified - it is overridden for created +# compactions as specified in ts-compaction-policy. +# integer, valid range: [0 .. LLONG_MAX], default: 0 +# +# ts-retention-policy 0 + +# Default policy for handling insertion (TS.ADD and TS.MADD) of multiple +# samples with identical timestamps. +# This default value is applied to each new time series upon its creation. +# string, valid values: BLOCK, FIRST, LAST, MIN, MAX, SUM, default: BLOCK +# +# ts-duplicate-policy BLOCK + +# Default initial allocation size, in bytes, for the data part of each new chunk +# This default value is applied to each new time series upon its creation. +# integer, valid range: [48 .. 1048576]; must be a multiple of 8, default: 4096 +# +# ts-chunk-size-bytes 4096 + +# Default values for newly created time series. +# Many sensors report data periodically. Often, the difference between the measured +# value and the previous measured value is negligible and related to random noise +# or to measurement accuracy limitations. In such situations it may be preferable +# not to add the new measurement to the time series. +# A new sample is considered a duplicate and is ignored if the following conditions are met: +# - The time series is not a compaction; +# - The time series' DUPLICATE_POLICY IS LAST; +# - The sample is added in-order (timestamp >= max_timestamp); +# - The difference of the current timestamp from the previous timestamp +# (timestamp - max_timestamp) is less than or equal to ts-ignore-max-time-diff +# - The absolute value difference of the current value from the value at the previous maximum timestamp +# (abs(value - value_at_max_timestamp) is less than or equal to ts-ignore-max-val-diff. +# where max_timestamp is the timestamp of the sample with the largest timestamp in the time series, +# and value_at_max_timestamp is the value at max_timestamp. +# ts-ignore-max-time-diff: integer, valid range: [0 .. LLONG_MAX], default: 0 +# ts-ignore-max-val-diff: double, Valid range: [0 .. DBL_MAX], default: 0 +# +# ts-ignore-max-time-diff 0 +# ts-ignore-max-val-diff 0 + + +########################### BLOOM FILTERS CONFIG ############################## + +# Defaults values for new Bloom filters created with BF.ADD, BF.MADD, BF.INSERT, and BF.RESERVE +# These defaults are applied to each new Bloom filter upon its creation. + +# Error ratio +# The desired probability for false positives. +# For a false positive rate of 0.1% (1 in 1000) - the value should be 0.001. +# double, Valid range: (0 .. 1), value greater than 0.25 is treated as 0.25, default: 0.01 +# +# bf-error-rate 0.01 + +# Initial capacity +# The number of entries intended to be added to the filter. +# integer, valid range: [1 .. 1GB], default: 100 +# +# bf-initial-size 100 + +# Expansion factor +# When capacity is reached, an additional sub-filter is created. +# The size of the new sub-filter is the size of the last sub-filter multiplied +# by expansion. +# integer, [0 .. 32768]. 0 is equivalent to NONSCALING. default: 2 +# +# bf-expansion-factor 2 + + +########################### CUCKOO FILTERS CONFIG ############################# + +# Defaults values for new Cuckoo filters created with +# CF.ADD, CF.ADDNX, CF.INSERT, CF.INSERTNX, and CF.RESERVE +# These defaults are applied to each new Cuckoo filter upon its creation. + +# Initial capacity +# A filter will likely not fill up to 100% of its capacity. +# Make sure to reserve extra capacity if you want to avoid expansions. +# value is rounded to the next 2^n integer. +# integer, valid range: [2*cf-bucket-size .. 1GB], default: 1024 +# +# cf-initial-size 1024 + +# Number of items in each bucket +# The minimal false positive rate is 2/255 ~ 0.78% when bucket size of 1 is used. +# Larger buckets increase the error rate linearly, but improve the fill rate. +# integer, valid range: [1 .. 255], default: 2 +# +# cf-bucket-size 2 + +# Maximum iterations +# Number of attempts to swap items between buckets before declaring filter +# as full and creating an additional filter. +# A lower value improves performance. A higher value improves fill rate. +# integer, Valid range: [1 .. 65535], default: 20 +# +# cf-max-iterations 20 + +# Expansion factor +# When a new filter is created, its size is the size of the current filter +# multiplied by this factor. +# integer, Valid range: [0 .. 32768], 0 is equivalent to NONSCALING, default: 1 +# +# cf-expansion-factor 1 + +# Maximum expansions +# integer, Valid range: [1 .. 65536], default: 32 +# +# cf-max-expansions 32 + + +################################## SECURITY ################################### +# +# The following is a list of command categories and their meanings: +# +# * search - Query engine related. +# * json - Data type: JSON related. +# * timeseries - Data type: time series related. +# * bloom - Data type: Bloom filter related. +# * cuckoo - Data type: cuckoo filter related. +# * topk - Data type: top-k related. +# * cms - Data type: count-min sketch related. +# * tdigest - Data type: t-digest related. + diff --git a/src/Makefile b/src/Makefile index 0eb2cf41b..c4a8a79ff 100644 --- a/src/Makefile +++ b/src/Makefile @@ -52,6 +52,7 @@ endif WARN=-Wall -W -Wno-missing-field-initializers -Werror=deprecated-declarations -Wstrict-prototypes OPT=$(OPTIMIZATION) +SKIP_VEC_SETS?=no # Detect if the compiler supports C11 _Atomic. # NUMBER_SIGN_CHAR is a workaround to support both GNU Make 4.3 and older versions. NUMBER_SIGN_CHAR := \# @@ -61,6 +62,7 @@ C11_ATOMIC := $(shell sh -c 'echo "$(NUMBER_SIGN_CHAR)include " > f ifeq ($(C11_ATOMIC),yes) STD+=-std=gnu11 else + SKIP_VEC_SETS=yes STD+=-std=c99 endif @@ -352,6 +354,13 @@ else GEN_COMMANDS_FLAGS= endif + +ifneq ($(SKIP_VEC_SETS),yes) + vpath %.c ../modules/vector-sets + REDIS_VEC_SETS_OBJ=hnsw.o cJSON.o vset.o + CFLAGS+=-DINCLUDE_VEC_SETS=1 +endif + REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX) REDIS_SENTINEL_NAME=redis-sentinel$(PROG_SUFFIX) REDIS_SERVER_OBJ=threads_mngr.o adlist.o quicklist.o ae.o anet.o dict.o ebuckets.o eventnotifier.o iothread.o mstr.o kvstore.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o cluster_legacy.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crccombine.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o strl.o connection.o unix.o logreqres.o @@ -361,7 +370,7 @@ REDIS_BENCHMARK_NAME=redis-benchmark$(PROG_SUFFIX) REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o redisassert.o release.o crcspeed.o crccombine.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o strl.o REDIS_CHECK_RDB_NAME=redis-check-rdb$(PROG_SUFFIX) REDIS_CHECK_AOF_NAME=redis-check-aof$(PROG_SUFFIX) -ALL_SOURCES=$(sort $(patsubst %.o,%.c,$(REDIS_SERVER_OBJ) $(REDIS_CLI_OBJ) $(REDIS_BENCHMARK_OBJ))) +ALL_SOURCES=$(sort $(patsubst %.o,%.c,$(REDIS_SERVER_OBJ) $(REDIS_VEC_SETS_OBJ) $(REDIS_CLI_OBJ) $(REDIS_BENCHMARK_OBJ))) all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) $(TLS_MODULE) @echo "" @@ -408,7 +417,7 @@ ifneq ($(strip $(PREV_FINAL_LDFLAGS)), $(strip $(FINAL_LDFLAGS))) endif # redis-server -$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ) +$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ) $(REDIS_VEC_SETS_OBJ) $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a ../deps/fast_float/libfast_float.a $(FINAL_LIBS) # redis-sentinel @@ -435,7 +444,7 @@ $(REDIS_CLI_NAME): $(REDIS_CLI_OBJ) $(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ) $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/hdr_histogram/libhdrhistogram.a $(FINAL_LIBS) $(TLS_CLIENT_LIBS) -DEP = $(REDIS_SERVER_OBJ:%.o=%.d) $(REDIS_CLI_OBJ:%.o=%.d) $(REDIS_BENCHMARK_OBJ:%.o=%.d) +DEP = $(REDIS_SERVER_OBJ:%.o=%.d) $(REDIS_VEC_SETS_OBJ:%.o=%.d) $(REDIS_CLI_OBJ:%.o=%.d) $(REDIS_BENCHMARK_OBJ:%.o=%.d) -include $(DEP) # Because the jemalloc.h header is generated as a part of the jemalloc build, @@ -502,7 +511,7 @@ bench: $(REDIS_BENCHMARK_NAME) @echo "" @echo "WARNING: if it fails under Linux you probably need to install libc6-dev-i386" @echo "" - $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" + $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" SKIP_VEC_SETS="yes" gcov: $(MAKE) REDIS_CFLAGS="-fprofile-arcs -ftest-coverage -DCOVERAGE_TEST" REDIS_LDFLAGS="-fprofile-arcs -ftest-coverage" diff --git a/src/config.c b/src/config.c index c10971846..3f833e939 100644 --- a/src/config.c +++ b/src/config.c @@ -1578,6 +1578,9 @@ void rewriteConfigLoadmoduleOption(struct rewriteConfigState *state) { dictEntry *de; while ((de = dictNext(di)) != NULL) { struct RedisModule *module = dictGetVal(de); + /* Internal modules doesn't have path and are not part of the configuration file */ + if (sdslen(module->loadmod->path) == 0) continue; + line = sdsnew("loadmodule "); line = sdscatsds(line, module->loadmod->path); for (int i = 0; i < module->loadmod->argc; i++) { diff --git a/src/module.c b/src/module.c index 406ada1bc..e0e568041 100644 --- a/src/module.c +++ b/src/module.c @@ -12249,6 +12249,15 @@ void moduleRemoveCateogires(RedisModule *module) { } } +int VectorSets_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); +/* Load internal data types that bundled as modules */ +void moduleLoadInternalModules(void) { +#ifdef INCLUDE_VEC_SETS + int retval = moduleOnLoad((int (*)(void *, void **, int)) VectorSets_OnLoad, NULL, NULL, NULL, 0, 0); + serverAssert(retval == C_OK); +#endif +} + /* Load all the modules in the server.loadmodule_queue list, which is * populated by `loadmodule` directives in the configuration file. * We can't load modules directly when processing the configuration file @@ -12448,7 +12457,7 @@ void moduleUnregisterCleanup(RedisModule *module) { moduleUnregisterAuthCBs(module); } -/* Load a module and initialize it. On success C_OK is returned, otherwise +/* Load a module by path and initialize it. On success C_OK is returned, otherwise * C_ERR is returned. */ int moduleLoad(const char *path, void **module_argv, int module_argc, int is_loadex) { int (*onload)(void *, void **, int); @@ -12476,6 +12485,13 @@ int moduleLoad(const char *path, void **module_argv, int module_argc, int is_loa "symbol. Module not loaded.",path); return C_ERR; } + + return moduleOnLoad(onload, path, handle, module_argv, module_argc, is_loadex); +} + +/* Load a module by its 'onload' callback and initialize it. On success C_OK is returned, otherwise + * C_ERR is returned. */ +int moduleOnLoad(int (*onload)(void *, void **, int), const char *path, void *handle, void **module_argv, int module_argc, int is_loadex) { RedisModuleCtx ctx; moduleCreateContext(&ctx, NULL, REDISMODULE_CTX_TEMP_CLIENT); /* We pass NULL since we don't have a module yet. */ if (onload((void*)&ctx,module_argv,module_argc) == REDISMODULE_ERR) { @@ -12487,7 +12503,7 @@ int moduleLoad(const char *path, void **module_argv, int module_argc, int is_loa moduleFreeModuleStructure(ctx.module); } moduleFreeContext(&ctx); - dlclose(handle); + if (handle) dlclose(handle); return C_ERR; } @@ -12504,12 +12520,12 @@ int moduleLoad(const char *path, void **module_argv, int module_argc, int is_loa incrRefCount(ctx.module->loadmod->argv[i]); } - /* If module commands have ACL categories, recompute command bits + /* If module commands have ACL categories, recompute command bits * for all existing users once the modules has been registered. */ if (ctx.module->num_commands_with_acl_categories) { ACLRecomputeCommandBitsFromCommandRulesAllUsers(); } - serverLog(LL_NOTICE,"Module '%s' loaded from %s",ctx.module->name,path); + if (path) serverLog(LL_NOTICE,"Module '%s' loaded from %s",ctx.module->name,path); ctx.module->onload = 0; int post_load_err = 0; @@ -12550,6 +12566,9 @@ int moduleUnload(sds name, const char **errmsg, int forced_unload) { if (module == NULL) { *errmsg = "no such module with that name"; return C_ERR; + } else if (sdslen(module->loadmod->path) == 0) { + *errmsg = "the module can't be unloaded"; + return C_ERR; } else if (listLength(module->types) && !forced_unload) { *errmsg = "the module exports one or more module-side data " "types, can't unload"; diff --git a/src/server.c b/src/server.c index b1f8ed1a4..bd9f35705 100644 --- a/src/server.c +++ b/src/server.c @@ -7490,6 +7490,7 @@ int main(int argc, char **argv) { } if (!server.sentinel_mode) { moduleInitModulesSystemLast(); + moduleLoadInternalModules(); moduleLoadFromQueue(); } ACLLoadUsersAtStartup(); diff --git a/src/server.h b/src/server.h index 1411f37c5..61012a1f9 100644 --- a/src/server.h +++ b/src/server.h @@ -2662,8 +2662,10 @@ void populateCommandLegacyRangeSpec(struct redisCommand *c); void moduleInitModulesSystem(void); void moduleInitModulesSystemLast(void); void modulesCron(void); +int moduleOnLoad(int (*onload)(void *, void **, int), const char *path, void *handle, void **module_argv, int module_argc, int is_loadex); int moduleLoad(const char *path, void **argv, int argc, int is_loadex); int moduleUnload(sds name, const char **errmsg, int forced_unload); +void moduleLoadInternalModules(void); void moduleLoadFromQueue(void); int moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, getKeysResult *result); int moduleGetCommandChannelsViaAPI(struct redisCommand *cmd, robj **argv, int argc, getKeysResult *result); diff --git a/utils/req-res-log-validator.py b/utils/req-res-log-validator.py index 46c110019..d4c387c63 100755 --- a/utils/req-res-log-validator.py +++ b/utils/req-res-log-validator.py @@ -58,6 +58,18 @@ IGNORED_COMMANDS = { # Commands to which we decided not write a reply schema "pfdebug", "lolwut", + # TODO: for vector-sets module + "VADD", + "VCARD", + "VDIM", + "VEMB", + "VGETATTR", + "VINFO", + "VLINKS", + "VRANDMEMBER", + "VREM", + "VSETATTR", + "VSIM", } class Request(object):