@@ -675,6 +675,16 @@ typedef struct XLogCtlData
675
675
*/
676
676
bool SharedHotStandbyActive ;
677
677
678
+ /*
679
+ * InstallXLogFileSegmentActive indicates whether the checkpointer should
680
+ * arrange for future segments by recycling and/or PreallocXlogFiles().
681
+ * Protected by ControlFileLock. Only the startup process changes it. If
682
+ * true, anyone can use InstallXLogFileSegment(). If false, the startup
683
+ * process owns the exclusive right to install segments, by reading from
684
+ * the archive and possibly replacing existing files.
685
+ */
686
+ bool InstallXLogFileSegmentActive ;
687
+
678
688
/*
679
689
* SharedPromoteIsTriggered indicates if a standby promotion has been
680
690
* triggered. Protected by info_lck.
@@ -925,6 +935,7 @@ static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
925
935
int reqLen , XLogRecPtr targetRecPtr , char * readBuf );
926
936
static bool WaitForWALToBecomeAvailable (XLogRecPtr RecPtr , bool randAccess ,
927
937
bool fetching_ckpt , XLogRecPtr tliRecPtr );
938
+ static void XLogShutdownWalRcv (void );
928
939
static int emode_for_corrupt_record (int emode , XLogRecPtr RecPtr );
929
940
static void XLogFileClose (void );
930
941
static void PreallocXlogFiles (XLogRecPtr endptr );
@@ -3608,8 +3619,8 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
3608
3619
* is false.)
3609
3620
*
3610
3621
* Returns true if the file was installed successfully. false indicates that
3611
- * max_segno limit was exceeded, or an error occurred while renaming the
3612
- * file into place.
3622
+ * max_segno limit was exceeded, the startup process has disabled this
3623
+ * function for now, or an error occurred while renaming the file into place.
3613
3624
*/
3614
3625
static bool
3615
3626
InstallXLogFileSegment (XLogSegNo * segno , char * tmppath ,
@@ -3621,6 +3632,11 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
3621
3632
XLogFilePath (path , ThisTimeLineID , * segno , wal_segment_size );
3622
3633
3623
3634
LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
3635
+ if (!XLogCtl -> InstallXLogFileSegmentActive )
3636
+ {
3637
+ LWLockRelease (ControlFileLock );
3638
+ return false;
3639
+ }
3624
3640
3625
3641
if (!find_free )
3626
3642
{
@@ -3725,6 +3741,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
3725
3741
*/
3726
3742
if (source == XLOG_FROM_ARCHIVE )
3727
3743
{
3744
+ Assert (!XLogCtl -> InstallXLogFileSegmentActive );
3728
3745
KeepFileRestoredFromArchive (path , xlogfname );
3729
3746
3730
3747
/*
@@ -3926,6 +3943,9 @@ PreallocXlogFiles(XLogRecPtr endptr)
3926
3943
char path [MAXPGPATH ];
3927
3944
uint64 offset ;
3928
3945
3946
+ if (!XLogCtl -> InstallXLogFileSegmentActive )
3947
+ return ; /* unlocked check says no */
3948
+
3929
3949
XLByteToPrevSeg (endptr , _logSegNo , wal_segment_size );
3930
3950
offset = XLogSegmentOffset (endptr - 1 , wal_segment_size );
3931
3951
if (offset >= (uint32 ) (0.75 * wal_segment_size ))
@@ -4207,6 +4227,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr lastredoptr, XLogRecPtr endptr)
4207
4227
*/
4208
4228
if (wal_recycle &&
4209
4229
endlogSegNo <= recycleSegNo &&
4230
+ XLogCtl -> InstallXLogFileSegmentActive && /* callee rechecks this */
4210
4231
lstat (path , & statbuf ) == 0 && S_ISREG (statbuf .st_mode ) &&
4211
4232
InstallXLogFileSegment (& endlogSegNo , path ,
4212
4233
true, recycleSegNo ))
@@ -4220,7 +4241,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr lastredoptr, XLogRecPtr endptr)
4220
4241
}
4221
4242
else
4222
4243
{
4223
- /* No need for any more future segments... */
4244
+ /* No need for any more future segments, or recycling failed ... */
4224
4245
int rc ;
4225
4246
4226
4247
ereport (DEBUG2 ,
@@ -5225,6 +5246,7 @@ XLOGShmemInit(void)
5225
5246
XLogCtl -> XLogCacheBlck = XLOGbuffers - 1 ;
5226
5247
XLogCtl -> SharedRecoveryState = RECOVERY_STATE_CRASH ;
5227
5248
XLogCtl -> SharedHotStandbyActive = false;
5249
+ XLogCtl -> InstallXLogFileSegmentActive = false;
5228
5250
XLogCtl -> SharedPromoteIsTriggered = false;
5229
5251
XLogCtl -> WalWriterSleeping = false;
5230
5252
@@ -5251,6 +5273,11 @@ BootStrapXLOG(void)
5251
5273
struct timeval tv ;
5252
5274
pg_crc32c crc ;
5253
5275
5276
+ /* allow ordinary WAL segment creation, like StartupXLOG() would */
5277
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
5278
+ XLogCtl -> InstallXLogFileSegmentActive = true;
5279
+ LWLockRelease (ControlFileLock );
5280
+
5254
5281
/*
5255
5282
* Select a hopefully-unique system identifier code for this installation.
5256
5283
* We use the result of gettimeofday(), including the fractional seconds
@@ -7531,7 +7558,7 @@ StartupXLOG(void)
7531
7558
* over these records and subsequent ones if it's still alive when we
7532
7559
* start writing WAL.
7533
7560
*/
7534
- ShutdownWalRcv ();
7561
+ XLogShutdownWalRcv ();
7535
7562
7536
7563
/*
7537
7564
* Reset unlogged relations to the contents of their INIT fork. This is
@@ -7556,7 +7583,7 @@ StartupXLOG(void)
7556
7583
* recovery, e.g., timeline history file) from archive or pg_wal.
7557
7584
*
7558
7585
* Note that standby mode must be turned off after killing WAL receiver,
7559
- * i.e., calling ShutdownWalRcv ().
7586
+ * i.e., calling XLogShutdownWalRcv ().
7560
7587
*/
7561
7588
Assert (!WalRcvStreaming ());
7562
7589
StandbyMode = false;
@@ -7625,6 +7652,14 @@ StartupXLOG(void)
7625
7652
*/
7626
7653
oldestActiveXID = PrescanPreparedTransactions (NULL , NULL );
7627
7654
7655
+ /*
7656
+ * Allow ordinary WAL segment creation before any exitArchiveRecovery(),
7657
+ * which sometimes creates a segment, and after the last ReadRecord().
7658
+ */
7659
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
7660
+ XLogCtl -> InstallXLogFileSegmentActive = true;
7661
+ LWLockRelease (ControlFileLock );
7662
+
7628
7663
/*
7629
7664
* Consider whether we need to assign a new timeline ID.
7630
7665
*
@@ -12491,7 +12526,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12491
12526
*/
12492
12527
if (StandbyMode && CheckForStandbyTrigger ())
12493
12528
{
12494
- ShutdownWalRcv ();
12529
+ XLogShutdownWalRcv ();
12495
12530
return false;
12496
12531
}
12497
12532
@@ -12539,7 +12574,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12539
12574
* WAL that we restore from archive.
12540
12575
*/
12541
12576
if (WalRcvStreaming ())
12542
- ShutdownWalRcv ();
12577
+ XLogShutdownWalRcv ();
12543
12578
12544
12579
/*
12545
12580
* Before we sleep, re-scan for possible new timelines if
@@ -12669,7 +12704,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12669
12704
*/
12670
12705
if (pendingWalRcvRestart && !startWalReceiver )
12671
12706
{
12672
- ShutdownWalRcv ();
12707
+ XLogShutdownWalRcv ();
12673
12708
12674
12709
/*
12675
12710
* Re-scan for possible new timelines if we were
@@ -12720,6 +12755,9 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12720
12755
tli , curFileTLI );
12721
12756
}
12722
12757
curFileTLI = tli ;
12758
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
12759
+ XLogCtl -> InstallXLogFileSegmentActive = true;
12760
+ LWLockRelease (ControlFileLock );
12723
12761
RequestXLogStreaming (tli , ptr , PrimaryConnInfo ,
12724
12762
PrimarySlotName ,
12725
12763
wal_receiver_create_temp_slot );
@@ -12882,6 +12920,17 @@ StartupRequestWalReceiverRestart(void)
12882
12920
}
12883
12921
}
12884
12922
12923
+ /* Thin wrapper around ShutdownWalRcv(). */
12924
+ static void
12925
+ XLogShutdownWalRcv (void )
12926
+ {
12927
+ ShutdownWalRcv ();
12928
+
12929
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
12930
+ XLogCtl -> InstallXLogFileSegmentActive = false;
12931
+ LWLockRelease (ControlFileLock );
12932
+ }
12933
+
12885
12934
/*
12886
12935
* Determine what log level should be used to report a corrupt WAL record
12887
12936
* in the current WAL page, previously read by XLogPageRead().
0 commit comments