From f8409b39d1dae28f063b378b9edee1a657845503 Mon Sep 17 00:00:00 2001
From: Simon Riggs <simon@2ndQuadrant.com>
Date: Wed, 2 Nov 2011 08:07:44 +0000
Subject: [PATCH] Fix timing of Startup CLOG and MultiXact during Hot Standby

Patch by me, bug report by Chris Redekop, analysis by Florian Pflug
---
 src/backend/access/transam/clog.c      | 19 +++++++++++++++++++
 src/backend/access/transam/multixact.c |  2 +-
 src/backend/access/transam/xlog.c      | 17 ++++++++++++-----
 src/backend/utils/init/postinit.c      |  1 +
 src/include/access/clog.h              |  1 +
 5 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index ee645f7bd47..6a2bf83362f 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -489,6 +489,25 @@ StartupCLOG(void)
 	 */
 	ClogCtl->shared->latest_page_number = pageno;
 
+	LWLockRelease(CLogControlLock);
+}
+
+/*
+ * This must be called ONCE at the end of startup/recovery.
+ */
+void
+TrimCLOG(void)
+{
+	TransactionId xid = ShmemVariableCache->nextXid;
+	int			pageno = TransactionIdToPage(xid);
+
+	LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
+
+	/*
+	 * Re-Initialize our idea of the latest page number.
+	 */
+	ClogCtl->shared->latest_page_number = pageno;
+
 	/*
 	 * Zero out the remainder of the current clog page.  Under normal
 	 * circumstances it should be zeroes already, but it seems at least
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 1d159bc89cb..c1c8ba52da3 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1567,7 +1567,7 @@ StartupMultiXact(void)
 
 	/*
 	 * Zero out the remainder of the current members page.	See notes in
-	 * StartupCLOG() for motivation.
+	 * TrimCLOG() for motivation.
 	 */
 	entryno = MXOffsetToMemberEntry(offset);
 	if (entryno != 0)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index a6aee9eb30c..bf57b3bf49e 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6410,10 +6410,12 @@ StartupXLOG(void)
 				oldestActiveXID = checkPoint.oldestActiveXid;
 			Assert(TransactionIdIsValid(oldestActiveXID));
 
-			/* Startup commit log and related stuff */
+			/*
+			 * Startup commit log and subtrans only. Other SLRUs are not
+			 * maintained during recovery and need not be started yet.
+			 */
 			StartupCLOG();
 			StartupSUBTRANS(oldestActiveXID);
-			StartupMultiXact();
 
 			/*
 			 * If we're beginning at a shutdown checkpoint, we know that
@@ -6914,16 +6916,21 @@ StartupXLOG(void)
 	TransactionIdRetreat(ShmemVariableCache->latestCompletedXid);
 
 	/*
-	 * Start up the commit log and related stuff, too. In hot standby mode we
-	 * did this already before WAL replay.
+	 * Start up the commit log and subtrans, if not already done for
+	 * hot standby.
 	 */
 	if (standbyState == STANDBY_DISABLED)
 	{
 		StartupCLOG();
 		StartupSUBTRANS(oldestActiveXID);
-		StartupMultiXact();
 	}
 
+	/*
+	 * Perform end of recovery actions for any SLRUs that need it.
+	 */
+	StartupMultiXact();
+	TrimCLOG();
+
 	/* Reload shared-memory state for prepared transactions */
 	RecoverPreparedTransactions();
 
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 94f92dd7343..0fda55af0fc 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -36,6 +36,7 @@
 #include "pgstat.h"
 #include "postmaster/autovacuum.h"
 #include "postmaster/postmaster.h"
+#include "postmaster/startup.h"
 #include "replication/walsender.h"
 #include "storage/bufmgr.h"
 #include "storage/fd.h"
diff --git a/src/include/access/clog.h b/src/include/access/clog.h
index 7a8918e0fc5..691430c97ca 100644
--- a/src/include/access/clog.h
+++ b/src/include/access/clog.h
@@ -40,6 +40,7 @@ extern Size CLOGShmemSize(void);
 extern void CLOGShmemInit(void);
 extern void BootStrapCLOG(void);
 extern void StartupCLOG(void);
+extern void TrimCLOG(void);
 extern void ShutdownCLOG(void);
 extern void CheckPointCLOG(void);
 extern void ExtendCLOG(TransactionId newestXact);
-- 
GitLab