diff options
author | Huang Zhw <huang_zhw@126.com> | 2022-11-30 17:56:36 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-30 11:56:36 +0200 |
commit | c81813148b71cd4be686402ef69f628f67dbb8c4 (patch) | |
tree | 54a5f6bc0701c97db66cb1cebe85fecfa3181429 /src/redismodule.h | |
parent | 7dfd7b9197bbe216912049eebecbda3f1684925e (diff) | |
download | redis-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.h | 63 |
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; |