diff --git a/src/db.c b/src/db.c index 41ee53601..5045935c3 100644 --- a/src/db.c +++ b/src/db.c @@ -477,6 +477,10 @@ dbBackup *backupDb(void) { sizeof(server.cluster->slots_keys_count)); } + moduleFireServerEvent(REDISMODULE_EVENT_REPL_BACKUP, + REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE, + NULL); + return backup; } @@ -498,6 +502,10 @@ void discardDbBackup(dbBackup *buckup, int flags, void(callback)(void*)) { /* Release buckup. */ zfree(buckup->dbarray); zfree(buckup); + + moduleFireServerEvent(REDISMODULE_EVENT_REPL_BACKUP, + REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD, + NULL); } /* Restore the previously created backup (discarding what currently resides @@ -526,6 +534,10 @@ void restoreDbBackup(dbBackup *buckup) { /* Release buckup. */ zfree(buckup->dbarray); zfree(buckup); + + moduleFireServerEvent(REDISMODULE_EVENT_REPL_BACKUP, + REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE, + NULL); } int selectDb(client *c, int id) { diff --git a/src/module.c b/src/module.c index 94bdbf641..29e44aa74 100644 --- a/src/module.c +++ b/src/module.c @@ -7350,7 +7350,7 @@ void ModuleForkDoneHandler(int exitcode, int bysignal) { * * RedisModuleEvent_SwapDB * - * This event is called when a swap db command has been successfully + * This event is called when a SWAPDB command has been successfully * Executed. * For this event call currently there is no subevents available. * @@ -7360,6 +7360,18 @@ void ModuleForkDoneHandler(int exitcode, int bysignal) { * int32_t dbnum_first; // Swap Db first dbnum * int32_t dbnum_second; // Swap Db second dbnum * + * RedisModuleEvent_ReplBackup + * + * Called when diskless-repl-load config is set to swapdb, + * And redis needs to backup the the current database for the + * possibility to be restored later. A module with global data and + * maybe with aux_load and aux_save callbacks may need to use this + * notification to backup / restore / discard its globals. + * The following sub events are available: + * + * REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE + * REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE + * REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD * * * The function returns REDISMODULE_OK if the module was successfully subscribed @@ -7432,6 +7444,8 @@ int RM_IsSubEventSupported(RedisModuleEvent event, int64_t subevent) { return subevent < _REDISMODULE_SUBEVENT_LOADING_PROGRESS_NEXT; case REDISMODULE_EVENT_SWAPDB: return subevent < _REDISMODULE_SUBEVENT_SWAPDB_NEXT; + case REDISMODULE_EVENT_REPL_BACKUP: + return subevent < _REDISMODULE_SUBEVENT_REPL_BACKUP_NEXT; default: break; } diff --git a/src/redismodule.h b/src/redismodule.h index d7d4b7689..d2afa1f21 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -215,9 +215,10 @@ typedef uint64_t RedisModuleTimerID; #define REDISMODULE_EVENT_MODULE_CHANGE 9 #define REDISMODULE_EVENT_LOADING_PROGRESS 10 #define REDISMODULE_EVENT_SWAPDB 11 +#define REDISMODULE_EVENT_REPL_BACKUP 12 /* Next event flag, should be updated if a new event added. */ -#define _REDISMODULE_EVENT_NEXT 12 +#define _REDISMODULE_EVENT_NEXT 13 typedef struct RedisModuleEvent { uint64_t id; /* REDISMODULE_EVENT_... defines. */ @@ -276,6 +277,10 @@ static const RedisModuleEvent RedisModuleEvent_SwapDB = { REDISMODULE_EVENT_SWAPDB, 1 + }, + RedisModuleEvent_ReplBackup = { + REDISMODULE_EVENT_REPL_BACKUP, + 1 }; /* Those are values that are used for the 'subevent' callback argument. */ @@ -317,11 +322,15 @@ static const RedisModuleEvent #define REDISMODULE_SUBEVENT_MODULE_UNLOADED 1 #define _REDISMODULE_SUBEVENT_MODULE_NEXT 2 - #define REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB 0 #define REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF 1 #define _REDISMODULE_SUBEVENT_LOADING_PROGRESS_NEXT 2 +#define REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE 0 +#define REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE 1 +#define REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD 2 +#define _REDISMODULE_SUBEVENT_REPL_BACKUP_NEXT 3 + #define _REDISMODULE_SUBEVENT_SHUTDOWN_NEXT 0 #define _REDISMODULE_SUBEVENT_CRON_LOOP_NEXT 0 #define _REDISMODULE_SUBEVENT_SWAPDB_NEXT 0 diff --git a/tests/modules/testrdb.c b/tests/modules/testrdb.c index 3150b88e4..5d9382a3a 100644 --- a/tests/modules/testrdb.c +++ b/tests/modules/testrdb.c @@ -13,6 +13,45 @@ RedisModuleType *testrdb_type = NULL; RedisModuleString *before_str = NULL; RedisModuleString *after_str = NULL; +void replBackupCallback(RedisModuleCtx *ctx, RedisModuleEvent e, uint64_t sub, void *data) +{ + REDISMODULE_NOT_USED(e); + REDISMODULE_NOT_USED(data); + static RedisModuleString *before_str_backup = NULL; + static RedisModuleString *after_str_backup = NULL; + + switch (sub) { + case REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE: + assert(before_str_backup == NULL); + assert(after_str_backup == NULL); + before_str_backup = before_str; + after_str_backup = after_str; + before_str = NULL; + after_str = NULL; + break; + case REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE: + if (before_str) + RedisModule_FreeString(ctx, before_str); + if (after_str) + RedisModule_FreeString(ctx, after_str); + before_str = before_str_backup; + after_str = after_str_backup; + before_str_backup = NULL; + after_str_backup = NULL; + break; + case REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD: + if (before_str_backup) + RedisModule_FreeString(ctx, before_str_backup); + if (after_str_backup) + RedisModule_FreeString(ctx, after_str_backup); + before_str_backup = NULL; + after_str_backup = NULL; + break; + default: + assert(0); + } +} + void *testrdb_type_load(RedisModuleIO *rdb, int encver) { int count = RedisModule_LoadSigned(rdb); RedisModuleString *str = RedisModule_LoadString(rdb); @@ -247,6 +286,9 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) if (RedisModule_CreateCommand(ctx,"testrdb.get.key", testrdb_get_key,"",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; + RedisModule_SubscribeToServerEvent(ctx, + RedisModuleEvent_ReplBackup, replBackupCallback); + return REDISMODULE_OK; }