@@ -1274,14 +1274,10 @@ void backgroundSaveDoneHandlerDisk(int exitcode, int bysignal) {
12741274
12751275/* A background saving child (BGSAVE) terminated its work. Handle this.
12761276 * This function covers the case of RDB -> Salves socket transfers for
1277- * diskless replication.
1278- *
1279- * TODO:
1280- * 1) Read from the pipe the set of IDs which are fine. This should be
1281- * just an uint32_t with the len, and N pid_t elements.
1282- * 2) Close all the slaves in state REDIS_REPL_WAIT_BGSAVE_END but are
1283- * not reported as "transfer ok" by the child. */
1277+ * diskless replication. */
12841278void backgroundSaveDoneHandlerSocket (int exitcode , int bysignal ) {
1279+ uint64_t * ok_slaves ;
1280+
12851281 if (!bysignal && exitcode == 0 ) {
12861282 redisLog (REDIS_NOTICE ,
12871283 "Background RDB transfer terminated with success" );
@@ -1294,18 +1290,64 @@ void backgroundSaveDoneHandlerSocket(int exitcode, int bysignal) {
12941290 server .rdb_child_pid = -1 ;
12951291 server .rdb_child_type = REDIS_RDB_CHILD_TYPE_NONE ;
12961292 server .rdb_save_time_start = -1 ;
1297- /* Read the set of slave client IDs that currently received the full
1298- * RDB payload, closing all the slaves which are not among the ones
1299- * listed. */
1300-
1301- /* TODO ... */
13021293
1303- /* Close the pipe FDs. */
1294+ /* If the child returns an OK exit code, read the set of slave client
1295+ * IDs that received the full RDB payload, closing all the slaves
1296+ * which are not among the ones listed.
1297+ *
1298+ * If the process returned an error, consider the list of slaves that
1299+ * can continue to be emtpy, so that it's just a speical case of the
1300+ * normal code path. */
1301+ ok_slaves = zmalloc (sizeof (uint64_t )); /* Make space for the count. */
1302+ ok_slaves = 0 ;
1303+ if (!bysignal && exitcode == 0 ) {
1304+ int readlen = sizeof (uint64_t );
1305+
1306+ if (read (server .rdb_pipe_read_result_from_child , ok_slaves , readlen ) !=
1307+ readlen )
1308+ {
1309+ readlen = ok_slaves [0 ]* sizeof (uint64_t );
1310+
1311+ /* Make space for enough elements as specified by the first
1312+ * uint64_t element in the array. */
1313+ ok_slaves = zrealloc (ok_slaves ,sizeof (uint64_t )+ readlen );
1314+ if (readlen &&
1315+ read (server .rdb_pipe_read_result_from_child , ok_slaves + 1 ,
1316+ readlen ) != readlen )
1317+ {
1318+ ok_slaves [0 ] = 0 ;
1319+ }
1320+ }
1321+ }
13041322
1305- /* TODO ... */
1323+ close (server .rdb_pipe_read_result_from_child );
1324+ close (server .rdb_pipe_write_result_to_parent );
13061325
13071326 /* We can continue the replication process with all the slaves that
1308- * correctly received the full payload. */
1327+ * correctly received the full payload. Others are terminated. */
1328+ listNode * ln ;
1329+ listIter li ;
1330+
1331+ listRewind (server .slaves ,& li );
1332+ while ((ln = listNext (& li ))) {
1333+ redisClient * slave = ln -> value ;
1334+
1335+ if (slave -> replstate == REDIS_REPL_WAIT_BGSAVE_END ) {
1336+ uint64_t j ;
1337+
1338+ for (j = 1 ; j < ok_slaves [0 ]; j ++ ) {
1339+ if (slave -> id == ok_slaves [j ]) break ; /* Found in the OK list. */
1340+ }
1341+ if (j == ok_slaves [0 ]) {
1342+ redisLog (REDIS_WARNING ,
1343+ "Closing slave %llu: child->slave RDB transfer failed." ,
1344+ slave -> id );
1345+ freeClient (slave );
1346+ }
1347+ }
1348+ }
1349+ zfree (ok_slaves );
1350+
13091351 updateSlavesWaitingBgsave ((!bysignal && exitcode == 0 ) ? REDIS_OK : REDIS_ERR , REDIS_RDB_CHILD_TYPE_SOCKET );
13101352}
13111353
0 commit comments