@@ -673,6 +673,16 @@ typedef struct XLogCtlData
673
673
*/
674
674
bool SharedHotStandbyActive ;
675
675
676
+ /*
677
+ * InstallXLogFileSegmentActive indicates whether the checkpointer should
678
+ * arrange for future segments by recycling and/or PreallocXlogFiles().
679
+ * Protected by ControlFileLock. Only the startup process changes it. If
680
+ * true, anyone can use InstallXLogFileSegment(). If false, the startup
681
+ * process owns the exclusive right to install segments, by reading from
682
+ * the archive and possibly replacing existing files.
683
+ */
684
+ bool InstallXLogFileSegmentActive ;
685
+
676
686
/*
677
687
* SharedPromoteIsTriggered indicates if a standby promotion has been
678
688
* triggered. Protected by info_lck.
@@ -935,6 +945,7 @@ static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
935
945
int reqLen , XLogRecPtr targetRecPtr , char * readBuf );
936
946
static bool WaitForWALToBecomeAvailable (XLogRecPtr RecPtr , bool randAccess ,
937
947
bool fetching_ckpt , XLogRecPtr tliRecPtr );
948
+ static void XLogShutdownWalRcv (void );
938
949
static int emode_for_corrupt_record (int emode , XLogRecPtr RecPtr );
939
950
static void XLogFileClose (void );
940
951
static void PreallocXlogFiles (XLogRecPtr endptr );
@@ -3653,8 +3664,8 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
3653
3664
* is false.)
3654
3665
*
3655
3666
* Returns true if the file was installed successfully. false indicates that
3656
- * max_segno limit was exceeded, or an error occurred while renaming the
3657
- * file into place.
3667
+ * max_segno limit was exceeded, the startup process has disabled this
3668
+ * function for now, or an error occurred while renaming the file into place.
3658
3669
*/
3659
3670
static bool
3660
3671
InstallXLogFileSegment (XLogSegNo * segno , char * tmppath ,
@@ -3666,6 +3677,11 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
3666
3677
XLogFilePath (path , ThisTimeLineID , * segno , wal_segment_size );
3667
3678
3668
3679
LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
3680
+ if (!XLogCtl -> InstallXLogFileSegmentActive )
3681
+ {
3682
+ LWLockRelease (ControlFileLock );
3683
+ return false;
3684
+ }
3669
3685
3670
3686
if (!find_free )
3671
3687
{
@@ -3770,6 +3786,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
3770
3786
*/
3771
3787
if (source == XLOG_FROM_ARCHIVE )
3772
3788
{
3789
+ Assert (!XLogCtl -> InstallXLogFileSegmentActive );
3773
3790
KeepFileRestoredFromArchive (path , xlogfname );
3774
3791
3775
3792
/*
@@ -3971,6 +3988,9 @@ PreallocXlogFiles(XLogRecPtr endptr)
3971
3988
char path [MAXPGPATH ];
3972
3989
uint64 offset ;
3973
3990
3991
+ if (!XLogCtl -> InstallXLogFileSegmentActive )
3992
+ return ; /* unlocked check says no */
3993
+
3974
3994
XLByteToPrevSeg (endptr , _logSegNo , wal_segment_size );
3975
3995
offset = XLogSegmentOffset (endptr - 1 , wal_segment_size );
3976
3996
if (offset >= (uint32 ) (0.75 * wal_segment_size ))
@@ -4252,6 +4272,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
4252
4272
*/
4253
4273
if (wal_recycle &&
4254
4274
* endlogSegNo <= recycleSegNo &&
4275
+ XLogCtl -> InstallXLogFileSegmentActive && /* callee rechecks this */
4255
4276
lstat (path , & statbuf ) == 0 && S_ISREG (statbuf .st_mode ) &&
4256
4277
InstallXLogFileSegment (endlogSegNo , path ,
4257
4278
true, recycleSegNo ))
@@ -4265,7 +4286,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
4265
4286
}
4266
4287
else
4267
4288
{
4268
- /* No need for any more future segments... */
4289
+ /* No need for any more future segments, or recycling failed ... */
4269
4290
int rc ;
4270
4291
4271
4292
ereport (DEBUG2 ,
@@ -5270,6 +5291,7 @@ XLOGShmemInit(void)
5270
5291
XLogCtl -> XLogCacheBlck = XLOGbuffers - 1 ;
5271
5292
XLogCtl -> SharedRecoveryState = RECOVERY_STATE_CRASH ;
5272
5293
XLogCtl -> SharedHotStandbyActive = false;
5294
+ XLogCtl -> InstallXLogFileSegmentActive = false;
5273
5295
XLogCtl -> SharedPromoteIsTriggered = false;
5274
5296
XLogCtl -> WalWriterSleeping = false;
5275
5297
@@ -5297,6 +5319,11 @@ BootStrapXLOG(void)
5297
5319
struct timeval tv ;
5298
5320
pg_crc32c crc ;
5299
5321
5322
+ /* allow ordinary WAL segment creation, like StartupXLOG() would */
5323
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
5324
+ XLogCtl -> InstallXLogFileSegmentActive = true;
5325
+ LWLockRelease (ControlFileLock );
5326
+
5300
5327
/*
5301
5328
* Select a hopefully-unique system identifier code for this installation.
5302
5329
* We use the result of gettimeofday(), including the fractional seconds
@@ -7685,7 +7712,7 @@ StartupXLOG(void)
7685
7712
* over these records and subsequent ones if it's still alive when we
7686
7713
* start writing WAL.
7687
7714
*/
7688
- ShutdownWalRcv ();
7715
+ XLogShutdownWalRcv ();
7689
7716
7690
7717
/*
7691
7718
* Reset unlogged relations to the contents of their INIT fork. This is
@@ -7710,7 +7737,7 @@ StartupXLOG(void)
7710
7737
* recovery, e.g., timeline history file) from archive or pg_wal.
7711
7738
*
7712
7739
* Note that standby mode must be turned off after killing WAL receiver,
7713
- * i.e., calling ShutdownWalRcv ().
7740
+ * i.e., calling XLogShutdownWalRcv ().
7714
7741
*/
7715
7742
Assert (!WalRcvStreaming ());
7716
7743
StandbyMode = false;
@@ -7779,6 +7806,14 @@ StartupXLOG(void)
7779
7806
*/
7780
7807
oldestActiveXID = PrescanPreparedTransactions (NULL , NULL );
7781
7808
7809
+ /*
7810
+ * Allow ordinary WAL segment creation before any exitArchiveRecovery(),
7811
+ * which sometimes creates a segment, and after the last ReadRecord().
7812
+ */
7813
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
7814
+ XLogCtl -> InstallXLogFileSegmentActive = true;
7815
+ LWLockRelease (ControlFileLock );
7816
+
7782
7817
/*
7783
7818
* Consider whether we need to assign a new timeline ID.
7784
7819
*
@@ -12717,7 +12752,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12717
12752
*/
12718
12753
if (StandbyMode && CheckForStandbyTrigger ())
12719
12754
{
12720
- ShutdownWalRcv ();
12755
+ XLogShutdownWalRcv ();
12721
12756
return false;
12722
12757
}
12723
12758
@@ -12765,7 +12800,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12765
12800
* WAL that we restore from archive.
12766
12801
*/
12767
12802
if (WalRcvStreaming ())
12768
- ShutdownWalRcv ();
12803
+ XLogShutdownWalRcv ();
12769
12804
12770
12805
/*
12771
12806
* Before we sleep, re-scan for possible new timelines if
@@ -12895,7 +12930,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12895
12930
*/
12896
12931
if (pendingWalRcvRestart && !startWalReceiver )
12897
12932
{
12898
- ShutdownWalRcv ();
12933
+ XLogShutdownWalRcv ();
12899
12934
12900
12935
/*
12901
12936
* Re-scan for possible new timelines if we were
@@ -12945,6 +12980,9 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
12945
12980
tli , curFileTLI );
12946
12981
}
12947
12982
curFileTLI = tli ;
12983
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
12984
+ XLogCtl -> InstallXLogFileSegmentActive = true;
12985
+ LWLockRelease (ControlFileLock );
12948
12986
RequestXLogStreaming (tli , ptr , PrimaryConnInfo ,
12949
12987
PrimarySlotName ,
12950
12988
wal_receiver_create_temp_slot );
@@ -13115,6 +13153,17 @@ StartupRequestWalReceiverRestart(void)
13115
13153
}
13116
13154
}
13117
13155
13156
+ /* Thin wrapper around ShutdownWalRcv(). */
13157
+ static void
13158
+ XLogShutdownWalRcv (void )
13159
+ {
13160
+ ShutdownWalRcv ();
13161
+
13162
+ LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
13163
+ XLogCtl -> InstallXLogFileSegmentActive = false;
13164
+ LWLockRelease (ControlFileLock );
13165
+ }
13166
+
13118
13167
/*
13119
13168
* Determine what log level should be used to report a corrupt WAL record
13120
13169
* in the current WAL page, previously read by XLogPageRead().
0 commit comments