[PATCH v5 1/3] Move code around in StartupXLOG().
Heikki Linnakangas <heikki.linnakangas@iki.fi>
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
To:
Date: 2021-07-31T12:06:32Z
Lists: pgsql-hackers
This is the order that things will happen with the next commit, this
makes it more explicit. To aid review, I added "BEGIN/END function"
comments to mark which blocks of code are moved to separate functions in
in the next commit.
---
src/backend/access/transam/xlog.c | 469 ++++++++++++++++--------------
1 file changed, 254 insertions(+), 215 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index efb3ca273ed..7d30ef4de77 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -882,7 +882,6 @@ static MemoryContext walDebugCxt = NULL;
static void readRecoverySignalFile(void);
static void validateRecoveryParameters(void);
-static void exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog);
static bool recoveryStopsBefore(XLogReaderState *record);
static bool recoveryStopsAfter(XLogReaderState *record);
static char *getRecoveryStopReason(void);
@@ -5593,10 +5592,10 @@ validateRecoveryParameters(void)
}
/*
- * Exit archive-recovery state
+ * Initialize the first WAL segment on new timeline.
*/
static void
-exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
+XLogInitNewTimeline(TimeLineID endTLI, XLogRecPtr endOfLog)
{
char xlogfname[MAXFNAMELEN];
XLogSegNo endLogSegNo;
@@ -5605,26 +5604,11 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
/* we always switch to a new timeline after archive recovery */
Assert(endTLI != ThisTimeLineID);
- /*
- * We are no longer in archive recovery state.
- */
- InArchiveRecovery = false;
-
/*
* Update min recovery point one last time.
*/
UpdateMinRecoveryPoint(InvalidXLogRecPtr, true);
- /*
- * If the ending log segment is still open, close it (to avoid problems on
- * Windows with trying to rename or delete an open file).
- */
- if (readFile >= 0)
- {
- close(readFile);
- readFile = -1;
- }
-
/*
* Calculate the last segment on the old timeline, and the first segment
* on the new timeline. If the switch happens in the middle of a segment,
@@ -5682,19 +5666,6 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
*/
XLogFileName(xlogfname, ThisTimeLineID, startLogSegNo, wal_segment_size);
XLogArchiveCleanup(xlogfname);
-
- /*
- * Remove the signal files out of the way, so that we don't accidentally
- * re-enter archive recovery mode in a subsequent crash.
- */
- if (standby_signal_file_found)
- durable_unlink(STANDBY_SIGNAL_FILE, FATAL);
-
- if (recovery_signal_file_found)
- durable_unlink(RECOVERY_SIGNAL_FILE, FATAL);
-
- ereport(LOG,
- (errmsg("archive recovery complete")));
}
/*
@@ -6498,12 +6469,12 @@ StartupXLOG(void)
checkPointLoc,
EndOfLog;
TimeLineID EndOfLogTLI;
+ char *recoveryStopReason;
TimeLineID PrevTimeLineID;
XLogRecord *record;
TransactionId oldestActiveXID;
bool backupEndRequired = false;
bool backupFromStandby = false;
- DBState dbstate_at_startup;
XLogReaderState *xlogreader;
XLogPageReadPrivate private;
bool promoted = false;
@@ -6611,6 +6582,8 @@ StartupXLOG(void)
SyncDataDirectory();
}
+ /*---- BEGIN InitWalRecovery ----*/
+
/*
* Initialize on the assumption we want to recover to the latest timeline
* that's active according to pg_control.
@@ -6863,20 +6836,6 @@ StartupXLOG(void)
wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
}
- /*
- * Clear out any old relcache cache files. This is *necessary* if we do
- * any WAL replay, since that would probably result in the cache files
- * being out of sync with database reality. In theory we could leave them
- * in place if the database had been cleanly shut down, but it seems
- * safest to just remove them always and let them be rebuilt during the
- * first backend startup. These files needs to be removed from all
- * directories including pg_tblspc, however the symlinks are created only
- * after reading tablespace_map file in case of archive recovery from
- * backup, so needs to clear old relcache files here after creating
- * symlinks.
- */
- RelationCacheInitFileRemove();
-
/*
* If the location of the checkpoint record is not on the expected
* timeline in the history of the requested timeline, we cannot proceed:
@@ -6939,9 +6898,113 @@ StartupXLOG(void)
(errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
checkPoint.oldestCommitTsXid,
checkPoint.newestCommitTsXid)));
+
+ /* sanity checks on the checkpoint record */
if (!TransactionIdIsNormal(XidFromFullTransactionId(checkPoint.nextXid)))
ereport(PANIC,
(errmsg("invalid next transaction ID")));
+ if (checkPoint.redo > checkPointLoc)
+ ereport(PANIC,
+ (errmsg("invalid redo in checkpoint record")));
+
+ /*
+ * Check whether we need to force recovery from WAL. If it appears to
+ * have been a clean shutdown and we did not have a recovery signal file,
+ * then assume no recovery needed.
+ */
+ if (checkPoint.redo < checkPointLoc)
+ {
+ if (wasShutdown)
+ ereport(PANIC,
+ (errmsg("invalid redo record in shutdown checkpoint")));
+ InRecovery = true;
+ }
+ else if (ControlFile->state != DB_SHUTDOWNED)
+ InRecovery = true;
+ else if (ArchiveRecoveryRequested)
+ {
+ /* force recovery due to presence of recovery signal file */
+ InRecovery = true;
+ }
+
+ /*
+ * If recovery is needed, update our in-memory copy of pg_control to show
+ * that we are recovering and to show the selected checkpoint as the place
+ * we are starting from. We also mark pg_control with any minimum recovery
+ * stop point obtained from a backup history file.
+ *
+ * We don't write the changes to disk yet, though. Only do that after
+ * initializing various subsystems.
+ */
+ if (InRecovery)
+ {
+ DBState dbstate_at_startup;
+
+ dbstate_at_startup = ControlFile->state;
+ if (InArchiveRecovery)
+ {
+ ControlFile->state = DB_IN_ARCHIVE_RECOVERY;
+ }
+ else
+ {
+ ereport(LOG,
+ (errmsg("database system was not properly shut down; "
+ "automatic recovery in progress")));
+ if (recoveryTargetTLI > ControlFile->checkPointCopy.ThisTimeLineID)
+ ereport(LOG,
+ (errmsg("crash recovery starts in timeline %u "
+ "and has target timeline %u",
+ ControlFile->checkPointCopy.ThisTimeLineID,
+ recoveryTargetTLI)));
+ ControlFile->state = DB_IN_CRASH_RECOVERY;
+ }
+ ControlFile->checkPoint = checkPointLoc;
+ ControlFile->checkPointCopy = checkPoint;
+ if (InArchiveRecovery)
+ {
+ /* initialize minRecoveryPoint if not set yet */
+ if (ControlFile->minRecoveryPoint < checkPoint.redo)
+ {
+ ControlFile->minRecoveryPoint = checkPoint.redo;
+ ControlFile->minRecoveryPointTLI = checkPoint.ThisTimeLineID;
+ }
+ }
+
+ /*
+ * Set backupStartPoint if we're starting recovery from a base backup.
+ *
+ * Also set backupEndPoint and use minRecoveryPoint as the backup end
+ * location if we're starting recovery from a base backup which was
+ * taken from a standby. In this case, the database system status in
+ * pg_control must indicate that the database was already in recovery.
+ * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
+ * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
+ * before reaching this point; e.g. because restore_command or
+ * primary_conninfo were faulty.
+ *
+ * Any other state indicates that the backup somehow became corrupted
+ * and we can't sensibly continue with recovery.
+ */
+ if (haveBackupLabel)
+ {
+ ControlFile->backupStartPoint = checkPoint.redo;
+ ControlFile->backupEndRequired = backupEndRequired;
+
+ if (backupFromStandby)
+ {
+ if (dbstate_at_startup != DB_IN_ARCHIVE_RECOVERY &&
+ dbstate_at_startup != DB_SHUTDOWNED_IN_RECOVERY)
+ ereport(FATAL,
+ (errmsg("backup_label contains data inconsistent with control file"),
+ errhint("This means that the backup is corrupted and you will "
+ "have to use another backup for recovery.")));
+ ControlFile->backupEndPoint = ControlFile->minRecoveryPoint;
+ }
+ }
+ ControlFile->time = (pg_time_t) time(NULL);
+ }
+
+ /*---- END InitWalRecovery ----*/
/* initialize shared memory variables from the checkpoint record */
ShmemVariableCache->nextXid = checkPoint.nextXid;
@@ -6955,6 +7018,20 @@ StartupXLOG(void)
checkPoint.newestCommitTsXid);
XLogCtl->ckptFullXid = checkPoint.nextXid;
+ /*
+ * Clear out any old relcache cache files. This is *necessary* if we do
+ * any WAL replay, since that would probably result in the cache files
+ * being out of sync with database reality. In theory we could leave them
+ * in place if the database had been cleanly shut down, but it seems
+ * safest to just remove them always and let them be rebuilt during the
+ * first backend startup. These files needs to be removed from all
+ * directories including pg_tblspc, however the symlinks are created only
+ * after reading tablespace_map file in case of archive recovery from
+ * backup, so needs to clear old relcache files here after creating
+ * symlinks.
+ */
+ RelationCacheInitFileRemove();
+
/*
* Initialize replication slots, before there's a chance to remove
* required resources.
@@ -7039,140 +7116,29 @@ StartupXLOG(void)
RedoRecPtr = XLogCtl->RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
doPageWrites = lastFullPageWrites;
- if (RecPtr < checkPoint.redo)
- ereport(PANIC,
- (errmsg("invalid redo in checkpoint record")));
-
- /*
- * Check whether we need to force recovery from WAL. If it appears to
- * have been a clean shutdown and we did not have a recovery signal file,
- * then assume no recovery needed.
- */
- if (checkPoint.redo < RecPtr)
- {
- if (wasShutdown)
- ereport(PANIC,
- (errmsg("invalid redo record in shutdown checkpoint")));
- InRecovery = true;
- }
- else if (ControlFile->state != DB_SHUTDOWNED)
- InRecovery = true;
- else if (ArchiveRecoveryRequested)
- {
- /* force recovery due to presence of recovery signal file */
- InRecovery = true;
- }
-
/* REDO */
if (InRecovery)
{
int rmid;
+ /* Initialize state for RecoveryInProgress() */
+ SpinLockAcquire(&XLogCtl->info_lck);
+ if (InArchiveRecovery)
+ XLogCtl->SharedRecoveryState = RECOVERY_STATE_ARCHIVE;
+ else
+ XLogCtl->SharedRecoveryState = RECOVERY_STATE_CRASH;
+ SpinLockRelease(&XLogCtl->info_lck);
+
/*
* Update pg_control to show that we are recovering and to show the
* selected checkpoint as the place we are starting from. We also mark
* pg_control with any minimum recovery stop point obtained from a
* backup history file.
- */
- dbstate_at_startup = ControlFile->state;
- if (InArchiveRecovery)
- {
- ControlFile->state = DB_IN_ARCHIVE_RECOVERY;
-
- SpinLockAcquire(&XLogCtl->info_lck);
- XLogCtl->SharedRecoveryState = RECOVERY_STATE_ARCHIVE;
- SpinLockRelease(&XLogCtl->info_lck);
- }
- else
- {
- ereport(LOG,
- (errmsg("database system was not properly shut down; "
- "automatic recovery in progress")));
- if (recoveryTargetTLI > ControlFile->checkPointCopy.ThisTimeLineID)
- ereport(LOG,
- (errmsg("crash recovery starts in timeline %u "
- "and has target timeline %u",
- ControlFile->checkPointCopy.ThisTimeLineID,
- recoveryTargetTLI)));
- ControlFile->state = DB_IN_CRASH_RECOVERY;
-
- SpinLockAcquire(&XLogCtl->info_lck);
- XLogCtl->SharedRecoveryState = RECOVERY_STATE_CRASH;
- SpinLockRelease(&XLogCtl->info_lck);
- }
- ControlFile->checkPoint = checkPointLoc;
- ControlFile->checkPointCopy = checkPoint;
- if (InArchiveRecovery)
- {
- /* initialize minRecoveryPoint if not set yet */
- if (ControlFile->minRecoveryPoint < checkPoint.redo)
- {
- ControlFile->minRecoveryPoint = checkPoint.redo;
- ControlFile->minRecoveryPointTLI = checkPoint.ThisTimeLineID;
- }
- }
-
- /*
- * Set backupStartPoint if we're starting recovery from a base backup.
- *
- * Also set backupEndPoint and use minRecoveryPoint as the backup end
- * location if we're starting recovery from a base backup which was
- * taken from a standby. In this case, the database system status in
- * pg_control must indicate that the database was already in recovery.
- * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
- * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
- * before reaching this point; e.g. because restore_command or
- * primary_conninfo were faulty.
*
- * Any other state indicates that the backup somehow became corrupted
- * and we can't sensibly continue with recovery.
+ * No need to hold ControlFileLock yet, we aren't up far enough
*/
- if (haveBackupLabel)
- {
- ControlFile->backupStartPoint = checkPoint.redo;
- ControlFile->backupEndRequired = backupEndRequired;
-
- if (backupFromStandby)
- {
- if (dbstate_at_startup != DB_IN_ARCHIVE_RECOVERY &&
- dbstate_at_startup != DB_SHUTDOWNED_IN_RECOVERY)
- ereport(FATAL,
- (errmsg("backup_label contains data inconsistent with control file"),
- errhint("This means that the backup is corrupted and you will "
- "have to use another backup for recovery.")));
- ControlFile->backupEndPoint = ControlFile->minRecoveryPoint;
- }
- }
- ControlFile->time = (pg_time_t) time(NULL);
- /* No need to hold ControlFileLock yet, we aren't up far enough */
UpdateControlFile();
- /*
- * Initialize our local copy of minRecoveryPoint. When doing crash
- * recovery we want to replay up to the end of WAL. Particularly, in
- * the case of a promoted standby minRecoveryPoint value in the
- * control file is only updated after the first checkpoint. However,
- * if the instance crashes before the first post-recovery checkpoint
- * is completed then recovery will use a stale location causing the
- * startup process to think that there are still invalid page
- * references when checking for data consistency.
- */
- if (InArchiveRecovery)
- {
- minRecoveryPoint = ControlFile->minRecoveryPoint;
- minRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
- }
- else
- {
- minRecoveryPoint = InvalidXLogRecPtr;
- minRecoveryPointTLI = 0;
- }
-
- /*
- * Reset pgstat data, because it may be invalid after recovery.
- */
- pgstat_reset_all();
-
/*
* If there was a backup label file, it's done its job and the info
* has now been propagated into pg_control. We must get rid of the
@@ -7200,6 +7166,32 @@ StartupXLOG(void)
durable_rename(TABLESPACE_MAP, TABLESPACE_MAP_OLD, FATAL);
}
+ /*
+ * Initialize our local copy of minRecoveryPoint. When doing crash
+ * recovery we want to replay up to the end of WAL. Particularly, in
+ * the case of a promoted standby minRecoveryPoint value in the
+ * control file is only updated after the first checkpoint. However,
+ * if the instance crashes before the first post-recovery checkpoint
+ * is completed then recovery will use a stale location causing the
+ * startup process to think that there are still invalid page
+ * references when checking for data consistency.
+ */
+ if (InArchiveRecovery)
+ {
+ minRecoveryPoint = ControlFile->minRecoveryPoint;
+ minRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
+ }
+ else
+ {
+ minRecoveryPoint = InvalidXLogRecPtr;
+ minRecoveryPointTLI = 0;
+ }
+
+ /*
+ * Reset pgstat data, because it may be invalid after recovery.
+ */
+ pgstat_reset_all();
+
/* Check that the GUCs used to generate the WAL allow recovery */
CheckRequiredParameterValues();
@@ -7283,12 +7275,7 @@ StartupXLOG(void)
}
}
- /* Initialize resource managers */
- for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
- {
- if (RmgrTable[rmid].rm_startup != NULL)
- RmgrTable[rmid].rm_startup();
- }
+ /*---- BEGIN PerformWalRecovery ----*/
/*
* Initialize shared variables for tracking progress of WAL replay, as
@@ -7296,7 +7283,7 @@ StartupXLOG(void)
* checkpoint record itself, if it's a shutdown checkpoint).
*/
SpinLockAcquire(&XLogCtl->info_lck);
- if (checkPoint.redo < RecPtr)
+ if (checkPoint.redo < checkPointLoc)
XLogCtl->replayEndRecPtr = checkPoint.redo;
else
XLogCtl->replayEndRecPtr = EndRecPtr;
@@ -7341,7 +7328,7 @@ StartupXLOG(void)
* Find the first record that logically follows the checkpoint --- it
* might physically precede it, though.
*/
- if (checkPoint.redo < RecPtr)
+ if (checkPoint.redo < checkPointLoc)
{
/* back up to find the record */
XLogBeginRead(xlogreader, checkPoint.redo);
@@ -7350,6 +7337,7 @@ StartupXLOG(void)
else
{
/* just have to read next record after CheckPoint */
+ Assert(RecPtr == checkPointLoc);
record = ReadRecord(xlogreader, LOG, false);
}
@@ -7363,6 +7351,13 @@ StartupXLOG(void)
InRedo = true;
+ /* Initialize resource managers */
+ for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
+ {
+ if (RmgrTable[rmid].rm_startup != NULL)
+ RmgrTable[rmid].rm_startup();
+ }
+
ereport(LOG,
(errmsg("redo starts at %X/%X",
LSN_FORMAT_ARGS(ReadRecPtr))));
@@ -7655,8 +7650,12 @@ StartupXLOG(void)
!reachedRecoveryTarget)
ereport(FATAL,
(errmsg("recovery ended before configured recovery target was reached")));
+
+ /*---- END PerformWalRecovery ----*/
}
+ /*---- BEGIN FinishWalRecovery ----*/
+
/*
* Kill WAL receiver, if it's still running, before we continue to write
* the startup checkpoint record. It will trump over the checkpoint and
@@ -7664,23 +7663,6 @@ StartupXLOG(void)
*/
XLogShutdownWalRcv();
- /*
- * Reset unlogged relations to the contents of their INIT fork. This is
- * done AFTER recovery is complete so as to include any unlogged relations
- * created during recovery, but BEFORE recovery is marked as having
- * completed successfully. Otherwise we'd not retry if any of the post
- * end-of-recovery steps fail.
- */
- if (InRecovery)
- ResetUnloggedRelations(UNLOGGED_RELATION_INIT);
-
- /*
- * We don't need the latch anymore. It's not strictly necessary to disown
- * it, but let's do it for the sake of tidiness.
- */
- if (ArchiveRecoveryRequested)
- DisownLatch(&XLogCtl->recoveryWakeupLatch);
-
/*
* We are now done reading the xlog from stream. Turn off streaming
* recovery to force fetching the files (which would be required at end of
@@ -7709,6 +7691,32 @@ StartupXLOG(void)
*/
EndOfLogTLI = xlogreader->seg.ws_tli;
+ if (ArchiveRecoveryRequested)
+ {
+ /*
+ * We are no longer in archive recovery state.
+ *
+ * We are now done reading the old WAL. Turn off archive fetching if
+ * it was active.
+ */
+ Assert(InArchiveRecovery);
+ InArchiveRecovery = false;
+
+ /*
+ * If the ending log segment is still open, close it (to avoid problems on
+ * Windows with trying to rename or delete an open file).
+ */
+ if (readFile >= 0)
+ {
+ close(readFile);
+ readFile = -1;
+ }
+ }
+
+ recoveryStopReason = getRecoveryStopReason();
+
+ /*---- END FinishWalRecovery ----*/
+
/*
* Complain if we did not roll forward far enough to render the backup
* dump consistent. Note: it is indeed okay to look at the local variable
@@ -7745,6 +7753,16 @@ StartupXLOG(void)
}
}
+ /*
+ * Reset unlogged relations to the contents of their INIT fork. This is
+ * done AFTER recovery is complete so as to include any unlogged relations
+ * created during recovery, but BEFORE recovery is marked as having
+ * completed successfully. Otherwise we'd not retry if any of the post
+ * end-of-recovery steps fail.
+ */
+ if (InRecovery)
+ ResetUnloggedRelations(UNLOGGED_RELATION_INIT);
+
/*
* Pre-scan prepared transactions to find out the range of XIDs present.
* This information is not quite needed yet, but it is positioned here so
@@ -7753,8 +7771,8 @@ StartupXLOG(void)
oldestActiveXID = PrescanPreparedTransactions(NULL, NULL);
/*
- * Allow ordinary WAL segment creation before any exitArchiveRecovery(),
- * which sometimes creates a segment, and after the last ReadRecord().
+ * Allow ordinary WAL segment creation before switching to a new timeline,
+ * which creates a new segment, and after the last ReadRecord().
*/
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
XLogCtl->InstallXLogFileSegmentActive = true;
@@ -7777,24 +7795,26 @@ StartupXLOG(void)
PrevTimeLineID = ThisTimeLineID;
if (ArchiveRecoveryRequested)
{
- char *reason;
- char recoveryPath[MAXPGPATH];
-
- Assert(InArchiveRecovery);
-
ThisTimeLineID = findNewestTimeLine(recoveryTargetTLI) + 1;
ereport(LOG,
(errmsg("selected new timeline ID: %u", ThisTimeLineID)));
- reason = getRecoveryStopReason();
+ /*
+ * Make a writable copy of the last WAL segment. (Note that we also
+ * have a copy of the last block of the old WAL in readBuf; we will
+ * use that below.)
+ */
+ XLogInitNewTimeline(EndOfLogTLI, EndOfLog);
/*
- * We are now done reading the old WAL. Turn off archive fetching if
- * it was active, and make a writable copy of the last WAL segment.
- * (Note that we also have a copy of the last block of the old WAL in
- * readBuf; we will use that below.)
+ * Remove the signal files out of the way, so that we don't accidentally
+ * re-enter archive recovery mode in a subsequent crash.
*/
- exitArchiveRecovery(EndOfLogTLI, EndOfLog);
+ if (standby_signal_file_found)
+ durable_unlink(STANDBY_SIGNAL_FILE, FATAL);
+
+ if (recovery_signal_file_found)
+ durable_unlink(RECOVERY_SIGNAL_FILE, FATAL);
/*
* Write the timeline history file, and have it archived. After this
@@ -7807,18 +7827,10 @@ StartupXLOG(void)
* between here and writing the end-of-recovery record.
*/
writeTimeLineHistory(ThisTimeLineID, recoveryTargetTLI,
- EndRecPtr, reason);
+ EndOfLog, recoveryStopReason);
- /*
- * Since there might be a partial WAL segment named RECOVERYXLOG, get
- * rid of it.
- */
- snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
- unlink(recoveryPath); /* ignore any error */
-
- /* Get rid of any remaining recovered timeline-history file, too */
- snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
- unlink(recoveryPath); /* ignore any error */
+ ereport(LOG,
+ (errmsg("archive recovery complete")));
}
/* Save the selected TimeLineID in shared memory, too */
@@ -8054,6 +8066,8 @@ StartupXLOG(void)
if (standbyState != STANDBY_DISABLED)
ShutdownRecoveryTransactionEnvironment();
+ /*---- BEGIN FreeWalRecovery ----*/
+
/* Shut down xlogreader */
if (readFile >= 0)
{
@@ -8062,6 +8076,31 @@ StartupXLOG(void)
}
XLogReaderFree(xlogreader);
+ if (ArchiveRecoveryRequested)
+ {
+ char recoveryPath[MAXPGPATH];
+
+ /*
+ * Since there might be a partial WAL segment named RECOVERYXLOG, get
+ * rid of it.
+ */
+ snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
+ unlink(recoveryPath); /* ignore any error */
+
+ /* Get rid of any remaining recovered timeline-history file, too */
+ snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
+ unlink(recoveryPath); /* ignore any error */
+ }
+
+ /*
+ * We don't need the latch anymore. It's not strictly necessary to disown
+ * it, but let's do it for the sake of tidiness.
+ */
+ if (ArchiveRecoveryRequested)
+ DisownLatch(&XLogCtl->recoveryWakeupLatch);
+
+ /*---- END FreeWalRecovery ----*/
+
/*
* If any of the critical GUCs have changed, log them before we allow
* backends to write WAL.
--
2.30.2
--------------F589ECF1004AF34308A0B206
Content-Type: text/x-patch; charset=UTF-8;
name="v5-0002-Split-xlog.c-into-xlog.c-and-xlogrecovery.c.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename*0="v5-0002-Split-xlog.c-into-xlog.c-and-xlogrecovery.c.patch"