From aae52b88ce67adc0261ebfeafb8496ed9e88d240 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Tue, 13 Aug 2024 16:40:57 +0300
Subject: [PATCH 4/5] Remove the now-unused xids array from xl_running_xacts

We still generate running-xacts records, because they are still needed
to initialize the snapshot in logical decoding.
---
 src/backend/access/rmgrdesc/standbydesc.c   | 18 ------------
 src/backend/replication/logical/snapbuild.c |  8 +++---
 src/backend/storage/ipc/standby.c           | 32 +++++----------------
 src/include/storage/standby.h               |  2 --
 src/include/storage/standbydefs.h           | 16 +++++++----
 5 files changed, 21 insertions(+), 55 deletions(-)

diff --git a/src/backend/access/rmgrdesc/standbydesc.c b/src/backend/access/rmgrdesc/standbydesc.c
index 32e509a4006..99f08beb4a8 100644
--- a/src/backend/access/rmgrdesc/standbydesc.c
+++ b/src/backend/access/rmgrdesc/standbydesc.c
@@ -19,28 +19,10 @@
 static void
 standby_desc_running_xacts(StringInfo buf, xl_running_xacts *xlrec)
 {
-	int			i;
-
 	appendStringInfo(buf, "nextXid %u latestCompletedXid %u oldestRunningXid %u",
 					 xlrec->nextXid,
 					 xlrec->latestCompletedXid,
 					 xlrec->oldestRunningXid);
-	if (xlrec->xcnt > 0)
-	{
-		appendStringInfo(buf, "; %d xacts:", xlrec->xcnt);
-		for (i = 0; i < xlrec->xcnt; i++)
-			appendStringInfo(buf, " %u", xlrec->xids[i]);
-	}
-
-	if (xlrec->subxid_overflow)
-		appendStringInfoString(buf, "; subxid overflowed");
-
-	if (xlrec->subxcnt > 0)
-	{
-		appendStringInfo(buf, "; %d subxacts:", xlrec->subxcnt);
-		for (i = 0; i < xlrec->subxcnt; i++)
-			appendStringInfo(buf, " %u", xlrec->xids[xlrec->xcnt + i]);
-	}
 }
 
 void
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index 31da0832cc3..cac3ffe577e 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1316,8 +1316,8 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
 		ereport(LOG,
 				(errmsg("logical decoding found initial starting point at %X/%X",
 						LSN_FORMAT_ARGS(lsn)),
-				 errdetail("Waiting for transactions (approximately %d) older than %u to end.",
-						   running->xcnt, running->nextXid)));
+				 errdetail("Waiting for transactions older than %u to end.",
+						   running->nextXid)));
 
 		SnapBuildWaitSnapshot(running->nextXid);
 	}
@@ -1340,8 +1340,8 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
 		ereport(LOG,
 				(errmsg("logical decoding found initial consistent point at %X/%X",
 						LSN_FORMAT_ARGS(lsn)),
-				 errdetail("Waiting for transactions (approximately %d) older than %u to end.",
-						   running->xcnt, running->nextXid)));
+				 errdetail("Waiting for transactions older than %u to end.",
+						   running->nextXid)));
 
 		SnapBuildWaitSnapshot(running->nextXid);
 	}
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index e02c9ab842d..6ed46bed033 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -1337,9 +1337,6 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
 	xl_running_xacts xlrec;
 	XLogRecPtr	recptr;
 
-	xlrec.xcnt = CurrRunningXacts->xcnt;
-	xlrec.subxcnt = CurrRunningXacts->subxcnt;
-	xlrec.subxid_overflow = (CurrRunningXacts->subxid_status != SUBXIDS_IN_ARRAY);
 	xlrec.nextXid = CurrRunningXacts->nextXid;
 	xlrec.oldestRunningXid = CurrRunningXacts->oldestRunningXid;
 	xlrec.latestCompletedXid = CurrRunningXacts->latestCompletedXid;
@@ -1347,31 +1344,16 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
 	/* Header */
 	XLogBeginInsert();
 	XLogSetRecordFlags(XLOG_MARK_UNIMPORTANT);
