summaryrefslogtreecommitdiff
path: root/src/aof.c
diff options
context:
space:
mode:
authorchenyang8094 <chenyang8094@users.noreply.github.com>2022-01-13 14:49:26 +0800
committerGitHub <noreply@github.com>2022-01-13 08:49:26 +0200
commite9bff7978a4e4b5cc7ab958715d1a6214dc68919 (patch)
treed4be16b9cd4fe3b85375bf5c78a754c5d08f6373 /src/aof.c
parent20c33fe6a8fce2edb3e4158bc10bde2c3740a25b (diff)
downloadredis-e9bff7978a4e4b5cc7ab958715d1a6214dc68919.tar.gz
Always create base AOF file when redis start from empty. (#10102)
Force create a BASE file (use a foreground `rewriteAppendOnlyFile`) when redis starts from an empty data set and `appendonly` is yes. The reasoning is that normally, after redis is running for some time, and the AOF has gone though a few rewrites, there's always a base rdb file. and the scenario where the base file is missing, is kinda rare (happens only at empty startup), so this change normalizes it. But more importantly, there are or could be some complex modules that are started with some configuration, when they create persistence they write that configuration to RDB AUX fields, so that can can always know with which configuration the persistence file they're loading was created (could be critical). there is (was) one scenario in which they could load their persisted data, and that configuration was missing, and this change fixes it. Add a new module event: REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START, similar to REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START which is async. Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'src/aof.c')
-rw-r--r--src/aof.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/aof.c b/src/aof.c
index d360d59f2..20b7e57b8 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -46,6 +46,7 @@ off_t getAppendOnlyFileSize(sds filename);
off_t getBaseAndIncrAppendOnlyFilesSize(aofManifest *am);
int getBaseAndIncrAppendOnlyFilesNum(aofManifest *am);
int aofFileExist(char *filename);
+int rewriteAppendOnlyFile(char *filename);
/* ----------------------------------------------------------------------------
* AOF Manifest file implementation.
@@ -667,11 +668,12 @@ int aofDelHistoryFiles(void) {
}
/* Called after `loadDataFromDisk` when redis start. If `server.aof_state` is
- * 'AOF_ON', It will do two things:
- * 1. Open the last opened INCR type AOF for writing, If not, create a new one
- * 2. Synchronously update the manifest file to the disk
+ * 'AOF_ON', It will do three things:
+ * 1. Force create a BASE file when redis starts with an empty dataset
+ * 2. Open the last opened INCR type AOF for writing, If not, create a new one
+ * 3. Synchronously update the manifest file to the disk
*
- * If any of the above two steps fails, the redis process will exit.
+ * If any of the above steps fails, the redis process will exit.
*/
void aofOpenIfNeededOnServerStart(void) {
if (server.aof_state != AOF_ON) {
@@ -687,6 +689,18 @@ void aofOpenIfNeededOnServerStart(void) {
exit(1);
}
+ /* If we start with an empty dataset, we will force create a BASE file. */
+ if (!server.aof_manifest->base_aof_info &&
+ !listLength(server.aof_manifest->incr_aof_list))
+ {
+ sds base_name = getNewBaseFileNameAndMarkPreAsHistory(server.aof_manifest);
+ sds base_filepath = makePath(server.aof_dirname, base_name);
+ if (rewriteAppendOnlyFile(base_filepath) != C_OK) {
+ exit(1);
+ }
+ sdsfree(base_filepath);
+ }
+
/* Because we will 'exit(1)' if open AOF or persistent manifest fails, so
* we don't need atomic modification here. */
sds aof_name = getLastIncrAofName(server.aof_manifest);
@@ -701,6 +715,7 @@ void aofOpenIfNeededOnServerStart(void) {
exit(1);
}
+ /* Persist our changes. */
int ret = persistAofManifest(server.aof_manifest);
if (ret != C_OK) {
exit(1);