summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-10-15 09:46:45 +0200
committerantirez <antirez@gmail.com>2014-10-15 09:46:49 +0200
commitfbe7545545269ab47f98be70ca41435a30043fe2 (patch)
treedb72a2f2670228116ff4484b7cc9fd8d785f6844
parent2a436aaeabcc9cd5ad625613e7882df9495ab04b (diff)
downloadredis-fbe7545545269ab47f98be70ca41435a30043fe2.tar.gz
Diskless replication: child writes report to parent.
-rw-r--r--src/rdb.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/rdb.c b/src/rdb.c
index 8c50610e4..f2eae0234 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -1328,6 +1328,7 @@ void backgroundSaveDoneHandler(int exitcode, int bysignal) {
* that are currently in REDIS_REPL_WAIT_BGSAVE_START state. */
int rdbSaveToSlavesSockets(void) {
int *fds;
+ uint64_t *clientids;
int numfds;
listNode *ln;
listIter li;
@@ -1347,6 +1348,10 @@ int rdbSaveToSlavesSockets(void) {
/* Collect the file descriptors of the slaves we want to transfer
* the RDB to, which are i WAIT_BGSAVE_START state. */
fds = zmalloc(sizeof(int)*listLength(server.slaves));
+ /* We also allocate an array of corresponding client IDs. This will
+ * be useful for the child process in order to build the report
+ * (sent via unix pipe) that will be sent to the parent. */
+ clientids = zmalloc(sizeof(uint64_t)*listLength(server.slaves));
numfds = 0;
listRewind(server.slaves,&li);
@@ -1354,6 +1359,7 @@ int rdbSaveToSlavesSockets(void) {
redisClient *slave = ln->value;
if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) {
+ clientids[numfds] = slave->id;
fds[numfds++] = slave->fd;
slave->replstate = REDIS_REPL_WAIT_BGSAVE_END;
}
@@ -1381,10 +1387,44 @@ int rdbSaveToSlavesSockets(void) {
"RDB: %zu MB of memory used by copy-on-write",
private_dirty/(1024*1024));
}
+
+ /* If we are returning OK, at least one slave was served
+ * with the RDB file as expected, so we need to send a report
+ * to the parent via the pipe. The format of the message is:
+ * just an array of uint64_t integers (to avoid alignment concerns),
+ * where the first element is the number of uint64_t elements
+ * that follows, representing slave client IDs that were
+ * successfully served. */
+ void *msg = zmalloc(sizeof(uint64_t)*(1+numfds));
+ uint64_t *len = msg;
+ uint64_t *ids = len+1;
+ int j, msglen;
+
+ *len = 0;
+ for (j = 0; j < numfds; j++) {
+ /* No error? Add it. */
+ if (slave_sockets.io.fdset.state[j] == 0) {
+ ids[*len] = clientids[j];
+ (*len)++;
+ }
+ }
+
+ /* Write the message to the parent. If we have no good slaves or
+ * we are unable to transfer the message to the parent, we exit
+ * with an error so that the parent will abort the replication
+ * process with all the childre that were waiting. */
+ msglen = sizeof(uint64_t)*(1+(*len));
+ if (*len == 0 ||
+ write(server.rdb_pipe_write_result_to_parent,msg,msglen)
+ != msglen)
+ {
+ retval = REDIS_ERR;
+ }
}
exitFromChild((retval == REDIS_OK) ? 0 : 1);
} else {
/* Parent */
+ zfree(clientids); /* Not used by parent. Free ASAP. */
server.stat_fork_time = ustime()-start;
server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */
latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000);