summaryrefslogtreecommitdiff
path: root/src/aof.c
diff options
context:
space:
mode:
authorchenyang8094 <chenyang8094@users.noreply.github.com>2022-02-17 14:13:28 +0800
committerGitHub <noreply@github.com>2022-02-17 08:13:28 +0200
commita50aa29bde33f22dabc307c4a28bc2321f8acdfe (patch)
tree8351914073483df081cb5e85ccd568f2939d5184 /src/aof.c
parentf7f68c654a90c4d3e84121c4555a56682b02b2de (diff)
downloadredis-a50aa29bde33f22dabc307c4a28bc2321f8acdfe.tar.gz
Adapt redis-check-aof tool for Multi Part Aof (#10061)
Modifications of this PR: 1. Support the verification of `Multi Part AOF`, while still maintaining support for the old-style `AOF/RDB-preamble`. `redis-check-aof` will automatically choose which mode to use according to the incoming file format. `Usage: redis-check-aof [--fix|--truncate-to-timestamp $timestamp] <AOF/manifest>` 2. Refactor part of the code to make it easier to understand 3. Currently only supports truncate (`--fix` or `--truncate-to-timestamp`) the last AOF file (may be `BASE` or `INCR`) The reasons for 3 above: - for `--fix`: Only the last AOF may be truncated, this is guaranteed by redis - for `--truncate-to-timestamp`: Normally, we only have `BASE` + `INCR` files at most, and `BASE` cannot be truncated(It only contains a timestamp annotation at the beginning of the file), so only `INCR` can be truncated. If we have a `BASE+INCR1+INCR2` file (meaning we have an interrupted AOFRW), Only `INCR2` files can be truncated at this time. If we still insist on truncate `INCR1`, we need to manually delete `INCR2` and update the manifest file, then re-run `redis-check-aof` - If we want to support truncate any file, we need to add very complicated code to support the atomic modification of multiple file deletion and update manifest, I think this is unnecessary
Diffstat (limited to 'src/aof.c')
-rw-r--r--src/aof.c55
1 files changed, 31 insertions, 24 deletions
diff --git a/src/aof.c b/src/aof.c
index 7fca84ef8..d7ba6b318 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -47,6 +47,8 @@ off_t getBaseAndIncrAppendOnlyFilesSize(aofManifest *am);
int getBaseAndIncrAppendOnlyFilesNum(aofManifest *am);
int aofFileExist(char *filename);
int rewriteAppendOnlyFile(char *filename);
+aofManifest *aofLoadManifestFromFile(sds am_filepath);
+void aofManifestFreeAndUpdate(aofManifest *am);
/* ----------------------------------------------------------------------------
* AOF Manifest file implementation.
@@ -226,13 +228,8 @@ sds getAofManifestAsString(aofManifest *am) {
* in order to support seamless upgrades from previous versions which did not
* use them.
*/
-#define MANIFEST_MAX_LINE 1024
void aofLoadManifestFromDisk(void) {
- const char *err = NULL;
- long long maxseq = 0;
-
server.aof_manifest = aofManifestCreate();
-
if (!dirExists(server.aof_dirname)) {
serverLog(LL_NOTICE, "The AOF directory %s doesn't exist", server.aof_dirname);
return;
@@ -247,16 +244,26 @@ void aofLoadManifestFromDisk(void) {
return;
}
+ aofManifest *am = aofLoadManifestFromFile(am_filepath);
+ if (am) aofManifestFreeAndUpdate(am);
+ sdsfree(am_name);
+ sdsfree(am_filepath);
+}
+
+/* Generic manifest loading function, used in `aofLoadManifestFromDisk` and redis-check-aof tool. */
+#define MANIFEST_MAX_LINE 1024
+aofManifest *aofLoadManifestFromFile(sds am_filepath) {
+ const char *err = NULL;
+ long long maxseq = 0;
+
+ aofManifest *am = aofManifestCreate();
FILE *fp = fopen(am_filepath, "r");
if (fp == NULL) {
serverLog(LL_WARNING, "Fatal error: can't open the AOF manifest "
- "file %s for reading: %s", am_name, strerror(errno));
+ "file %s for reading: %s", am_filepath, strerror(errno));
exit(1);
}
- sdsfree(am_name);
- sdsfree(am_filepath);
-
char buf[MANIFEST_MAX_LINE+1];
sds *argv = NULL;
int argc;
@@ -292,14 +299,14 @@ void aofLoadManifestFromDisk(void) {
line = sdstrim(sdsnew(buf), " \t\r\n");
if (!sdslen(line)) {
- err = "The AOF manifest file is invalid format";
+ err = "Invalid AOF manifest file format";
goto loaderr;
}
argv = sdssplitargs(line, &argc);
/* 'argc < 6' was done for forward compatibility. */
if (argv == NULL || argc < 6 || (argc % 2)) {
- err = "The AOF manifest file is invalid format";
+ err = "Invalid AOF manifest file format";
goto loaderr;
}
@@ -321,7 +328,7 @@ void aofLoadManifestFromDisk(void) {
/* We have to make sure we load all the information. */
if (!ai->file_name || !ai->file_seq || !ai->file_type) {
- err = "The AOF manifest file is invalid format";
+ err = "Invalid AOF manifest file format";
goto loaderr;
}
@@ -329,21 +336,21 @@ void aofLoadManifestFromDisk(void) {
argv = NULL;
if (ai->file_type == AOF_FILE_TYPE_BASE) {
- if (server.aof_manifest->base_aof_info) {
+ if (am->base_aof_info) {
err = "Found duplicate base file information";
goto loaderr;
}
- server.aof_manifest->base_aof_info = ai;
- server.aof_manifest->curr_base_file_seq = ai->file_seq;
+ am->base_aof_info = ai;
+ am->curr_base_file_seq = ai->file_seq;
} else if (ai->file_type == AOF_FILE_TYPE_HIST) {
- listAddNodeTail(server.aof_manifest->history_aof_list, ai);
+ listAddNodeTail(am->history_aof_list, ai);
} else if (ai->file_type == AOF_FILE_TYPE_INCR) {
if (ai->file_seq <= maxseq) {
err = "Found a non-monotonic sequence number";
goto loaderr;
}
- listAddNodeTail(server.aof_manifest->incr_aof_list, ai);
- server.aof_manifest->curr_incr_file_seq = ai->file_seq;
+ listAddNodeTail(am->incr_aof_list, ai);
+ am->curr_incr_file_seq = ai->file_seq;
maxseq = ai->file_seq;
} else {
err = "Unknown AOF file type";
@@ -356,7 +363,7 @@ void aofLoadManifestFromDisk(void) {
}
fclose(fp);
- return;
+ return am;
loaderr:
/* Sanitizer suppression: may report a false positive if we goto loaderr
@@ -1526,15 +1533,15 @@ uxeof: /* Unexpected AOF end of file. */
}
}
}
- serverLog(LL_WARNING,"Unexpected end of file reading the append only file %s. You can: \
- 1) Make a backup of your AOF file, then use ./redis-check-aof --fix <filename>. \
- 2) Alternatively you can set the 'aof-load-truncated' configuration option to yes and restart the server.", filename);
+ serverLog(LL_WARNING, "Unexpected end of file reading the append only file %s. You can: "
+ "1) Make a backup of your AOF file, then use ./redis-check-aof --fix <filename.manifest>. "
+ "2) Alternatively you can set the 'aof-load-truncated' configuration option to yes and restart the server.", filename);
ret = AOF_FAILED;
goto cleanup;
fmterr: /* Format error. */
- serverLog(LL_WARNING,"Bad file format reading the append only file %s: \
- make a backup of your AOF file, then use ./redis-check-aof --fix <filename>", filename);
+ serverLog(LL_WARNING, "Bad file format reading the append only file %s: "
+ "make a backup of your AOF file, then use ./redis-check-aof --fix <filename.manifest>", filename);
ret = AOF_FAILED;
/* fall through to cleanup. */