summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config.c6
-rw-r--r--src/module.c19
-rw-r--r--src/redismodule.h23
-rw-r--r--tests/modules/hooks.c15
-rw-r--r--tests/unit/moduleapi/hooks.tcl6
5 files changed, 66 insertions, 3 deletions
diff --git a/src/config.c b/src/config.c
index fd720e50a..4684d8661 100644
--- a/src/config.c
+++ b/src/config.c
@@ -709,6 +709,7 @@ void configSetCommand(client *c) {
const char *invalid_arg_name = NULL;
const char *err_arg_name = NULL;
standardConfig **set_configs; /* TODO: make this a dict for better performance */
+ const char **config_names;
sds *new_values;
sds *old_values = NULL;
apply_fn *apply_fns; /* TODO: make this a set for better performance */
@@ -724,6 +725,7 @@ void configSetCommand(client *c) {
config_count = (c->argc - 2) / 2;
set_configs = zcalloc(sizeof(standardConfig*)*config_count);
+ config_names = zcalloc(sizeof(char*)*config_count);
new_values = zmalloc(sizeof(sds*)*config_count);
old_values = zcalloc(sizeof(sds*)*config_count);
apply_fns = zcalloc(sizeof(apply_fn)*config_count);
@@ -779,6 +781,7 @@ void configSetCommand(client *c) {
}
}
set_configs[i] = config;
+ config_names[i] = config->name;
new_values[i] = c->argv[2+i*2+1]->ptr;
}
@@ -824,6 +827,8 @@ void configSetCommand(client *c) {
goto err;
}
}
+ RedisModuleConfigChangeV1 cc = {.num_changes = config_count, .config_names = config_names};
+ moduleFireServerEvent(REDISMODULE_EVENT_CONFIG, REDISMODULE_SUBEVENT_CONFIG_CHANGE, &cc);
addReply(c,shared.ok);
goto end;
@@ -840,6 +845,7 @@ err:
}
end:
zfree(set_configs);
+ zfree(config_names);
zfree(new_values);
for (i = 0; i < config_count; i++)
sdsfree(old_values[i]);
diff --git a/src/module.c b/src/module.c
index 2946f6229..d0b1d7ce5 100644
--- a/src/module.c
+++ b/src/module.c
@@ -9976,6 +9976,7 @@ static uint64_t moduleEventVersions[] = {
-1, /* REDISMODULE_EVENT_FORK_CHILD */
-1, /* REDISMODULE_EVENT_REPL_ASYNC_LOAD */
-1, /* REDISMODULE_EVENT_EVENTLOOP */
+ -1, /* REDISMODULE_EVENT_CONFIG */
};
/* Register to be notified, via a callback, when the specified server event
@@ -10236,6 +10237,20 @@ static uint64_t moduleEventVersions[] = {
* * `REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP`
* * `REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP`
*
+ * * RedisModule_Event_Config
+ *
+ * Called when a configuration event happens
+ * The following sub events are available:
+ *
+ * * `REDISMODULE_SUBEVENT_CONFIG_CHANGE`
+ *
+ * The data pointer can be casted to a RedisModuleConfigChange
+ * structure with the following fields:
+ *
+ * const char **config_names; // An array of C string pointers containing the
+ * // name of each modified configuration item
+ * uint32_t num_changes; // The number of elements in the config_names array
+ *
* The function returns REDISMODULE_OK if the module was successfully subscribed
* for the specified event. If the API is called from a wrong context or unsupported event
* is given then REDISMODULE_ERR is returned. */
@@ -10313,6 +10328,8 @@ int RM_IsSubEventSupported(RedisModuleEvent event, int64_t subevent) {
return subevent < _REDISMODULE_SUBEVENT_FORK_CHILD_NEXT;
case REDISMODULE_EVENT_EVENTLOOP:
return subevent < _REDISMODULE_SUBEVENT_EVENTLOOP_NEXT;
+ case REDISMODULE_EVENT_CONFIG:
+ return subevent < _REDISMODULE_SUBEVENT_CONFIG_NEXT;
default:
break;
}
@@ -10389,6 +10406,8 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) {
moduledata = data;
} else if (eid == REDISMODULE_EVENT_SWAPDB) {
moduledata = data;
+ } else if (eid == REDISMODULE_EVENT_CONFIG) {
+ moduledata = data;
}
el->module->in_hook++;
diff --git a/src/redismodule.h b/src/redismodule.h
index 79ce2c697..1f16708c0 100644
--- a/src/redismodule.h
+++ b/src/redismodule.h
@@ -429,7 +429,8 @@ typedef void (*RedisModuleEventLoopOneShotFunc)(void *user_data);
#define REDISMODULE_EVENT_FORK_CHILD 13
#define REDISMODULE_EVENT_REPL_ASYNC_LOAD 14
#define REDISMODULE_EVENT_EVENTLOOP 15
-#define _REDISMODULE_EVENT_NEXT 16 /* Next event flag, should be updated if a new event added. */
+#define REDISMODULE_EVENT_CONFIG 16
+#define _REDISMODULE_EVENT_NEXT 17 /* Next event flag, should be updated if a new event added. */
typedef struct RedisModuleEvent {
uint64_t id; /* REDISMODULE_EVENT_... defines. */
@@ -532,7 +533,11 @@ static const RedisModuleEvent
RedisModuleEvent_EventLoop = {
REDISMODULE_EVENT_EVENTLOOP,
1
-};
+ },
+ RedisModuleEvent_Config = {
+ REDISMODULE_EVENT_CONFIG,
+ 1
+ };
/* Those are values that are used for the 'subevent' callback argument. */
#define REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START 0
@@ -574,6 +579,9 @@ static const RedisModuleEvent
#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
@@ -674,6 +682,17 @@ typedef struct RedisModuleModuleChange {
#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
diff --git a/tests/modules/hooks.c b/tests/modules/hooks.c
index af4681cf9..94d902d22 100644
--- a/tests/modules/hooks.c
+++ b/tests/modules/hooks.c
@@ -267,6 +267,18 @@ void swapDbCallback(RedisModuleCtx *ctx, RedisModuleEvent e, uint64_t sub, void
LogNumericEvent(ctx, "swapdb-second", ei->dbnum_second);
}
+void configChangeCallback(RedisModuleCtx *ctx, RedisModuleEvent e, uint64_t sub, void *data)
+{
+ REDISMODULE_NOT_USED(e);
+ if (sub != REDISMODULE_SUBEVENT_CONFIG_CHANGE) {
+ return;
+ }
+
+ RedisModuleConfigChangeV1 *ei = data;
+ LogNumericEvent(ctx, "config-change-count", ei->num_changes);
+ LogStringEvent(ctx, "config-change-first", ei->config_names[0]);
+}
+
/* This function must be present on each Redis module. It is used in order to
* register the commands into the Redis server. */
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
@@ -317,6 +329,9 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
RedisModule_SubscribeToServerEvent(ctx,
RedisModuleEvent_SwapDB, swapDbCallback);
+ RedisModule_SubscribeToServerEvent(ctx,
+ RedisModuleEvent_Config, configChangeCallback);
+
event_log = RedisModule_CreateDict(ctx);
if (RedisModule_CreateCommand(ctx,"hooks.event_count", cmdEventCount,"",0,0,0) == REDISMODULE_ERR)
diff --git a/tests/unit/moduleapi/hooks.tcl b/tests/unit/moduleapi/hooks.tcl
index cb36c9f71..814f31bc0 100644
--- a/tests/unit/moduleapi/hooks.tcl
+++ b/tests/unit/moduleapi/hooks.tcl
@@ -150,13 +150,17 @@ tags "modules" {
r swapdb 0 10
assert_equal [r hooks.event_last swapdb-first] 0
assert_equal [r hooks.event_last swapdb-second] 10
+ }
+ test {Test configchange hooks} {
+ r config set rdbcompression no
+ assert_equal [r hooks.event_last config-change-count] 1
+ assert_equal [r hooks.event_last config-change-first] rdbcompression
}
# look into the log file of the server that just exited
test {Test shutdown hook} {
assert_equal [string match {*module-event-shutdown*} [exec tail -5 < $replica_stdout]] 1
}
-
}
}