summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalvatore Sanfilippo <antirez@gmail.com>2020-02-06 13:10:00 +0100
committerGitHub <noreply@github.com>2020-02-06 13:10:00 +0100
commit9c00bdd86e8b5e8e863c056cf7c1eb69a00fdc51 (patch)
tree41615f33ce6343e151a286f3bd3e75fc06bcfdf8
parent50d4326e3b65b4ab713a9ab8bd59f36a4b66b52f (diff)
parent92dc5e1fa41491e0ab0744a2bab55f837db89dc2 (diff)
downloadredis-9c00bdd86e8b5e8e863c056cf7c1eb69a00fdc51.tar.gz
Merge pull request #6822 from guybe7/diskless_load_module_hook_fix
Diskless-load emptyDb-related fixes
-rw-r--r--src/db.c57
-rw-r--r--src/replication.c14
-rw-r--r--src/server.h1
3 files changed, 44 insertions, 28 deletions
diff --git a/src/db.c b/src/db.c
index 88342ac4d..c80524e94 100644
--- a/src/db.c
+++ b/src/db.c
@@ -347,7 +347,10 @@ robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {
* DB number if we want to flush only a single Redis database number.
*
* Flags are be EMPTYDB_NO_FLAGS if no special flags are specified or
- * EMPTYDB_ASYNC if we want the memory to be freed in a different thread
+ * 1. EMPTYDB_ASYNC if we want the memory to be freed in a different thread.
+ * 2. EMPTYDB_BACKUP if we want to empty the backup dictionaries created by
+ * disklessLoadMakeBackups. In that case we only free memory and avoid
+ * firing module events.
* and the function to return ASAP.
*
* On success the fuction returns the number of keys removed from the
@@ -355,6 +358,8 @@ robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {
* DB number is out of range, and errno is set to EINVAL. */
long long emptyDbGeneric(redisDb *dbarray, int dbnum, int flags, void(callback)(void*)) {
int async = (flags & EMPTYDB_ASYNC);
+ int backup = (flags & EMPTYDB_BACKUP); /* Just free the memory, nothing else */
+ RedisModuleFlushInfoV1 fi = {REDISMODULE_FLUSHINFO_VERSION,!async,dbnum};
long long removed = 0;
if (dbnum < -1 || dbnum >= server.dbnum) {
@@ -362,16 +367,18 @@ long long emptyDbGeneric(redisDb *dbarray, int dbnum, int flags, void(callback)(
return -1;
}
- /* Fire the flushdb modules event. */
- RedisModuleFlushInfoV1 fi = {REDISMODULE_FLUSHINFO_VERSION,!async,dbnum};
- moduleFireServerEvent(REDISMODULE_EVENT_FLUSHDB,
- REDISMODULE_SUBEVENT_FLUSHDB_START,
- &fi);
-
- /* Make sure the WATCHed keys are affected by the FLUSH* commands.
- * Note that we need to call the function while the keys are still
- * there. */
- signalFlushedDb(dbnum);
+ /* Pre-flush actions */
+ if (!backup) {
+ /* Fire the flushdb modules event. */
+ moduleFireServerEvent(REDISMODULE_EVENT_FLUSHDB,
+ REDISMODULE_SUBEVENT_FLUSHDB_START,
+ &fi);
+
+ /* Make sure the WATCHed keys are affected by the FLUSH* commands.
+ * Note that we need to call the function while the keys are still
+ * there. */
+ signalFlushedDb(dbnum);
+ }
int startdb, enddb;
if (dbnum == -1) {
@@ -390,20 +397,24 @@ long long emptyDbGeneric(redisDb *dbarray, int dbnum, int flags, void(callback)(
dictEmpty(dbarray[j].expires,callback);
}
}
- if (server.cluster_enabled) {
- if (async) {
- slotToKeyFlushAsync();
- } else {
- slotToKeyFlush();
+
+ /* Post-flush actions */
+ if (!backup) {
+ if (server.cluster_enabled) {
+ if (async) {
+ slotToKeyFlushAsync();
+ } else {
+ slotToKeyFlush();
+ }
}
- }
- if (dbnum == -1) flushSlaveKeysWithExpireList();
+ if (dbnum == -1) flushSlaveKeysWithExpireList();
- /* Also fire the end event. Note that this event will fire almost
- * immediately after the start event if the flush is asynchronous. */
- moduleFireServerEvent(REDISMODULE_EVENT_FLUSHDB,
- REDISMODULE_SUBEVENT_FLUSHDB_END,
- &fi);
+ /* Also fire the end event. Note that this event will fire almost
+ * immediately after the start event if the flush is asynchronous. */
+ moduleFireServerEvent(REDISMODULE_EVENT_FLUSHDB,
+ REDISMODULE_SUBEVENT_FLUSHDB_END,
+ &fi);
+ }
return removed;
}
diff --git a/src/replication.c b/src/replication.c
index a006d0ad1..4843f97d5 100644
--- a/src/replication.c
+++ b/src/replication.c
@@ -1339,8 +1339,8 @@ void disklessLoadRestoreBackups(redisDb *backup, int restore, int empty_db_flags
server.db[i] = backup[i];
}
} else {
- /* Delete. */
- emptyDbGeneric(backup,-1,empty_db_flags,replicationEmptyDbCallback);
+ /* Delete (Pass EMPTYDB_BACKUP in order to avoid firing module events) . */
+ emptyDbGeneric(backup,-1,empty_db_flags|EMPTYDB_BACKUP,replicationEmptyDbCallback);
for (int i=0; i<server.dbnum; i++) {
dictRelease(backup[i].dict);
dictRelease(backup[i].expires);
@@ -1524,7 +1524,6 @@ void readSyncBulkPayload(connection *conn) {
/* We need to stop any AOF rewriting child before flusing and parsing
* the RDB, otherwise we'll create a copy-on-write disaster. */
if (server.aof_state != AOF_OFF) stopAppendOnly();
- signalFlushedDb(-1);
/* When diskless RDB loading is used by replicas, it may be configured
* in order to save the current DB instead of throwing it away,
@@ -1532,10 +1531,15 @@ void readSyncBulkPayload(connection *conn) {
if (use_diskless_load &&
server.repl_diskless_load == REPL_DISKLESS_LOAD_SWAPDB)
{
+ /* Create a backup of server.db[] and initialize to empty
+ * dictionaries */
diskless_load_backup = disklessLoadMakeBackups();
- } else {
- emptyDb(-1,empty_db_flags,replicationEmptyDbCallback);
}
+ /* We call to emptyDb even in case of REPL_DISKLESS_LOAD_SWAPDB
+ * (Where disklessLoadMakeBackups left server.db empty) because we
+ * want to execute all the auxiliary logic of emptyDb (Namely,
+ * fire module events) */
+ emptyDb(-1,empty_db_flags,replicationEmptyDbCallback);
/* Before loading the DB into memory we need to delete the readable
* handler, otherwise it will get called recursively since
diff --git a/src/server.h b/src/server.h
index cf423a664..dfbc15ac3 100644
--- a/src/server.h
+++ b/src/server.h
@@ -2045,6 +2045,7 @@ robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o);
#define EMPTYDB_NO_FLAGS 0 /* No flags. */
#define EMPTYDB_ASYNC (1<<0) /* Reclaim memory in another thread. */
+#define EMPTYDB_BACKUP (1<<2) /* DB array is a backup for REPL_DISKLESS_LOAD_SWAPDB. */
long long emptyDb(int dbnum, int flags, void(callback)(void*));
long long emptyDbGeneric(redisDb *dbarray, int dbnum, int flags, void(callback)(void*));
void flushAllDataAndResetRDB(int flags);