AOF fixes in the context of replicaiton (when AOF is used by slave) and CONFIG SET appendonly yes/no.

This commit is contained in:
antirez 2011-12-15 16:07:49 +01:00
parent e074416be4
commit e7a2e7c1f7
4 changed files with 39 additions and 5 deletions

View File

@ -26,6 +26,7 @@ void stopAppendOnly(void) {
server.appendfd = -1; server.appendfd = -1;
server.appendseldb = -1; server.appendseldb = -1;
server.appendonly = 0; server.appendonly = 0;
server.aof_wait_rewrite = 0;
/* rewrite operation in progress? kill it, wait child exit */ /* rewrite operation in progress? kill it, wait child exit */
if (server.bgrewritechildpid != -1) { if (server.bgrewritechildpid != -1) {
int statloc; int statloc;
@ -35,6 +36,7 @@ void stopAppendOnly(void) {
/* reset the buffer accumulating changes while the child saves */ /* reset the buffer accumulating changes while the child saves */
sdsfree(server.bgrewritebuf); sdsfree(server.bgrewritebuf);
server.bgrewritebuf = sdsempty(); server.bgrewritebuf = sdsempty();
aofRemoveTempFile(server.bgrewritechildpid);
server.bgrewritechildpid = -1; server.bgrewritechildpid = -1;
} }
} }
@ -46,15 +48,18 @@ int startAppendOnly(void) {
server.lastfsync = time(NULL); server.lastfsync = time(NULL);
server.appendfd = open(server.appendfilename,O_WRONLY|O_APPEND|O_CREAT,0644); server.appendfd = open(server.appendfilename,O_WRONLY|O_APPEND|O_CREAT,0644);
if (server.appendfd == -1) { if (server.appendfd == -1) {
redisLog(REDIS_WARNING,"Used tried to switch on AOF via CONFIG, but I can't open the AOF file: %s",strerror(errno)); redisLog(REDIS_WARNING,"Redis needs to enable the AOF but can't open the append only file: %s",strerror(errno));
return REDIS_ERR; return REDIS_ERR;
} }
if (rewriteAppendOnlyFileBackground() == REDIS_ERR) { if (rewriteAppendOnlyFileBackground() == REDIS_ERR) {
server.appendonly = 0; server.appendonly = 0;
close(server.appendfd); close(server.appendfd);
redisLog(REDIS_WARNING,"User tried turning on AOF with CONFIG SET but I can't trigger a background AOF rewrite operation. Check the above logs for more info about the error."); redisLog(REDIS_WARNING,"Redis needs to enable the AOF but can't trigger a background AOF rewrite operation. Check the above logs for more info about the error.");
return REDIS_ERR; return REDIS_ERR;
} }
/* We correctly switched on AOF, now wait for the rerwite to be complete
* in order to append data on disk. */
server.aof_wait_rewrite = 1;
return REDIS_OK; return REDIS_OK;
} }
@ -219,9 +224,15 @@ sds catAppendOnlyExpireAtCommand(sds buf, struct redisCommand *cmd, robj *key, r
} }
void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc) { void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc) {
sds buf = sdsempty(); sds buf;
robj *tmpargv[3]; robj *tmpargv[3];
/* Return ASAP if we are writing a rewrite to finish in order to start
* appending to the Append Only File. */
if (server.aof_wait_rewrite) return;
buf = sdsempty();
/* The DB this command was targetting is not the same as the last command /* The DB this command was targetting is not the same as the last command
* we appendend. To issue a SELECT command is needed. */ * we appendend. To issue a SELECT command is needed. */
if (dictid != server.appendseldb) { if (dictid != server.appendseldb) {
@ -953,6 +964,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
} }
redisLog(REDIS_NOTICE, "Background AOF rewrite successful"); redisLog(REDIS_NOTICE, "Background AOF rewrite successful");
server.aof_wait_rewrite = 0;
/* Asynchronously close the overwritten AOF. */ /* Asynchronously close the overwritten AOF. */
if (oldfd != -1) bioCreateBackgroundJob(REDIS_BIO_CLOSE_FILE,(void*)(long)oldfd,NULL,NULL); if (oldfd != -1) bioCreateBackgroundJob(REDIS_BIO_CLOSE_FILE,(void*)(long)oldfd,NULL,NULL);
@ -972,4 +984,10 @@ cleanup:
server.bgrewritebuf = sdsempty(); server.bgrewritebuf = sdsempty();
aofRemoveTempFile(server.bgrewritechildpid); aofRemoveTempFile(server.bgrewritechildpid);
server.bgrewritechildpid = -1; server.bgrewritechildpid = -1;
/* If we were waiting for an AOF rewrite before to start appending
* to the AOF again (this happens both when the user switches on
* AOF with CONFIG SET, and after a slave with AOF enabled syncs with
* the master), but the rewrite failed (otherwise aof_wait_rewrite
* would be zero), we need to schedule a new one. */
if (server.aof_wait_rewrite) server.aofrewrite_scheduled = 1;
} }

View File

@ -880,6 +880,7 @@ void initServerConfig() {
server.auto_aofrewrite_min_size = REDIS_AUTO_AOFREWRITE_MIN_SIZE; server.auto_aofrewrite_min_size = REDIS_AUTO_AOFREWRITE_MIN_SIZE;
server.auto_aofrewrite_base_size = 0; server.auto_aofrewrite_base_size = 0;
server.aofrewrite_scheduled = 0; server.aofrewrite_scheduled = 0;
server.aof_wait_rewrite = 0;
server.lastfsync = time(NULL); server.lastfsync = time(NULL);
server.appendfd = -1; server.appendfd = -1;
server.appendseldb = -1; /* Make sure the first time will not match */ server.appendseldb = -1; /* Make sure the first time will not match */

View File

@ -547,6 +547,7 @@ struct redisServer {
off_t auto_aofrewrite_base_size;/* AOF size on latest startup or rewrite. */ off_t auto_aofrewrite_base_size;/* AOF size on latest startup or rewrite. */
off_t appendonly_current_size; /* AOF current size. */ off_t appendonly_current_size; /* AOF current size. */
int aofrewrite_scheduled; /* Rewrite once BGSAVE terminates. */ int aofrewrite_scheduled; /* Rewrite once BGSAVE terminates. */
int aof_wait_rewrite; /* Don't append to AOF before rewrite */
int shutdown_asap; /* SHUTDOWN needed */ int shutdown_asap; /* SHUTDOWN needed */
int activerehashing; int activerehashing;
char *requirepass; char *requirepass;

View File

@ -358,8 +358,22 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) {
server.master->authenticated = 1; server.master->authenticated = 1;
server.replstate = REDIS_REPL_CONNECTED; server.replstate = REDIS_REPL_CONNECTED;
redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Finished with success"); redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Finished with success");
/* Rewrite the AOF file now that the dataset changed. */ /* Restart the AOF subsystem now that we finished the sync. This
if (server.appendonly) rewriteAppendOnlyFileBackground(); * will trigger an AOF rewrite, and when done will start appending
* to the new file. */
if (server.appendonly) {
int retry = 10;
stopAppendOnly();
while (retry-- && startAppendOnly() == REDIS_ERR) {
redisLog(REDIS_WARNING,"Failed enabling the AOF after successful master synchrnization! Trying it again in one second.");
sleep(1);
}
if (!retry) {
redisLog(REDIS_WARNING,"FATAL: this slave instance finished the synchronization with its master, but the AOF can't be turned on. Exiting now.");
exit(1);
}
}
} }
return; return;