-	XLogRegisterData((char *) (&xlrec), MinSizeOfXactRunningXacts);
-
-	/* array of TransactionIds */
-	if (xlrec.xcnt > 0)
-		XLogRegisterData((char *) CurrRunningXacts->xids,
-						 (xlrec.xcnt + xlrec.subxcnt) * sizeof(TransactionId));
+	XLogRegisterData((char *) (&xlrec), SizeOfXactRunningXacts);
 
 	recptr = XLogInsert(RM_STANDBY_ID, XLOG_RUNNING_XACTS);
 
-	if (xlrec.subxid_overflow)
-		elog(DEBUG2,
-			 "snapshot of %d running transactions overflowed (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
-			 CurrRunningXacts->xcnt,
-			 LSN_FORMAT_ARGS(recptr),
-			 CurrRunningXacts->oldestRunningXid,
-			 CurrRunningXacts->latestCompletedXid,
-			 CurrRunningXacts->nextXid);
-	else
-		elog(DEBUG2,
-			 "snapshot of %d+%d running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
-			 CurrRunningXacts->xcnt, CurrRunningXacts->subxcnt,
-			 LSN_FORMAT_ARGS(recptr),
-			 CurrRunningXacts->oldestRunningXid,
-			 CurrRunningXacts->latestCompletedXid,
-			 CurrRunningXacts->nextXid);
+	elog(DEBUG2,
+		 "logging running transaction bounds (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
+		 LSN_FORMAT_ARGS(recptr),
+		 CurrRunningXacts->oldestRunningXid,
+		 CurrRunningXacts->latestCompletedXid,
+		 CurrRunningXacts->nextXid);
 
 	/*
 	 * Ensure running_xacts information is synced to disk not too far in the
diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h
index cce0bc521e7..9d5a298a392 100644
--- a/src/include/storage/standby.h
+++ b/src/include/storage/standby.h
@@ -60,8 +60,6 @@ extern void StandbyReleaseLockTree(TransactionId xid,
 extern void StandbyReleaseAllLocks(void);
 extern void StandbyReleaseOldLocks(TransactionId oldxid);
 
-#define MinSizeOfXactRunningXacts offsetof(xl_running_xacts, xids)
-
 
 /*
  * Declarations for GetRunningTransactionData(). Similar to Snapshots, but
diff --git a/src/include/storage/standbydefs.h b/src/include/storage/standbydefs.h
index fe12f463a86..d8582094472 100644
--- a/src/include/storage/standbydefs.h
+++ b/src/include/storage/standbydefs.h
@@ -42,20 +42,24 @@ typedef struct xl_standby_locks
 } xl_standby_locks;
 
 /*
- * When we write running xact data to WAL, we use this structure.
+ * Data included in an XLOG_RUNNING_XACTS record.
+ *
+ * This used to include a list of running XIDs, hence the name, but nowadays
+ * this only contains the min and max bounds of the transactions that were
+ * running when the record was written.  They are needed to initialize logical
+ * decoding.  They are also used in hot standby to prune information about old
+ * running transactions, in case the the primary didn't write a COMMIT/ABORT
+ * record for some reason.
  */
 typedef struct xl_running_xacts
 {
-	int			xcnt;			/* # of xact ids in xids[] */
-	int			subxcnt;		/* # of subxact ids in xids[] */
-	bool		subxid_overflow;	/* snapshot overflowed, subxids missing */
 	TransactionId nextXid;		/* xid from TransamVariables->nextXid */
 	TransactionId oldestRunningXid; /* *not* oldestXmin */
 	TransactionId latestCompletedXid;	/* so we can set xmax */
-
-	TransactionId xids[FLEXIBLE_ARRAY_MEMBER];
 } xl_running_xacts;
 
+#define SizeOfXactRunningXacts sizeof(xl_running_xacts)
+
 /*
  * Invalidations for standby, currently only when transactions without an
  * assigned xid commit.
-- 
2.39.5

