@@ -816,9 +816,13 @@ static XLogSource readSource = XLOG_FROM_ANY;
816816 * currently have a WAL file open. If lastSourceFailed is set, our last
817817 * attempt to read from currentSource failed, and we should try another source
818818 * next.
819+ *
820+ * pendingWalRcvRestart is set when a config change occurs that requires a
821+ * walreceiver restart. This is only valid in XLOG_FROM_STREAM state.
819822 */
820823static XLogSource currentSource = XLOG_FROM_ANY ;
821824static bool lastSourceFailed = false;
825+ static bool pendingWalRcvRestart = false;
822826
823827typedef struct XLogPageReadPrivate
824828{
@@ -11905,6 +11909,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1190511909 for (;;)
1190611910 {
1190711911 XLogSource oldSource = currentSource ;
11912+ bool startWalReceiver = false;
1190811913
1190911914 /*
1191011915 * First check if we failed to read from the current source, and
@@ -11939,54 +11944,11 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1193911944 return false;
1194011945
1194111946 /*
11942- * If primary_conninfo is set, launch walreceiver to try
11943- * to stream the missing WAL.
11944- *
11945- * If fetching_ckpt is true, RecPtr points to the initial
11946- * checkpoint location. In that case, we use RedoStartLSN
11947- * as the streaming start position instead of RecPtr, so
11948- * that when we later jump backwards to start redo at
11949- * RedoStartLSN, we will have the logs streamed already.
11950- */
11951- if (PrimaryConnInfo && strcmp (PrimaryConnInfo , "" ) != 0 )
11952- {
11953- XLogRecPtr ptr ;
11954- TimeLineID tli ;
11955-
11956- if (fetching_ckpt )
11957- {
11958- ptr = RedoStartLSN ;
11959- tli = ControlFile -> checkPointCopy .ThisTimeLineID ;
11960- }
11961- else
11962- {
11963- ptr = RecPtr ;
11964-
11965- /*
11966- * Use the record begin position to determine the
11967- * TLI, rather than the position we're reading.
11968- */
11969- tli = tliOfPointInHistory (tliRecPtr , expectedTLEs );
11970-
11971- if (curFileTLI > 0 && tli < curFileTLI )
11972- elog (ERROR , "according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u" ,
11973- (uint32 ) (tliRecPtr >> 32 ),
11974- (uint32 ) tliRecPtr ,
11975- tli , curFileTLI );
11976- }
11977- curFileTLI = tli ;
11978- RequestXLogStreaming (tli , ptr , PrimaryConnInfo ,
11979- PrimarySlotName ,
11980- wal_receiver_create_temp_slot );
11981- receivedUpto = 0 ;
11982- }
11983-
11984- /*
11985- * Move to XLOG_FROM_STREAM state in either case. We'll
11986- * get immediate failure if we didn't launch walreceiver,
11987- * and move on to the next state.
11947+ * Move to XLOG_FROM_STREAM state, and set to start a
11948+ * walreceiver if necessary.
1198811949 */
1198911950 currentSource = XLOG_FROM_STREAM ;
11951+ startWalReceiver = true;
1199011952 break ;
1199111953
1199211954 case XLOG_FROM_STREAM :
@@ -12138,7 +12100,71 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1213812100 Assert (StandbyMode );
1213912101
1214012102 /*
12141- * Check if WAL receiver is still active.
12103+ * First, shutdown walreceiver if its restart has been
12104+ * requested -- but no point if we're already slated for
12105+ * starting it.
12106+ */
12107+ if (pendingWalRcvRestart && !startWalReceiver )
12108+ {
12109+ ShutdownWalRcv ();
12110+
12111+ /*
12112+ * Re-scan for possible new timelines if we were
12113+ * requested to recover to the latest timeline.
12114+ */
12115+ if (recoveryTargetTimeLineGoal ==
12116+ RECOVERY_TARGET_TIMELINE_LATEST )
12117+ rescanLatestTimeLine ();
12118+
12119+ startWalReceiver = true;
12120+ }
12121+ pendingWalRcvRestart = false;
12122+
12123+ /*
12124+ * Launch walreceiver if needed.
12125+ *
12126+ * If fetching_ckpt is true, RecPtr points to the initial
12127+ * checkpoint location. In that case, we use RedoStartLSN
12128+ * as the streaming start position instead of RecPtr, so
12129+ * that when we later jump backwards to start redo at
12130+ * RedoStartLSN, we will have the logs streamed already.
12131+ */
12132+ if (startWalReceiver &&
12133+ PrimaryConnInfo && strcmp (PrimaryConnInfo , "" ) != 0 )
12134+ {
12135+ XLogRecPtr ptr ;
12136+ TimeLineID tli ;
12137+
12138+ if (fetching_ckpt )
12139+ {
12140+ ptr = RedoStartLSN ;
12141+ tli = ControlFile -> checkPointCopy .ThisTimeLineID ;
12142+ }
12143+ else
12144+ {
12145+ ptr = RecPtr ;
12146+
12147+ /*
12148+ * Use the record begin position to determine the
12149+ * TLI, rather than the position we're reading.
12150+ */
12151+ tli = tliOfPointInHistory (tliRecPtr , expectedTLEs );
12152+
12153+ if (curFileTLI > 0 && tli < curFileTLI )
12154+ elog (ERROR , "according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u" ,
12155+ (uint32 ) (tliRecPtr >> 32 ),
12156+ (uint32 ) tliRecPtr ,
12157+ tli , curFileTLI );
12158+ }
12159+ curFileTLI = tli ;
12160+ RequestXLogStreaming (tli , ptr , PrimaryConnInfo ,
12161+ PrimarySlotName ,
12162+ wal_receiver_create_temp_slot );
12163+ receivedUpto = 0 ;
12164+ }
12165+
12166+ /*
12167+ * Check if WAL receiver is active or wait to start up.
1214212168 */
1214312169 if (!WalRcvStreaming ())
1214412170 {
@@ -12266,6 +12292,22 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1226612292 return false; /* not reached */
1226712293}
1226812294
12295+ /*
12296+ * Set flag to signal the walreceiver to restart. (The startup process calls
12297+ * this on noticing a relevant configuration change.)
12298+ */
12299+ void
12300+ StartupRequestWalReceiverRestart (void )
12301+ {
12302+ if (currentSource == XLOG_FROM_STREAM && WalRcvRunning ())
12303+ {
12304+ ereport (LOG ,
12305+ (errmsg ("wal receiver process shutdown requested" )));
12306+
12307+ pendingWalRcvRestart = true;
12308+ }
12309+ }
12310+
1226912311/*
1227012312 * Determine what log level should be used to report a corrupt WAL record
1227112313 * in the current WAL page, previously read by XLogPageRead().
0 commit comments