summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2019-10-21 17:16:34 +0200
committerantirez <antirez@gmail.com>2019-10-21 17:16:41 +0200
commit226aaa3003d394b6a0eb790f2e83378d9c0c62fa (patch)
tree414f7af2855848a3069b5f6fe428fe6885df15fc
parentd9fe3252a86914361e0d4ee057135bac5c8b0629 (diff)
downloadredis-226aaa3003d394b6a0eb790f2e83378d9c0c62fa.tar.gz
Modules hooks: a first version of events and some API.
-rw-r--r--src/module.c58
-rw-r--r--src/redismodule.h69
2 files changed, 120 insertions, 7 deletions
diff --git a/src/module.c b/src/module.c
index d60763851..7a1a4398d 100644
--- a/src/module.c
+++ b/src/module.c
@@ -345,13 +345,6 @@ static struct RedisModuleForkInfo {
#define REDISMODULE_EVENT_ID_MASTER_LINK_UP 14
#define REDISMODULE_EVENT_ID_MASTER_LINK_DOWN 15
-typedef struct RedisModuleEvent {
- uint64_t id; /* REDISMODULE_EVENT_ID_... defines. */
- uint64_t dataver; /* Version of the structure we pass as 'data'. */
-} RedisModuleEvent;
-
-typedef int (*RedisModuleEventCallback)(RedisModuleEvent eid, void *data);
-
typedef struct RedisModuleEventListener {
RedisModule *module;
RedisModuleEvent event;
@@ -5588,6 +5581,57 @@ void ModuleForkDoneHandler(int exitcode, int bysignal) {
}
/* --------------------------------------------------------------------------
+ * Server hooks implementation
+ * -------------------------------------------------------------------------- */
+
+/* Register to be notified, via a callback, when the specified server event
+ * happens. The callback is called with the event as argument, and an additional
+ * argument which is a void pointer and should be cased to a specific type
+ * that is event-specific (but many events will just use NULL since they do not
+ * have additional information to pass to the callback).
+ *
+ * If the callback is NULL and there was a previous subscription, the module
+ * 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.
+ *
+ * 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
+ * REDISMODULE_ERR is returned. */
+int RedisModule_SubscribeToServerEvent(RedisModuleCtx *ctx, RedisModuleEvent event, RedisModuleEventCallback callback) {
+ RedisModuleEventListener *el;
+
+ /* Protect in case of calls from contexts without a module reference. */
+ if (ctx->module == NULL) return REDISMODULE_ERR;
+
+ /* Search an event matching this module and event ID. */
+ listIter li;
+ listNode *ln;
+ listRewind(RedisModule_EventListeners,&li);
+ while((ln = listNext(&li))) {
+ el = ln->value;
+ if (el->module == ctx->module && el->event.id == event.id)
+ break; /* Matching event found. */
+ }
+
+ /* Modify or remove the event listener if we already had one. */
+ if (ln) {
+ if (callback == NULL)
+ listDelNode(RedisModule_EventListeners,ln);
+ else
+ el->callback = callback; /* Update the callback with the new one. */
+ return REDISMODULE_OK;
+ }
+
+ /* No event found, we need to add a new one. */
+ el = zmalloc(sizeof(*el));
+ el->module = ctx->module;
+ el->event = event;
+ el->callback = callback;
+ listAddNodeTail(RedisModule_EventListeners,el);
+ return REDISMODULE_OK;
+}
+
+/* --------------------------------------------------------------------------
* Modules API internals
* -------------------------------------------------------------------------- */
diff --git a/src/redismodule.h b/src/redismodule.h
index 19a9cd897..1b8885e04 100644
--- a/src/redismodule.h
+++ b/src/redismodule.h
@@ -162,6 +162,75 @@ typedef uint64_t RedisModuleTimerID;
/* Declare that the module can handle errors with RedisModule_SetModuleOptions. */
#define REDISMODULE_OPTIONS_HANDLE_IO_ERRORS (1<<0)
+/* Server events definitions. */
+#define REDISMODULE_EVENT_ID_REPLICATION_ROLE_CHANGED 0
+#define REDISMODULE_EVENT_ID_PERSISTENCE 1
+#define REDISMODULE_EVENT_ID_FLUSHDB 2
+#define REDISMODULE_EVENT_ID_LOADING 3
+#define REDISMODULE_EVENT_ID_CLIENT_CHANGE 4
+#define REDISMODULE_EVENT_ID_SHUTDOWN 5
+#define REDISMODULE_EVENT_ID_REPLICA_CHANGE 6
+#define REDISMODULE_EVENT_ID_MASTER_LINK_CHANGE 7
+
+typedef struct RedisModuleEvent {
+ uint64_t id; /* REDISMODULE_EVENT_ID_... defines. */
+ uint64_t dataver; /* Version of the structure we pass as 'data'. */
+} RedisModuleEvent;
+
+RedisModuleEvent
+ RedisModuleEvent_ReplicationRoleChanged = {
+ REDISMODULE_EVENT_ID_REPLICATION_ROLE_CHANGED,
+ 0
+ },
+ RedisModuleEvent_Persistence = {
+ REDISMODULE_EVENT_ID_PERSISTENCE,
+ 0
+ },
+ RedisModuleEvent_FlushDB = {
+ REDISMODULE_EVENT_ID_FLUSHDB,
+ 0
+ },
+ RedisModuleEvent_Loading = {
+ REDISMODULE_EVENT_ID_LOADING,
+ 0
+ },
+ RedisModuleEvent_ClientChange = {
+ REDISMODULE_EVENT_ID_CLIENT_CHANGE,
+ 0
+ },
+ RedisModuleEvent_Shutdown = {
+ REDISMODULE_EVENT_ID_SHUTDOWN,
+ 0
+ },
+ RedisModuleEvent_ReplicaChange = {
+ REDISMODULE_EVENT_ID_REPLICA_CHANGE,
+ 0
+ },
+ RedisModuleEvent_MasterLinkChange = {
+ REDISMODULE_EVENT_ID_MASTER_LINK_CHANGE,
+ 0
+ };
+
+typedef int (*RedisModuleEventCallback)(RedisModuleEvent eid, uint64_t subevent, void *data);
+
+/* Those are values that are used for the 'subevent' callback argument. */
+#define REDISMODULE_EVENT_PERSISTENCE_RDB_START 0
+#define REDISMODULE_EVENT_PERSISTENCE_RDB_END 1
+#define REDISMODULE_EVENT_PERSISTENCE_AOF_START 2
+#define REDISMODULE_EVENT_PERSISTENCE_AOF_END 3
+
+#define REDISMODULE_EVENT_LOADING_START 0
+#define REDISMODULE_EVENT_LOADING_END 1
+
+#define REDISMODULE_EVENT_CLIENT_CHANGE_CONNECTED 0
+#define REDISMODULE_EVENT_CLIENT_CHANGE_DISCONNECTED 1
+
+#define REDISMODULE_EVENT_MASTER_LINK_UP 0
+#define REDISMODULE_EVENT_MASTER_LINK_DOWN 1
+
+#define REDISMODULE_EVENT_REPLICA_CHANGE_CONNECTED 0
+#define REDISMODULE_EVENT_REPLICA_CHANGE_DISCONNECTED 1
+
/* ------------------------- End of common defines ------------------------ */
#ifndef REDISMODULE_CORE