summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/aof.c7
-rw-r--r--src/rdb.c28
-rw-r--r--src/server.c23
-rw-r--r--src/server.h1
4 files changed, 51 insertions, 8 deletions
diff --git a/src/aof.c b/src/aof.c
index aa726d33b..6a92a0cd9 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -251,7 +251,10 @@ int startAppendOnly(void) {
strerror(errno));
return C_ERR;
}
- if (rewriteAppendOnlyFileBackground() == C_ERR) {
+ if (server.rdb_child_pid != -1) {
+ server.aof_rewrite_scheduled = 1;
+ serverLog(LL_WARNING,"AOF was enabled but there is already a child process saving an RDB file on disk. An AOF background was scheduled to start when possible.");
+ } else if (rewriteAppendOnlyFileBackground() == C_ERR) {
close(server.aof_fd);
serverLog(LL_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 C_ERR;
@@ -1273,7 +1276,7 @@ int rewriteAppendOnlyFileBackground(void) {
pid_t childpid;
long long start;
- if (server.aof_child_pid != -1) return C_ERR;
+ if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;
if (aofCreatePipes() != C_OK) return C_ERR;
start = ustime();
if ((childpid = fork()) == 0) {
diff --git a/src/rdb.c b/src/rdb.c
index 3b7cec6d7..859297943 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -997,7 +997,7 @@ int rdbSaveBackground(char *filename) {
pid_t childpid;
long long start;
- if (server.rdb_child_pid != -1) return C_ERR;
+ if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;
server.dirty_before_bgsave = server.dirty;
server.lastbgsave_try = time(NULL);
@@ -1687,7 +1687,7 @@ int rdbSaveToSlavesSockets(void) {
long long start;
int pipefds[2];
- if (server.rdb_child_pid != -1) return C_ERR;
+ if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;
/* Before to fork, create a pipe that will be used in order to
* send back to the parent the IDs of the slaves that successfully
@@ -1842,11 +1842,33 @@ void saveCommand(client *c) {
}
}
+/* BGSAVE [SCHEDULE] */
void bgsaveCommand(client *c) {
+ int schedule = 0;
+
+ /* The SCHEDULE option changes the behavior of BGSAVE when an AOF rewrite
+ * is in progress. Instead of returning an error a BGSAVE gets scheduled. */
+ if (c->argc > 1) {
+ if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"schedule")) {
+ schedule = 1;
+ } else {
+ addReply(c,shared.syntaxerr);
+ return;
+ }
+ }
+
if (server.rdb_child_pid != -1) {
addReplyError(c,"Background save already in progress");
} else if (server.aof_child_pid != -1) {
- addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress");
+ if (schedule) {
+ server.rdb_bgsave_scheduled = 1;
+ addReplyStatus(c,"Background saving scheduled");
+ } else {
+ addReplyError(c,
+ "An AOF log rewriting in progress: can't BGSAVE right now. "
+ "Use BGSAVE SCHEDULE in order to schedule a BGSAVE whenver "
+ "possible.");
+ }
} else if (rdbSaveBackground(server.rdb_filename) == C_OK) {
addReplyStatus(c,"Background saving started");
} else {
diff --git a/src/server.c b/src/server.c
index abb98edfd..f9806d280 100644
--- a/src/server.c
+++ b/src/server.c
@@ -233,7 +233,7 @@ struct redisCommand redisCommandTable[] = {
{"ping",pingCommand,-1,"tF",0,NULL,0,0,0,0,0},
{"echo",echoCommand,2,"F",0,NULL,0,0,0,0,0},
{"save",saveCommand,1,"as",0,NULL,0,0,0,0,0},
- {"bgsave",bgsaveCommand,1,"a",0,NULL,0,0,0,0,0},
+ {"bgsave",bgsaveCommand,-1,"a",0,NULL,0,0,0,0,0},
{"bgrewriteaof",bgrewriteaofCommand,1,"a",0,NULL,0,0,0,0,0},
{"shutdown",shutdownCommand,-1,"alt",0,NULL,0,0,0,0,0},
{"lastsave",lastsaveCommand,1,"RF",0,NULL,0,0,0,0,0},
@@ -1113,8 +1113,8 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
/* Clear the paused clients flag if needed. */
clientsArePaused(); /* Don't check return value, just use the side effect. */
- /* Replication cron function -- used to reconnect to master and
- * to detect transfer failures. */
+ /* Replication cron function -- used to reconnect to master,
+ * detect transfer failures, start background RDB transfers and so forth. */
run_with_period(1000) replicationCron();
/* Run the Redis Cluster cron. */
@@ -1132,6 +1132,22 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
migrateCloseTimedoutSockets();
}
+ /* Start a scheduled BGSAVE if the corresponding flag is set. This is
+ * useful when we are forced to postpone a BGSAVE because an AOF
+ * rewrite is in progress.
+ *
+ * Note: this code must be after the replicationCron() call above so
+ * make sure when refactoring this file to keep this order. This is useful
+ * because we want to give priority to RDB savings for replication. */
+ if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 &&
+ server.rdb_bgsave_scheduled &&
+ (server.unixtime-server.lastbgsave_try > CONFIG_BGSAVE_RETRY_DELAY ||
+ server.lastbgsave_status == C_OK))
+ {
+ if (rdbSaveBackground(server.rdb_filename) == C_OK)
+ server.rdb_bgsave_scheduled = 0;
+ }
+
server.cronloops++;
return 1000/server.hz;
}
@@ -1762,6 +1778,7 @@ void initServer(void) {
server.rdb_child_pid = -1;
server.aof_child_pid = -1;
server.rdb_child_type = RDB_CHILD_TYPE_NONE;
+ server.rdb_bgsave_scheduled = 0;
aofRewriteBufferReset();
server.aof_buf = sdsempty();
server.lastsave = time(NULL); /* At startup we consider the DB saved. */
diff --git a/src/server.h b/src/server.h
index 4e34453e5..534b59bd5 100644
--- a/src/server.h
+++ b/src/server.h
@@ -918,6 +918,7 @@ struct redisServer {
time_t lastbgsave_try; /* Unix time of last attempted bgsave */
time_t rdb_save_time_last; /* Time used by last RDB save run. */
time_t rdb_save_time_start; /* Current RDB save start time. */
+ int rdb_bgsave_scheduled; /* BGSAVE when possible if true. */
int rdb_child_type; /* Type of save by active child. */
int lastbgsave_status; /* C_OK or C_ERR */
int stop_writes_on_bgsave_err; /* Don't allow writes if can't BGSAVE */