diff options
author | chenyang8094 <chenyang8094@users.noreply.github.com> | 2022-02-17 14:13:28 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-17 08:13:28 +0200 |
commit | a50aa29bde33f22dabc307c4a28bc2321f8acdfe (patch) | |
tree | 8351914073483df081cb5e85ccd568f2939d5184 /src/aof.c | |
parent | f7f68c654a90c4d3e84121c4555a56682b02b2de (diff) | |
download | redis-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.c | 55 |
1 files changed, 31 insertions, 24 deletions
@@ -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. */ |