mirror of
http://github.com/valkey-io/valkey
synced 2024-11-23 11:51:01 +00:00
Modules hooks: event firing logic.
This commit is contained in:
parent
6e56f513b4
commit
b9af7e24e4
89
src/module.c
89
src/module.c
@ -1553,19 +1553,22 @@ unsigned long long RM_GetClientId(RedisModuleCtx *ctx) {
|
|||||||
* fields depending on the version provided. If the version is not valid
|
* fields depending on the version provided. If the version is not valid
|
||||||
* then REDISMODULE_ERR is returned. Otherwise the function returns
|
* then REDISMODULE_ERR is returned. Otherwise the function returns
|
||||||
* REDISMODULE_OK and the structure pointed by 'ci' gets populated. */
|
* REDISMODULE_OK and the structure pointed by 'ci' gets populated. */
|
||||||
|
|
||||||
|
/* Note that we may have multiple versions of the client info structure,
|
||||||
|
* as the API evolves. */
|
||||||
|
struct moduleClientInfoV1 {
|
||||||
|
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. */
|
||||||
|
};
|
||||||
|
|
||||||
int modulePopulateClientInfoStructure(void *ci, client *client, int structver) {
|
int modulePopulateClientInfoStructure(void *ci, client *client, int structver) {
|
||||||
if (structver != 1) return REDISMODULE_ERR;
|
if (structver != 1) return REDISMODULE_ERR;
|
||||||
|
|
||||||
struct {
|
struct moduleClientInfoV1 *ci1 = ci;
|
||||||
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. */
|
|
||||||
} *ci1;
|
|
||||||
|
|
||||||
ci1 = ci;
|
|
||||||
memset(ci1,0,sizeof(*ci1));
|
memset(ci1,0,sizeof(*ci1));
|
||||||
ci1->version = structver;
|
ci1->version = structver;
|
||||||
if (client->flags & CLIENT_MULTI)
|
if (client->flags & CLIENT_MULTI)
|
||||||
@ -5685,6 +5688,40 @@ void ModuleForkDoneHandler(int exitcode, int bysignal) {
|
|||||||
* will be unsubscribed. If there was a previous subscription and the callback
|
* will be unsubscribed. If there was a previous subscription and the callback
|
||||||
* is not null, the old callback will be replaced with the new one.
|
* is not null, the old callback will be replaced with the new one.
|
||||||
*
|
*
|
||||||
|
* The callback must be of this type:
|
||||||
|
*
|
||||||
|
* int (*RedisModuleEventCallback)(RedisModuleCtx *ctx,
|
||||||
|
* RedisModuleEvent eid,
|
||||||
|
* uint64_t subevent,
|
||||||
|
* void *data);
|
||||||
|
*
|
||||||
|
* The 'ctx' is a normal Redis module context that the callback can use in
|
||||||
|
* order to call other modules APIs. The 'eid' is the event itself, this
|
||||||
|
* is only useful in the case the module subscribed to multiple events: using
|
||||||
|
* the 'id' field of this structure it is possible to check if the event
|
||||||
|
* is one of the events we registered with this callback. The 'subevent' field
|
||||||
|
* depends on the event that fired. Here is a list of sub events:
|
||||||
|
*
|
||||||
|
* REDISMODULE_EVENT_PERSISTENCE_RDB_START
|
||||||
|
* REDISMODULE_EVENT_PERSISTENCE_RDB_END
|
||||||
|
* REDISMODULE_EVENT_PERSISTENCE_AOF_START
|
||||||
|
* REDISMODULE_EVENT_PERSISTENCE_AOF_END
|
||||||
|
* REDISMODULE_EVENT_LOADING_START
|
||||||
|
* REDISMODULE_EVENT_LOADING_END
|
||||||
|
* REDISMODULE_EVENT_CLIENT_CHANGE_CONNECTED
|
||||||
|
* REDISMODULE_EVENT_CLIENT_CHANGE_DISCONNECTED
|
||||||
|
* REDISMODULE_EVENT_MASTER_LINK_UP
|
||||||
|
* REDISMODULE_EVENT_MASTER_LINK_DOWN
|
||||||
|
* REDISMODULE_EVENT_REPLICA_CHANGE_CONNECTED
|
||||||
|
* REDISMODULE_EVENT_REPLICA_CHANGE_DISCONNECTED
|
||||||
|
*
|
||||||
|
* Finally the 'data' pointer may be populated, only for certain events, with
|
||||||
|
* more relevant data.
|
||||||
|
*
|
||||||
|
* In the case of REDISMODULE_EVENT_CLIENT_CHANGE events it gets populated
|
||||||
|
* with a RedisModuleClientInfo structure: the module should just cast the
|
||||||
|
* void pointer to the structure and access its fields.
|
||||||
|
*
|
||||||
* The function returns REDISMODULE_OK if the module was successfully subscrived
|
* The function returns REDISMODULE_OK if the module was successfully subscrived
|
||||||
* for the specified event. If the API is called from a wrong context then
|
* for the specified event. If the API is called from a wrong context then
|
||||||
* REDISMODULE_ERR is returned. */
|
* REDISMODULE_ERR is returned. */
|
||||||
@ -5722,6 +5759,38 @@ int RedisModule_SubscribeToServerEvent(RedisModuleCtx *ctx, RedisModuleEvent eve
|
|||||||
return REDISMODULE_OK;
|
return REDISMODULE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is called by the Redis internals every time we want to fire an
|
||||||
|
* event that can be interceppted by some module. The pointer 'data' is useful
|
||||||
|
* in order to populate the event-specific structure when needed, in order
|
||||||
|
* to return the structure with more information to the callback.
|
||||||
|
*
|
||||||
|
* 'eid' and 'subid' are just the main event ID and the sub event associated
|
||||||
|
* with the event, depending on what exactly happened. */
|
||||||
|
void RedisModule_FireServerEvent(uint64_t eid, int subid, void *data) {
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(RedisModule_EventListeners,&li);
|
||||||
|
while((ln = listNext(&li))) {
|
||||||
|
RedisModuleEventListener *el = ln->value;
|
||||||
|
if (el->event.id == eid) {
|
||||||
|
RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
|
||||||
|
ctx.module = el->module;
|
||||||
|
ctx.client = moduleFreeContextReusedClient;
|
||||||
|
|
||||||
|
void *moduledata = NULL;
|
||||||
|
struct moduleClientInfoV1 civ1;
|
||||||
|
if (eid == REDISMODULE_EVENT_ID_CLIENT_CONNNECTED ||
|
||||||
|
eid == REDISMODULE_EVENT_ID_CLIENT_DISCONNECTED)
|
||||||
|
{
|
||||||
|
modulePopulateClientInfoStructure(&civ1,data,
|
||||||
|
el->event.dataver);
|
||||||
|
}
|
||||||
|
el->callback(&ctx,el->event,subid,moduledata);
|
||||||
|
moduleFreeContext(&ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* Modules API internals
|
* Modules API internals
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
@ -180,38 +180,38 @@ typedef struct RedisModuleEvent {
|
|||||||
RedisModuleEvent
|
RedisModuleEvent
|
||||||
RedisModuleEvent_ReplicationRoleChanged = {
|
RedisModuleEvent_ReplicationRoleChanged = {
|
||||||
REDISMODULE_EVENT_ID_REPLICATION_ROLE_CHANGED,
|
REDISMODULE_EVENT_ID_REPLICATION_ROLE_CHANGED,
|
||||||
0
|
1
|
||||||
},
|
},
|
||||||
RedisModuleEvent_Persistence = {
|
RedisModuleEvent_Persistence = {
|
||||||
REDISMODULE_EVENT_ID_PERSISTENCE,
|
REDISMODULE_EVENT_ID_PERSISTENCE,
|
||||||
0
|
1
|
||||||
},
|
},
|
||||||
RedisModuleEvent_FlushDB = {
|
RedisModuleEvent_FlushDB = {
|
||||||
REDISMODULE_EVENT_ID_FLUSHDB,
|
REDISMODULE_EVENT_ID_FLUSHDB,
|
||||||
0
|
1
|
||||||
},
|
},
|
||||||
RedisModuleEvent_Loading = {
|
RedisModuleEvent_Loading = {
|
||||||
REDISMODULE_EVENT_ID_LOADING,
|
REDISMODULE_EVENT_ID_LOADING,
|
||||||
0
|
1
|
||||||
},
|
},
|
||||||
RedisModuleEvent_ClientChange = {
|
RedisModuleEvent_ClientChange = {
|
||||||
REDISMODULE_EVENT_ID_CLIENT_CHANGE,
|
REDISMODULE_EVENT_ID_CLIENT_CHANGE,
|
||||||
0
|
1
|
||||||
},
|
},
|
||||||
RedisModuleEvent_Shutdown = {
|
RedisModuleEvent_Shutdown = {
|
||||||
REDISMODULE_EVENT_ID_SHUTDOWN,
|
REDISMODULE_EVENT_ID_SHUTDOWN,
|
||||||
0
|
1
|
||||||
},
|
},
|
||||||
RedisModuleEvent_ReplicaChange = {
|
RedisModuleEvent_ReplicaChange = {
|
||||||
REDISMODULE_EVENT_ID_REPLICA_CHANGE,
|
REDISMODULE_EVENT_ID_REPLICA_CHANGE,
|
||||||
0
|
1
|
||||||
},
|
},
|
||||||
RedisModuleEvent_MasterLinkChange = {
|
RedisModuleEvent_MasterLinkChange = {
|
||||||
REDISMODULE_EVENT_ID_MASTER_LINK_CHANGE,
|
REDISMODULE_EVENT_ID_MASTER_LINK_CHANGE,
|
||||||
0
|
1
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int (*RedisModuleEventCallback)(RedisModuleEvent eid, uint64_t subevent, void *data);
|
typedef int (*RedisModuleEventCallback)(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64_t subevent, void *data);
|
||||||
|
|
||||||
/* Those are values that are used for the 'subevent' callback argument. */
|
/* Those are values that are used for the 'subevent' callback argument. */
|
||||||
#define REDISMODULE_EVENT_PERSISTENCE_RDB_START 0
|
#define REDISMODULE_EVENT_PERSISTENCE_RDB_START 0
|
||||||
|
Loading…
Reference in New Issue
Block a user