@@ -169,7 +169,7 @@ static void WalSndLoop(void);
169
169
static void InitWalSenderSlot (void );
170
170
static void WalSndKill (int code , Datum arg );
171
171
static void XLogSend (bool * caughtup );
172
- static XLogRecPtr GetStandbyFlushRecPtr (TimeLineID currentTLI );
172
+ static XLogRecPtr GetStandbyFlushRecPtr (void );
173
173
static void IdentifySystem (void );
174
174
static void StartReplication (StartReplicationCmd * cmd );
175
175
static void ProcessStandbyMessage (void );
@@ -250,7 +250,7 @@ IdentifySystem(void)
250
250
if (am_cascading_walsender )
251
251
{
252
252
/* this also updates ThisTimeLineID */
253
- logptr = GetStandbyFlushRecPtr (0 );
253
+ logptr = GetStandbyFlushRecPtr ();
254
254
}
255
255
else
256
256
logptr = GetInsertRecPtr ();
@@ -423,7 +423,7 @@ StartReplication(StartReplicationCmd *cmd)
423
423
if (am_cascading_walsender )
424
424
{
425
425
/* this also updates ThisTimeLineID */
426
- FlushPtr = GetStandbyFlushRecPtr (0 );
426
+ FlushPtr = GetStandbyFlushRecPtr ();
427
427
}
428
428
else
429
429
FlushPtr = GetFlushRecPtr ();
@@ -1310,7 +1310,6 @@ static void
1310
1310
XLogSend (bool * caughtup )
1311
1311
{
1312
1312
XLogRecPtr SendRqstPtr ;
1313
- XLogRecPtr FlushPtr ;
1314
1313
XLogRecPtr startptr ;
1315
1314
XLogRecPtr endptr ;
1316
1315
Size nbytes ;
@@ -1321,33 +1320,39 @@ XLogSend(bool *caughtup)
1321
1320
return ;
1322
1321
}
1323
1322
1324
- /*
1325
- * Attempt to send all data that's already been written out and fsync'd to
1326
- * disk. We cannot go further than what's been written out given the
1327
- * current implementation of XLogRead(). And in any case it's unsafe to
1328
- * send WAL that is not securely down to disk on the master: if the master
1329
- * subsequently crashes and restarts, slaves must not have applied any WAL
1330
- * that gets lost on the master.
1331
- */
1332
- if (am_cascading_walsender )
1333
- FlushPtr = GetStandbyFlushRecPtr (sendTimeLine );
1334
- else
1335
- FlushPtr = GetFlushRecPtr ();
1336
-
1337
- /*
1338
- * In a cascading standby, the current recovery target timeline can
1339
- * change, or we can be promoted. In either case, the current timeline
1340
- * becomes historic. We need to detect that so that we don't try to stream
1341
- * past the point where we switched to another timeline. It's checked
1342
- * after calculating FlushPtr, to avoid a race condition: if the timeline
1343
- * becomes historic just after we checked that it was still current, it
1344
- * should still be OK to stream it up to the FlushPtr that was calculated
1345
- * before it became historic.
1346
- */
1347
- if (!sendTimeLineIsHistoric && am_cascading_walsender )
1323
+ /* Figure out how far we can safely send the WAL. */
1324
+ if (sendTimeLineIsHistoric )
1348
1325
{
1326
+ /*
1327
+ * Streaming an old timeline timeline that's in this server's history,
1328
+ * but is not the one we're currently inserting or replaying. It can
1329
+ * be streamed up to the point where we switched off that timeline.
1330
+ */
1331
+ SendRqstPtr = sendTimeLineValidUpto ;
1332
+ }
1333
+ else if (am_cascading_walsender )
1334
+ {
1335
+ /*
1336
+ * Streaming the latest timeline on a standby.
1337
+ *
1338
+ * Attempt to send all WAL that has already been replayed, so that
1339
+ * we know it's valid. If we're receiving WAL through streaming
1340
+ * replication, it's also OK to send any WAL that has been received
1341
+ * but not replayed.
1342
+ *
1343
+ * The timeline we're recovering from can change, or we can be
1344
+ * promoted. In either case, the current timeline becomes historic.
1345
+ * We need to detect that so that we don't try to stream past the
1346
+ * point where we switched to another timeline. We check for promotion
1347
+ * or timeline switch after calculating FlushPtr, to avoid a race
1348
+ * condition: if the timeline becomes historic just after we checked
1349
+ * that it was still current, it's still be OK to stream it up to the
1350
+ * FlushPtr that was calculated before it became historic.
1351
+ */
1349
1352
bool becameHistoric = false;
1350
1353
1354
+ SendRqstPtr = GetStandbyFlushRecPtr ();
1355
+
1351
1356
if (!RecoveryInProgress ())
1352
1357
{
1353
1358
/*
@@ -1361,7 +1366,8 @@ XLogSend(bool *caughtup)
1361
1366
{
1362
1367
/*
1363
1368
* Still a cascading standby. But is the timeline we're sending
1364
- * still the one recovery is recovering from?
1369
+ * still the one recovery is recovering from? ThisTimeLineID was
1370
+ * updated by the GetStandbyFlushRecPtr() call above.
1365
1371
*/
1366
1372
if (sendTimeLine != ThisTimeLineID )
1367
1373
becameHistoric = true;
@@ -1391,8 +1397,24 @@ XLogSend(bool *caughtup)
1391
1397
(uint32 ) sentPtr );
1392
1398
1393
1399
sendTimeLineIsHistoric = true;
1400
+
1401
+ SendRqstPtr = sendTimeLineValidUpto ;
1394
1402
}
1395
1403
}
1404
+ else
1405
+ {
1406
+ /*
1407
+ * Streaming the current timeline on a master.
1408
+ *
1409
+ * Attempt to send all data that's already been written out and
1410
+ * fsync'd to disk. We cannot go further than what's been written out
1411
+ * given the current implementation of XLogRead(). And in any case
1412
+ * it's unsafe to send WAL that is not securely down to disk on the
1413
+ * master: if the master subsequently crashes and restarts, slaves
1414
+ * must not have applied any WAL that gets lost on the master.
1415
+ */
1416
+ SendRqstPtr = GetFlushRecPtr ();
1417
+ }
1396
1418
1397
1419
/*
1398
1420
* If this is a historic timeline and we've reached the point where we
@@ -1413,15 +1435,7 @@ XLogSend(bool *caughtup)
1413
1435
return ;
1414
1436
}
1415
1437
1416
- /*
1417
- * Stream up to the point known to be flushed to disk, or to the end of
1418
- * this timeline, whichever comes first.
1419
- */
1420
- if (sendTimeLineIsHistoric && XLByteLT (sendTimeLineValidUpto , FlushPtr ))
1421
- SendRqstPtr = sendTimeLineValidUpto ;
1422
- else
1423
- SendRqstPtr = FlushPtr ;
1424
-
1438
+ /* Do we have any work to do? */
1425
1439
Assert (XLByteLE (sentPtr , SendRqstPtr ));
1426
1440
if (XLByteLE (SendRqstPtr , sentPtr ))
1427
1441
{
@@ -1522,15 +1536,11 @@ XLogSend(bool *caughtup)
1522
1536
* can be sent to the standby. This should only be called when in recovery,
1523
1537
* ie. we're streaming to a cascaded standby.
1524
1538
*
1525
- * If currentTLI is non-zero, the function returns the point that the WAL on
1526
- * the given timeline has been flushed upto. If recovery has already switched
1527
- * to a different timeline, InvalidXLogRecPtr is returned.
1528
- *
1529
1539
* As a side-effect, ThisTimeLineID is updated to the TLI of the last
1530
1540
* replayed WAL record.
1531
1541
*/
1532
1542
static XLogRecPtr
1533
- GetStandbyFlushRecPtr (TimeLineID currentTLI )
1543
+ GetStandbyFlushRecPtr (void )
1534
1544
{
1535
1545
XLogRecPtr replayPtr ;
1536
1546
TimeLineID replayTLI ;
@@ -1549,11 +1559,8 @@ GetStandbyFlushRecPtr(TimeLineID currentTLI)
1549
1559
1550
1560
ThisTimeLineID = replayTLI ;
1551
1561
1552
- if (currentTLI != replayTLI && currentTLI != 0 )
1553
- return InvalidXLogRecPtr ;
1554
-
1555
1562
result = replayPtr ;
1556
- if (receiveTLI == currentTLI && receivePtr > replayPtr )
1563
+ if (receiveTLI == ThisTimeLineID && receivePtr > replayPtr )
1557
1564
result = receivePtr ;
1558
1565
1559
1566
return result ;
0 commit comments