summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-09-16 10:32:58 +0200
committerantirez <antirez@gmail.com>2014-09-17 10:01:01 +0200
commitac76d56e6fa7206baae16c5de82e7c9e37ec3afc (patch)
tree2551af9a3e9e9386806f0c6a0d92359c21544643
parentef61ab6347155e3a154f7640378ca7d3ee20226c (diff)
downloadredis-ac76d56e6fa7206baae16c5de82e7c9e37ec3afc.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 3bc598f02..a7f32abae 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -602,6 +602,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;
@@ -691,6 +692,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.
@@ -715,9 +717,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);