summaryrefslogtreecommitdiff
path: root/src/redismodule.h
diff options
context:
space:
mode:
authorHuang Zhw <huang_zhw@126.com>2022-11-30 17:56:36 +0800
committerGitHub <noreply@github.com>2022-11-30 11:56:36 +0200
commitc81813148b71cd4be686402ef69f628f67dbb8c4 (patch)
tree54a5f6bc0701c97db66cb1cebe85fecfa3181429 /src/redismodule.h
parent7dfd7b9197bbe216912049eebecbda3f1684925e (diff)
downloadredis-c81813148b71cd4be686402ef69f628f67dbb8c4.tar.gz
Add a special notification unlink available only for modules (#9406)
Add a new module event `RedisModule_Event_Key`, this event is fired when a key is removed from the keyspace. The event includes an open key that can be used for reading the key before it is removed. Modules can also extract the key-name, and use RM_Open or RM_Call to access key from within that event, but shouldn't modify anything from within this event. The following sub events are available: - `REDISMODULE_SUBEVENT_KEY_DELETED` - `REDISMODULE_SUBEVENT_KEY_EXPIRED` - `REDISMODULE_SUBEVENT_KEY_EVICTED` - `REDISMODULE_SUBEVENT_KEY_OVERWRITE` The data pointer can be casted to a RedisModuleKeyInfo structure with the following fields: ``` RedisModuleKey *key; // Opened Key ``` ### internals * We also add two dict functions: `dictTwoPhaseUnlinkFind` finds an element from the table, also get the plink of the entry. The entry is returned if the element is found. The user should later call `dictTwoPhaseUnlinkFree` with it in order to unlink and release it. Otherwise if the key is not found, NULL is returned. These two functions should be used in pair. `dictTwoPhaseUnlinkFind` pauses rehash and `dictTwoPhaseUnlinkFree` resumes rehash. * We change `dbOverwrite` to `dbReplaceValue` which just replaces the value of the key and doesn't fire any events. The "overwrite" part (which emits events) is just when called from `setKey`, the other places that called dbOverwrite were ones that just update the value in-place (INCR*, SPOP, and dbUnshareStringValue). This should not have any real impact since `moduleNotifyKeyUnlink` and `signalDeletedKeyAsReady` wouldn't have mattered in these cases anyway (i.e. module keys and stream keys didn't have direct calls to dbOverwrite) * since we allow doing RM_OpenKey from withing these callbacks, we temporarily disable lazy expiry. * We also temporarily disable lazy expiry when we are in unlink/unlink2 callback and keyspace notification callback. * Move special definitions to the top of redismodule.h This is needed to resolve compilation errors with RedisModuleKeyInfoV1 that carries a RedisModuleKey member. Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'src/redismodule.h')
-rw-r--r--src/redismodule.h63
1 files changed, 44 insertions, 19 deletions
diff --git a/src/redismodule.h b/src/redismodule.h
index 7f04f7ba4..d65687a23 100644
--- a/src/redismodule.h
+++ b/src/redismodule.h
@@ -6,6 +6,28 @@
#include <stdio.h>
#include <stdlib.h>
+
+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. */
@@ -458,7 +480,8 @@ typedef void (*RedisModuleEventLoopOneShotFunc)(void *user_data);
#define REDISMODULE_EVENT_REPL_ASYNC_LOAD 14
#define REDISMODULE_EVENT_EVENTLOOP 15
#define REDISMODULE_EVENT_CONFIG 16
-#define _REDISMODULE_EVENT_NEXT 17 /* Next event flag, should be updated if a new event added. */
+#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. */
@@ -565,6 +588,10 @@ static const RedisModuleEvent
RedisModuleEvent_Config = {
REDISMODULE_EVENT_CONFIG,
1
+ },
+ RedisModuleEvent_Key = {
+ REDISMODULE_EVENT_KEY,
+ 1
};
/* Those are values that are used for the 'subevent' callback argument. */
@@ -633,6 +660,12 @@ static const RedisModuleEvent
#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
@@ -756,6 +789,16 @@ typedef struct RedisModuleSwapDbInfo {
#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 */
@@ -764,7 +807,6 @@ typedef enum {
} RedisModuleACLLogEntryReason;
/* Incomplete structures needed by both the core and modules. */
-typedef struct RedisModuleString RedisModuleString;
typedef struct RedisModuleIO RedisModuleIO;
typedef struct RedisModuleDigest RedisModuleDigest;
typedef struct RedisModuleInfoCtx RedisModuleInfoCtx;
@@ -778,22 +820,6 @@ typedef void (*RedisModuleUserChangedFunc) (uint64_t client_id, void *privdata);
/* ------------------------- End of common defines ------------------------ */
-#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 */
-
/* ----------- The rest of the defines are only for modules ----------------- */
#if !defined REDISMODULE_CORE || defined REDISMODULE_CORE_MODULE
/* Things defined for modules and core-modules. */
@@ -826,7 +852,6 @@ typedef long long ustime_t;
/* Incomplete structures for compiler checks but opaque access. */
typedef struct RedisModuleCtx RedisModuleCtx;
typedef struct RedisModuleCommand RedisModuleCommand;
-typedef struct RedisModuleKey RedisModuleKey;
typedef struct RedisModuleCallReply RedisModuleCallReply;
typedef struct RedisModuleType RedisModuleType;
typedef struct RedisModuleBlockedClient RedisModuleBlockedClient;