@@ -662,6 +662,16 @@ typedef struct XLogCtlData
662
662
*/
663
663
bool SharedHotStandbyActive ;
664
664
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
+
665
675
/*
666
676
* SharedPromoteIsTriggered indicates if a standby promotion has been
667
677
* triggered. Protected by info_lck.
@@ -921,6 +931,7 @@ static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
921
931
int reqLen , XLogRecPtr targetRecPtr , char * readBuf );
922
932
static bool WaitForWALToBecomeAvailable (XLogRecPtr RecPtr , bool randAccess ,
923
933
bool fetching_ckpt , XLogRecPtr tliRecPtr );
934
+ static void XLogShutdownWalRcv (void );
924
935
static int emode_for_corrupt_record (int emode , XLogRecPtr RecPtr );
925
936
static void XLogFileClose (void );
926
937
static void PreallocXlogFiles (XLogRecPtr endptr );
@@ -3625,8 +3636,8 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
3625
3636
* is false.)
3626
3637
*
3627
3638
* 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.
3630
3641
*/
3631
3642
static bool
3632
3643
InstallXLogFileSegment (XLogSegNo * segno , char * tmppath ,
@@ -3638,6 +3649,11 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
3638
3649
XLogFilePath (path , ThisTimeLineID , * segno , wal_segment_size );
3639
3650
3640
3651
LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
3652
+ if (!XLogCtl -> InstallXLogFileSegmentActive )
3653
+ {
3654
+ LWLockRelease (ControlFileLock );
3655
+ return false;
3656
+ }
3641
3657
3642
3658
if (!find_free )
3643
3659
{
@@ -3745,6 +3761,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
3745
3761
*/
3746
3762
if (source == XLOG_FROM_ARCHIVE )
3747
3763
{
3764
+ Assert (!XLogCtl -> InstallXLogFileSegmentActive );
3748
3765
KeepFileRestoredFromArchive (path , xlogfname );
3749
3766
3750
3767
/*
@@ -3946,6 +3963,9 @@ PreallocXlogFiles(XLogRecPtr endptr)
3946
3963
char path [MAXPGPATH ];
3947
3964
uint64 offset ;
3948
3965
3966
+ if (!XLogCtl -> InstallXLogFileSegmentActive )
3967
+ return ; /* unlocked check says no */
3968
+
3949
3969
XLByteToPrevSeg (endptr , _logSegNo , wal_segment_size );
3950
3970
offset = XLogSegmentOffset (endptr - 1 , wal_segment_size );
3951
3971
if (offset >= (uint32 ) (0.75 * wal_segment_size ))
@@ -4227,6 +4247,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
4227
4247
*/
4228
4248
if (wal_recycle &&
4229
4249
* endlogSegNo <= recycleSegNo &&
4250
+ XLogCtl -> InstallXLogFileSegmentActive && /* callee rechecks this */
4230
4251
lstat (path , & statbuf ) == 0 && S_ISREG (statbuf .st_mode ) &&
4231
4252
InstallXLogFileSegment (endlogSegNo , path ,
4232
4253
true, recycleSegNo ))
@@ -4240,7 +4261,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
4240
4261
}
4241
4262
else
4242
4263
{
4243
- /* No need for any more future segments... */
4264
+ /* No need for any more future segments, or recycling failed ... */
4244
4265
int rc ;
4245
4266
4246
4267
ereport (DEBUG2 ,
@@ -5226,6 +5247,7 @@ XLOGShmemInit(void)
5226
5247
XLogCtl -> XLogCacheBlck = XLOGbuffers - 1 ;
5227
5248
XLogCtl -> SharedRecoveryState = RECOVERY_STATE_CRASH ;
5228
5249
XLogCtl -> SharedHotStandbyActive = false;
5250
+ XLogCtl -> InstallXLogFileSegmentActive = false;
5229
5251
XLogCtl -> SharedPromoteIsTriggered = false;
5230
5252
XLogCtl -> WalWriterSleeping = false;
5231
5253
@@ -5253,6 +5275,11 @@ BootStrapXLOG(void)
5253
5275
struct timeval tv ;
5254
5276
pg_crc32c crc ;
5255
5277
5278
+ /* allow ordinary WAL segment creation, like StartupXLOG() would */
5279
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
5280
+ XLogCtl -> InstallXLogFileSegmentActive = true;
5281
+ LWLockRelease (ControlFileLock );
5282
+
5256
5283
/*
5257
5284
* Select a hopefully-unique system identifier code for this installation.
5258
5285
* We use the result of gettimeofday(), including the fractional seconds
@@ -7619,7 +7646,7 @@ StartupXLOG(void)
7619
7646
* the startup checkpoint record. It will trump over the checkpoint and
7620
7647
* subsequent records if it's still alive when we start writing WAL.
7621
7648
*/
7622
- ShutdownWalRcv ();
7649
+ XLogShutdownWalRcv ();
7623
7650
7624
7651
/*
7625
7652
* Reset unlogged relations to the contents of their INIT fork. This is
@@ -7644,7 +7671,7 @@ StartupXLOG(void)
7644
7671
* recovery, e.g., timeline history file) from archive or pg_wal.
7645
7672
*
7646
7673
* Note that standby mode must be turned off after killing WAL receiver,
7647
- * i.e., calling ShutdownWalRcv ().
7674
+ * i.e., calling XLogShutdownWalRcv ().
7648
7675
*/
7649
7676
Assert (!WalRcvStreaming ());
7650
7677
StandbyMode = false;
@@ -7709,6 +7736,14 @@ StartupXLOG(void)
7709
7736
*/
7710
7737
oldestActiveXID = PrescanPreparedTransactions (NULL , NULL );
7711
7738
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
+
7712
7747
/*
7713
7748
* Consider whether we need to assign a new timeline ID.
7714
7749
*
@@ -12378,7 +12413,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12378
12413
*/
12379
12414
if (StandbyMode && CheckForStandbyTrigger ())
12380
12415
{
12381
- ShutdownWalRcv ();
12416
+ XLogShutdownWalRcv ();
12382
12417
return false;
12383
12418
}
12384
12419
@@ -12426,7 +12461,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12426
12461
* WAL that we restore from archive.
12427
12462
*/
12428
12463
if (WalRcvStreaming ())
12429
- ShutdownWalRcv ();
12464
+ XLogShutdownWalRcv ();
12430
12465
12431
12466
/*
12432
12467
* Before we sleep, re-scan for possible new timelines if
@@ -12553,7 +12588,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12553
12588
*/
12554
12589
if (pendingWalRcvRestart && !startWalReceiver )
12555
12590
{
12556
- ShutdownWalRcv ();
12591
+ XLogShutdownWalRcv ();
12557
12592
12558
12593
/*
12559
12594
* Re-scan for possible new timelines if we were
@@ -12603,6 +12638,9 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12603
12638
tli , curFileTLI );
12604
12639
}
12605
12640
curFileTLI = tli ;
12641
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
12642
+ XLogCtl -> InstallXLogFileSegmentActive = true;
12643
+ LWLockRelease (ControlFileLock );
12606
12644
RequestXLogStreaming (tli , ptr , PrimaryConnInfo ,
12607
12645
PrimarySlotName ,
12608
12646
wal_receiver_create_temp_slot );
@@ -12770,6 +12808,17 @@ StartupRequestWalReceiverRestart(void)
12770
12808
}
12771
12809
}
12772
12810
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
+
12773
12822
/*
12774
12823
* Determine what log level should be used to report a corrupt WAL record
12775
12824
* in the current WAL page, previously read by XLogPageRead().
0 commit comments