@@ -662,6 +662,16 @@ typedef struct XLogCtlData
662662 */
663663bool SharedHotStandbyActive ;
664664
665+ /*
666+ * InstallXLogFileSegmentActive indicates whether the checkpointer should
667+ * arrange for future segments by recycling and/or PreallocXlogFiles().
668+ * Protected by ControlFileLock. Only the startup process changes it. If
669+ * true, anyone can use InstallXLogFileSegment(). If false, the startup
670+ * process owns the exclusive right to install segments, by reading from
671+ * the archive and possibly replacing existing files.
672+ */
673+ bool InstallXLogFileSegmentActive ;
674+
665675/*
666676 * SharedPromoteIsTriggered indicates if a standby promotion has been
667677 * triggered. Protected by info_lck.
@@ -921,6 +931,7 @@ static intXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
921931int reqLen ,XLogRecPtr targetRecPtr ,char * readBuf );
922932static bool WaitForWALToBecomeAvailable (XLogRecPtr RecPtr ,bool randAccess ,
923933bool fetching_ckpt ,XLogRecPtr tliRecPtr );
934+ static void XLogShutdownWalRcv (void );
924935static int emode_for_corrupt_record (int emode ,XLogRecPtr RecPtr );
925936static void XLogFileClose (void );
926937static void PreallocXlogFiles (XLogRecPtr endptr );
@@ -3625,8 +3636,8 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
36253636 * is false.)
36263637 *
36273638 * Returns true if the file was installed successfully. false indicates that
3628- * max_segno limit was exceeded,or an error occurred while renaming the
3629- * file into place.
3639+ * max_segno limit was exceeded,the startup process has disabled this
3640+ *function for now, or an error occurred while renaming the file into place.
36303641 */
36313642static bool
36323643InstallXLogFileSegment (XLogSegNo * segno ,char * tmppath ,
@@ -3638,6 +3649,11 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
36383649XLogFilePath (path ,ThisTimeLineID ,* segno ,wal_segment_size );
36393650
36403651LWLockAcquire (ControlFileLock ,LW_EXCLUSIVE );
3652+ if (!XLogCtl -> InstallXLogFileSegmentActive )
3653+ {
3654+ LWLockRelease (ControlFileLock );
3655+ return false;
3656+ }
36413657
36423658if (!find_free )
36433659{
@@ -3745,6 +3761,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
37453761 */
37463762if (source == XLOG_FROM_ARCHIVE )
37473763{
3764+ Assert (!XLogCtl -> InstallXLogFileSegmentActive );
37483765KeepFileRestoredFromArchive (path ,xlogfname );
37493766
37503767/*
@@ -3946,6 +3963,9 @@ PreallocXlogFiles(XLogRecPtr endptr)
39463963char path [MAXPGPATH ];
39473964uint64 offset ;
39483965
3966+ if (!XLogCtl -> InstallXLogFileSegmentActive )
3967+ return ;/* unlocked check says no */
3968+
39493969XLByteToPrevSeg (endptr ,_logSegNo ,wal_segment_size );
39503970offset = XLogSegmentOffset (endptr - 1 ,wal_segment_size );
39513971if (offset >= (uint32 ) (0.75 * wal_segment_size ))
@@ -4227,6 +4247,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
42274247 */
42284248if (wal_recycle &&
42294249* endlogSegNo <=recycleSegNo &&
4250+ XLogCtl -> InstallXLogFileSegmentActive && /* callee rechecks this */
42304251lstat (path ,& statbuf )== 0 && S_ISREG (statbuf .st_mode )&&
42314252InstallXLogFileSegment (endlogSegNo ,path ,
42324253 true,recycleSegNo ))
@@ -4240,7 +4261,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
42404261}
42414262else
42424263{
4243- /* No need for any more future segments... */
4264+ /* No need for any more future segments, or recycling failed ... */
42444265int rc ;
42454266
42464267ereport (DEBUG2 ,
@@ -5226,6 +5247,7 @@ XLOGShmemInit(void)
52265247XLogCtl -> XLogCacheBlck = XLOGbuffers - 1 ;
52275248XLogCtl -> SharedRecoveryState = RECOVERY_STATE_CRASH ;
52285249XLogCtl -> SharedHotStandbyActive = false;
5250+ XLogCtl -> InstallXLogFileSegmentActive = false;
52295251XLogCtl -> SharedPromoteIsTriggered = false;
52305252XLogCtl -> WalWriterSleeping = false;
52315253
@@ -5253,6 +5275,11 @@ BootStrapXLOG(void)
52535275struct timeval tv ;
52545276pg_crc32c crc ;
52555277
5278+ /* allow ordinary WAL segment creation, like StartupXLOG() would */
5279+ LWLockAcquire (ControlFileLock ,LW_EXCLUSIVE );
5280+ XLogCtl -> InstallXLogFileSegmentActive = true;
5281+ LWLockRelease (ControlFileLock );
5282+
52565283/*
52575284 * Select a hopefully-unique system identifier code for this installation.
52585285 * We use the result of gettimeofday(), including the fractional seconds
@@ -7619,7 +7646,7 @@ StartupXLOG(void)
76197646 * the startup checkpoint record. It will trump over the checkpoint and
76207647 * subsequent records if it's still alive when we start writing WAL.
76217648 */
7622- ShutdownWalRcv ();
7649+ XLogShutdownWalRcv ();
76237650
76247651/*
76257652 * Reset unlogged relations to the contents of their INIT fork. This is
@@ -7644,7 +7671,7 @@ StartupXLOG(void)
76447671 * recovery, e.g., timeline history file) from archive or pg_wal.
76457672 *
76467673 * Note that standby mode must be turned off after killing WAL receiver,
7647- * i.e., callingShutdownWalRcv ().
7674+ * i.e., callingXLogShutdownWalRcv ().
76487675 */
76497676Assert (!WalRcvStreaming ());
76507677StandbyMode = false;
@@ -7709,6 +7736,14 @@ StartupXLOG(void)
77097736 */
77107737oldestActiveXID = PrescanPreparedTransactions (NULL ,NULL );
77117738
7739+ /*
7740+ * Allow ordinary WAL segment creation before any exitArchiveRecovery(),
7741+ * which sometimes creates a segment, and after the last ReadRecord().
7742+ */
7743+ LWLockAcquire (ControlFileLock ,LW_EXCLUSIVE );
7744+ XLogCtl -> InstallXLogFileSegmentActive = true;
7745+ LWLockRelease (ControlFileLock );
7746+
77127747/*
77137748 * Consider whether we need to assign a new timeline ID.
77147749 *
@@ -12378,7 +12413,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1237812413 */
1237912414if (StandbyMode && CheckForStandbyTrigger ())
1238012415{
12381- ShutdownWalRcv ();
12416+ XLogShutdownWalRcv ();
1238212417return false;
1238312418}
1238412419
@@ -12426,7 +12461,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1242612461 * WAL that we restore from archive.
1242712462 */
1242812463if (WalRcvStreaming ())
12429- ShutdownWalRcv ();
12464+ XLogShutdownWalRcv ();
1243012465
1243112466/*
1243212467 * Before we sleep, re-scan for possible new timelines if
@@ -12553,7 +12588,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1255312588 */
1255412589if (pendingWalRcvRestart && !startWalReceiver )
1255512590{
12556- ShutdownWalRcv ();
12591+ XLogShutdownWalRcv ();
1255712592
1255812593/*
1255912594 * Re-scan for possible new timelines if we were
@@ -12603,6 +12638,9 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1260312638tli ,curFileTLI );
1260412639}
1260512640curFileTLI = tli ;
12641+ LWLockAcquire (ControlFileLock ,LW_EXCLUSIVE );
12642+ XLogCtl -> InstallXLogFileSegmentActive = true;
12643+ LWLockRelease (ControlFileLock );
1260612644RequestXLogStreaming (tli ,ptr ,PrimaryConnInfo ,
1260712645PrimarySlotName ,
1260812646wal_receiver_create_temp_slot );
@@ -12770,6 +12808,17 @@ StartupRequestWalReceiverRestart(void)
1277012808}
1277112809}
1277212810
12811+ /* Thin wrapper around ShutdownWalRcv(). */
12812+ static void
12813+ XLogShutdownWalRcv (void )
12814+ {
12815+ ShutdownWalRcv ();
12816+
12817+ LWLockAcquire (ControlFileLock ,LW_EXCLUSIVE );
12818+ XLogCtl -> InstallXLogFileSegmentActive = false;
12819+ LWLockRelease (ControlFileLock );
12820+ }
12821+
1277312822/*
1277412823 * Determine what log level should be used to report a corrupt WAL record
1277512824 * in the current WAL page, previously read by XLogPageRead().