summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-09-16 10:32:58 +0200
committerantirez <antirez@gmail.com>2014-09-16 10:41:15 +0200
commit9faeff02151c8d6f0c943feb7e771d0ae292ada9 (patch)
tree49a220c9dde83e26940d1c6196ae8d16b949d48b
parentfbd9dc6039a0cae03472839b3e21657915eac48d (diff)
downloadredis-9faeff02151c8d6f0c943feb7e771d0ae292ada9.tar.gz
On AOF end of file, truncate the AOF to last valid command.
Recently we introduced the ability to load truncated AOFs, but unfortuantely the support was broken since the server, after loading the truncated AOF, continues appending to the file that is corrupted at the end. The problem is fixed only in the next AOF rewrite. This commit fixes the issue by truncating the AOF to the last valid opcode, and aborting if it is not possible to truncate the file correctly.
-rw-r--r--src/aof.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/aof.c b/src/aof.c
index 9231812ef..350ea8d93 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -558,6 +558,7 @@ int loadAppendOnlyFile(char *filename) {
struct redis_stat sb;
int old_aof_state = server.aof_state;
long loops = 0;
+ off_t valid_up_to = 0; /* Offset of the latest well-formed command loaded. */
if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {
server.aof_current_size = 0;
@@ -647,6 +648,7 @@ int loadAppendOnlyFile(char *filename) {
/* Clean up. Command code may have changed argv/argc so we use the
* argv/argc of the client instead of the local variables. */
freeFakeClientArgv(fakeClient);
+ if (server.aof_load_truncated) valid_up_to = ftello(fp);
}
/* This point can only be reached when EOF is reached without errors.
@@ -671,9 +673,20 @@ readerr: /* Read error. If feof(fp) is true, fall through to unexpected EOF. */
uxeof: /* Unexpected AOF end of file. */
if (server.aof_load_truncated) {
redisLog(REDIS_WARNING,"!!! Warning: short read while loading the AOF file !!!");
- redisLog(REDIS_WARNING,
- "AOF loaded anyway because aof-load-truncated is enabled");
- goto loaded_ok;
+ redisLog(REDIS_WARNING,"!!! Truncating the AOF at offset %llu !!!",
+ (unsigned long long) valid_up_to);
+ if (valid_up_to == -1 || truncate(filename,valid_up_to) == -1) {
+ if (valid_up_to == -1) {
+ redisLog(REDIS_WARNING,"Last valid command offset is invalid");
+ } else {
+ redisLog(REDIS_WARNING,"Error truncating the AOF file: %s",
+ strerror(errno));
+ }
+ } else {
+ redisLog(REDIS_WARNING,
+ "AOF loaded anyway because aof-load-truncated is enabled");
+ goto loaded_ok;
+ }
}
redisLog(REDIS_WARNING,"Unexpected end of file reading the append only file. 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.");
exit(1);