@@ -169,7 +169,7 @@ static void WalSndLoop(void);
169169static void InitWalSenderSlot (void );
170170static void WalSndKill (int code ,Datum arg );
171171static void XLogSend (bool * caughtup );
172- static XLogRecPtr GetStandbyFlushRecPtr (TimeLineID currentTLI );
172+ static XLogRecPtr GetStandbyFlushRecPtr (void );
173173static void IdentifySystem (void );
174174static void StartReplication (StartReplicationCmd * cmd );
175175static void ProcessStandbyMessage (void );
@@ -250,7 +250,7 @@ IdentifySystem(void)
250250if (am_cascading_walsender )
251251{
252252/* this also updates ThisTimeLineID */
253- logptr = GetStandbyFlushRecPtr (0 );
253+ logptr = GetStandbyFlushRecPtr ();
254254}
255255else
256256logptr = GetInsertRecPtr ();
@@ -423,7 +423,7 @@ StartReplication(StartReplicationCmd *cmd)
423423if (am_cascading_walsender )
424424{
425425/* this also updates ThisTimeLineID */
426- FlushPtr = GetStandbyFlushRecPtr (0 );
426+ FlushPtr = GetStandbyFlushRecPtr ();
427427}
428428else
429429FlushPtr = GetFlushRecPtr ();
@@ -1310,7 +1310,6 @@ static void
13101310XLogSend (bool * caughtup )
13111311{
13121312XLogRecPtr SendRqstPtr ;
1313- XLogRecPtr FlushPtr ;
13141313XLogRecPtr startptr ;
13151314XLogRecPtr endptr ;
13161315Size nbytes ;
@@ -1321,33 +1320,39 @@ XLogSend(bool *caughtup)
13211320return ;
13221321}
13231322
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 )
13481325{
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+ */
13491352bool becameHistoric = false;
13501353
1354+ SendRqstPtr = GetStandbyFlushRecPtr ();
1355+
13511356if (!RecoveryInProgress ())
13521357{
13531358/*
@@ -1361,7 +1366,8 @@ XLogSend(bool *caughtup)
13611366{
13621367/*
13631368 * 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.
13651371 */
13661372if (sendTimeLine != ThisTimeLineID )
13671373becameHistoric = true;
@@ -1391,8 +1397,24 @@ XLogSend(bool *caughtup)
13911397 (uint32 )sentPtr );
13921398
13931399sendTimeLineIsHistoric = true;
1400+
1401+ SendRqstPtr = sendTimeLineValidUpto ;
13941402}
13951403}
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+ }
13961418
13971419/*
13981420 * If this is a historic timeline and we've reached the point where we
@@ -1413,15 +1435,7 @@ XLogSend(bool *caughtup)
14131435return ;
14141436}
14151437
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? */
14251439Assert (XLByteLE (sentPtr ,SendRqstPtr ));
14261440if (XLByteLE (SendRqstPtr ,sentPtr ))
14271441{
@@ -1522,15 +1536,11 @@ XLogSend(bool *caughtup)
15221536 * can be sent to the standby. This should only be called when in recovery,
15231537 * ie. we're streaming to a cascaded standby.
15241538 *
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- *
15291539 * As a side-effect, ThisTimeLineID is updated to the TLI of the last
15301540 * replayed WAL record.
15311541 */
15321542static XLogRecPtr
1533- GetStandbyFlushRecPtr (TimeLineID currentTLI )
1543+ GetStandbyFlushRecPtr (void )
15341544{
15351545XLogRecPtr replayPtr ;
15361546TimeLineID replayTLI ;
@@ -1549,11 +1559,8 @@ GetStandbyFlushRecPtr(TimeLineID currentTLI)
15491559
15501560ThisTimeLineID = replayTLI ;
15511561
1552- if (currentTLI != replayTLI && currentTLI != 0 )
1553- return InvalidXLogRecPtr ;
1554-
15551562result = replayPtr ;
1556- if (receiveTLI == currentTLI && receivePtr > replayPtr )
1563+ if (receiveTLI == ThisTimeLineID && receivePtr > replayPtr )
15571564result = receivePtr ;
15581565
15591566return result ;