This function is called at the end of every background saving, * or when the replication RDB transfer strategy is modified from * disk to socket or the other way around. * * The goal of this function is to handle slaves waiting for a successful * background saving in order to perform non-blocking synchronization, and * to schedule a new BGSAVE if there are slaves that attached while a * BGS
| 2097 | * The 'type' argument is the type of the child that terminated |
| 2098 | * (if it had a disk or socket target). */ |
| 2099 | void updateSlavesWaitingBgsave(int bgsaveerr, int type) |
| 2100 | { |
| 2101 | listNode *ln; |
| 2102 | listIter li; |
| 2103 | serverAssert(GlobalLocksAcquired()); |
| 2104 | |
| 2105 | listRewind(g_pserver->slaves,&li); |
| 2106 | while((ln = listNext(&li))) { |
| 2107 | client *replica = (client*)ln->value; |
| 2108 | |
| 2109 | std::unique_lock<fastlock> ul(replica->lock); |
| 2110 | |
| 2111 | if (replica->replstate == SLAVE_STATE_WAIT_BGSAVE_END) { |
| 2112 | struct redis_stat buf; |
| 2113 | |
| 2114 | if (bgsaveerr != C_OK) { |
| 2115 | ul.unlock(); |
| 2116 | freeClientAsync(replica); |
| 2117 | serverLog(LL_WARNING,"SYNC failed. BGSAVE child returned an error"); |
| 2118 | continue; |
| 2119 | } |
| 2120 | |
| 2121 | /* If this was an RDB on disk save, we have to prepare to send |
| 2122 | * the RDB from disk to the replica socket. Otherwise if this was |
| 2123 | * already an RDB -> Slaves socket transfer, used in the case of |
| 2124 | * diskless replication, our work is trivial, we can just put |
| 2125 | * the replica online. */ |
| 2126 | if (type == RDB_CHILD_TYPE_SOCKET) { |
| 2127 | serverLog(LL_NOTICE, |
| 2128 | "Streamed RDB transfer with replica %s succeeded (socket). Waiting for REPLCONF ACK from slave to enable streaming", |
| 2129 | replicationGetSlaveName(replica)); |
| 2130 | /* Note: we wait for a REPLCONF ACK message from the replica in |
| 2131 | * order to really put it online (install the write handler |
| 2132 | * so that the accumulated data can be transferred). However |
| 2133 | * we change the replication state ASAP, since our slave |
| 2134 | * is technically online now. |
| 2135 | * |
| 2136 | * So things work like that: |
| 2137 | * |
| 2138 | * 1. We end trasnferring the RDB file via socket. |
| 2139 | * 2. The replica is put ONLINE but the write handler |
| 2140 | * is not installed. |
| 2141 | * 3. The replica however goes really online, and pings us |
| 2142 | * back via REPLCONF ACK commands. |
| 2143 | * 4. Now we finally install the write handler, and send |
| 2144 | * the buffers accumulated so far to the replica. |
| 2145 | * |
| 2146 | * But why we do that? Because the replica, when we stream |
| 2147 | * the RDB directly via the socket, must detect the RDB |
| 2148 | * EOF (end of file), that is a special random string at the |
| 2149 | * end of the RDB (for streamed RDBs we don't know the length |
| 2150 | * in advance). Detecting such final EOF string is much |
| 2151 | * simpler and less CPU intensive if no more data is sent |
| 2152 | * after such final EOF. So we don't want to glue the end of |
| 2153 | * the RDB trasfer with the start of the other replication |
| 2154 | * data. */ |
| 2155 | replica->replstate = SLAVE_STATE_ONLINE; |
| 2156 | replica->repl_put_online_on_ack = 1; |
no test coverage detected