From e1f1e4c6aa5ddb2f656978d84577c45cc0a83c00 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Fri, 23 Jul 2021 14:27:51 -0400
Subject: [PATCH 2/3] Postpone some end-of-recovery operations relating to
 allowing WAL.

Previously, we issued XLOG_FPW_CHANGE and either
XLOG_CHECKPOINT_SHUTDOWN or XLOG_END_OF_RECOVERY while still
technically in recovery, and also performed post-archive-recovery
cleanup steps at that point. Postpone that stuff until after we clear
InRecovery and shut down the XLogReader.

This is preparatory work for a future patch that wants to allow
recovery to end at one time and only later start to allow WAL writes.
The steps that themselves write WAL clearly shouldn't happen before
we're ready to accept WAL writes, and it seems best for now to keep
the steps performed by CleanupAfterArchiveRecovery() at the same point
relative to the surrounding steps. We assume (hopefully correctly)
that the user doesn't want recovery_end_command to run until we're
committed to writing WAL on the new timeline. Until then, the
machine is still usable as a standby on the old timeline.

Aside from the value of this patch as preparatory work, this order of
operations actually seems more logical, since it means we don't
actually write any WAL until after exiting recovery.
---
 src/backend/access/transam/xlog.c | 34 ++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 203a9babc9..c652a0635d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7999,22 +7999,11 @@ StartupXLOG(void)
 	XLogCtl->LogwrtRqst.Flush = EndOfLog;
 
 	/*
-	 * Update full_page_writes in shared memory and write an XLOG_FPW_CHANGE
-	 * record before resource manager writes cleanup WAL records or checkpoint
-	 * record is written.
+	 * Figure out what xlog activity is needed to mark end of recovery. We
+	 * must make this determination before setting InRecovery = false, or
+	 * we'll get the wrong answer.
 	 */
-	Insert->fullPageWrites = lastFullPageWrites;
-	LocalSetXLogInsertAllowed();
-	UpdateFullPageWrites();
-	LocalXLogInsertAllowed = -1;
-
-	/* Emit checkpoint or end-of-recovery record in XLOG, if required. */
 	xlogaction = DetermineRecoveryXlogAction(xlogreader);
-	PerformRecoveryXLogAction(xlogaction);
-
-	/* If this is archive recovery, perform post-recovery cleanup actions. */
-	if (ArchiveRecoveryRequested)
-		CleanupAfterArchiveRecovery(EndOfLogTLI, EndOfLog);
 
 	/*
 	 * Preallocate additional log files, if wanted.
@@ -8067,6 +8056,23 @@ StartupXLOG(void)
 	}
 	XLogReaderFree(xlogreader);
 
+	/*
+	 * Update full_page_writes in shared memory and write an XLOG_FPW_CHANGE
+	 * record before resource manager writes cleanup WAL records or checkpoint
+	 * record is written.
+	 */
+	Insert->fullPageWrites = lastFullPageWrites;
+	LocalSetXLogInsertAllowed();
+	UpdateFullPageWrites();
+	LocalXLogInsertAllowed = -1;
+
+	/* Emit checkpoint or end-of-recovery record in XLOG, if required. */
+	PerformRecoveryXLogAction(xlogaction);
+
+	/* If this is archive recovery, perform post-recovery cleanup actions. */
+	if (ArchiveRecoveryRequested)
+		CleanupAfterArchiveRecovery(EndOfLogTLI, EndOfLog);
+
 	/*
 	 * If any of the critical GUCs have changed, log them before we allow
 	 * backends to write WAL.
-- 
2.24.3 (Apple Git-128)

