From d53bea02c9465c30c50604324ab8b59e64ccc220 Mon Sep 17 00:00:00 2001
From: Maxim Orlov <orlovmg@gmail.com>
Date: Thu, 28 Dec 2023 18:45:19 +0300
Subject: [PATCH v1 1/2] Switch to FullTransactionId for PGPROC->xid

As a step towards 64bit xids switch to FullTransactionId for PGPROC->xid.

Author: Maxim Orlov <orlovmg@gmail.com>
---
 src/backend/access/transam/clog.c     |  2 +-
 src/backend/access/transam/twophase.c |  6 ++++--
 src/backend/access/transam/varsup.c   |  4 ++--
 src/backend/commands/indexcmds.c      |  2 +-
 src/backend/storage/ipc/procarray.c   | 25 +++++++++++++------------
 src/backend/storage/ipc/sinvaladt.c   |  2 +-
 src/backend/storage/lmgr/lock.c       |  4 ++--
 src/backend/storage/lmgr/proc.c       |  4 ++--
 src/include/access/transam.h          | 15 ++++++++++++++-
 src/include/storage/proc.h            |  2 +-
 10 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 7dca1df61b..96af8166ec 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -302,7 +302,7 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
 	 * sub-XIDs and all of the XIDs for which we're adjusting clog should be
 	 * on the same page.  Check those conditions, too.
 	 */
-	if (all_xact_same_page && xid == MyProc->xid &&
+	if (all_xact_same_page && xid == XidFromFullTransactionId(MyProc->xid) &&
 		nsubxids <= THRESHOLD_SUBTRANS_CLOG_OPT &&
 		nsubxids == MyProc->subxidStatus.count &&
 		(nsubxids == 0 ||
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 11e1446cd1..4e3564580f 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -234,6 +234,8 @@ static void MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid,
 static void RemoveTwoPhaseFile(TransactionId xid, bool giveWarning);
 static void RecreateTwoPhaseFile(TransactionId xid, void *content, int len);
 
+static inline FullTransactionId AdjustToFullTransactionId(TransactionId xid);
+
 /*
  * Initialization of shared memory
  */
@@ -477,7 +479,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
 		proc->lxid = xid;
 		proc->backendId = InvalidBackendId;
 	}
-	proc->xid = xid;
+	proc->xid = AdjustToFullTransactionId(xid);
 	Assert(proc->xmin == InvalidTransactionId);
 	proc->delayChkptFlags = 0;
 	proc->statusFlags = 0;
@@ -793,7 +795,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
 		 * Form tuple with appropriate data.
 		 */
 
-		values[0] = TransactionIdGetDatum(proc->xid);
+		values[0] = TransactionIdGetDatum(XidFromFullTransactionId(proc->xid));
 		values[1] = CStringGetTextDatum(gxact->gid);
 		values[2] = TimestampTzGetDatum(gxact->prepared_at);
 		values[3] = ObjectIdGetDatum(gxact->owner);
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index 77b18b8f28..b85fae9826 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -93,7 +93,7 @@ GetNewTransactionId(bool isSubXact)
 	if (IsBootstrapProcessingMode())
 	{
 		Assert(!isSubXact);
-		MyProc->xid = BootstrapTransactionId;
+		MyProc->xid = BootstrapFullTransactionId;
 		ProcGlobal->xids[MyProc->pgxactoff] = BootstrapTransactionId;
 		return FullTransactionIdFromEpochAndXid(0, BootstrapTransactionId);
 	}
@@ -255,7 +255,7 @@ GetNewTransactionId(bool isSubXact)
 		Assert(!MyProc->subxidStatus.overflowed);
 
 		/* LWLockRelease acts as barrier */
-		MyProc->xid = xid;
+		MyProc->xid = full_xid;
 		ProcGlobal->xids[MyProc->pgxactoff] = xid;
 	}
 	else
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index e56205abd8..a070afb0a7 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -4433,7 +4433,7 @@ set_indexsafe_procflags(void)
 	 * This should only be called before installing xid or xmin in MyProc;
 	 * otherwise, concurrent processes could see an Xmin that moves backwards.
 	 */
-	Assert(MyProc->xid == InvalidTransactionId &&
+	Assert(FullTransactionIdIsInvalid(MyProc->xid) &&
 		   MyProc->xmin == InvalidTransactionId);
 
 	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 976f7856fb..ac9198ae52 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -525,7 +525,7 @@ ProcArrayAdd(PGPROC *proc)
 
 	arrayP->pgprocnos[index] = proc->pgprocno;
 	proc->pgxactoff = index;
-	ProcGlobal->xids[index] = proc->xid;
+	ProcGlobal->xids[index] = XidFromFullTransactionId(proc->xid);
 	ProcGlobal->subxidStates[index] = proc->subxidStatus;
 	ProcGlobal->statusFlags[index] = proc->statusFlags;
 
@@ -674,7 +674,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
 		 * else is taking a snapshot.  See discussion in
 		 * src/backend/access/transam/README.
 		 */
-		Assert(TransactionIdIsValid(proc->xid));
+		Assert(FullTransactionIdIsValid(proc->xid));
 
 		/*
 		 * If we can immediately acquire ProcArrayLock, we clear our own XID
@@ -696,7 +696,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
 		 * anyone else's calculation of a snapshot.  We might change their
 		 * estimate of global xmin, but that's OK.
 		 */
-		Assert(!TransactionIdIsValid(proc->xid));
+		Assert(!TransactionIdIsValid(XidFromFullTransactionId(proc->xid)));
 		Assert(proc->subxidStatus.count == 0);
 		Assert(!proc->subxidStatus.overflowed);
 
@@ -738,10 +738,10 @@ ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
 	 */
 	Assert(LWLockHeldByMeInMode(ProcArrayLock, LW_EXCLUSIVE));
 	Assert(TransactionIdIsValid(ProcGlobal->xids[pgxactoff]));
-	Assert(ProcGlobal->xids[pgxactoff] == proc->xid);
+	Assert(ProcGlobal->xids[pgxactoff] == XidFromFullTransactionId(proc->xid));
 
 	ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
-	proc->xid = InvalidTransactionId;
+	proc->xid = InvalidFullTransactionId;
 	proc->lxid = InvalidLocalTransactionId;
 	proc->xmin = InvalidTransactionId;
 
@@ -796,7 +796,7 @@ ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
 	uint32		wakeidx;
 
 	/* We should definitely have an XID to clear. */
-	Assert(TransactionIdIsValid(proc->xid));
+	Assert(FullTransactionIdIsValid(proc->xid));
 
 	/* Add ourselves to the list of processes needing a group XID clear. */
 	proc->procArrayGroupMember = true;
@@ -926,7 +926,7 @@ ProcArrayClearTransaction(PGPROC *proc)
 	pgxactoff = proc->pgxactoff;
 
 	ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
-	proc->xid = InvalidTransactionId;
+	proc->xid = InvalidFullTransactionId;
 
 	proc->lxid = InvalidLocalTransactionId;
 	proc->xmin = InvalidTransactionId;
@@ -1734,7 +1734,8 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
 	 * additions.
 	 */
 	{
-		TransactionId initial;
+		TransactionId	initial,
+						myproc_xid = XidFromFullTransactionId(MyProc->xid);
 
 		initial = XidFromFullTransactionId(h->latest_completed);
 		Assert(TransactionIdIsValid(initial));
@@ -1756,8 +1757,8 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
 		 * definition, can't be any newer changes in the temp table than
 		 * latestCompletedXid.
 		 */
-		if (TransactionIdIsValid(MyProc->xid))
-			h->temp_oldest_nonremovable = MyProc->xid;
+		if (TransactionIdIsValid(myproc_xid))
+			h->temp_oldest_nonremovable = myproc_xid;
 		else
 			h->temp_oldest_nonremovable = initial;
 	}
@@ -2222,7 +2223,7 @@ GetSnapshotData(Snapshot snapshot)
 	latest_completed = TransamVariables->latestCompletedXid;
 	mypgxactoff = MyProc->pgxactoff;
 	myxid = other_xids[mypgxactoff];
-	Assert(myxid == MyProc->xid);
+	Assert(myxid == XidFromFullTransactionId(MyProc->xid));
 
 	oldestxid = TransamVariables->oldestXid;
 	curXactCompletionCount = TransamVariables->xactCompletionCount;
@@ -3484,7 +3485,7 @@ MinimumActiveBackends(int min)
 			continue;			/* do not count deleted entries */
 		if (proc == MyProc)
 			continue;			/* do not count myself */
-		if (proc->xid == InvalidTransactionId)
+		if (FullTransactionIdIsInvalid(proc->xid))
 			continue;			/* do not count if no XID assigned */
 		if (proc->pid == 0)
 			continue;			/* do not count prepared xacts */
diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c
index 3d97c75bf1..3ae06bfa33 100644
--- a/src/backend/storage/ipc/sinvaladt.c
+++ b/src/backend/storage/ipc/sinvaladt.c
@@ -429,7 +429,7 @@ BackendIdGetTransactionIds(int backendID, TransactionId *xid,
 
 		if (proc != NULL)
 		{
-			*xid = proc->xid;
+			*xid = XidFromFullTransactionId(proc->xid);
 			*xmin = proc->xmin;
 			*nsubxid = proc->subxidStatus.count;
 			*overflowed = proc->subxidStatus.overflowed;
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index b8c57b3e16..8d988a3c17 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -3981,7 +3981,7 @@ GetRunningTransactionLocks(int *nlocks)
 		{
 			PGPROC	   *proc = proclock->tag.myProc;
 			LOCK	   *lock = proclock->tag.myLock;
-			TransactionId xid = proc->xid;
+			TransactionId xid = XidFromFullTransactionId(proc->xid);
 
 			/*
 			 * Don't record locks for transactions if we know they have
@@ -4601,7 +4601,7 @@ VirtualXactLock(VirtualTransactionId vxid, bool wait)
 	 * so we won't save an XID of a different VXID.  It doesn't matter whether
 	 * we save this before or after setting up the primary lock table entry.
 	 */
-	xid = proc->xid;
+	xid = XidFromFullTransactionId(proc->xid);
 
 	/* Done with proc->fpLockBits */
 	LWLockRelease(&proc->fpInfoLock);
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index b6451d9d08..e6e06d277b 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -377,7 +377,7 @@ InitProcess(void)
 	MyProc->lxid = InvalidLocalTransactionId;
 	MyProc->fpVXIDLock = false;
 	MyProc->fpLocalTransactionId = InvalidLocalTransactionId;
-	MyProc->xid = InvalidTransactionId;
+	MyProc->xid = InvalidFullTransactionId;
 	MyProc->xmin = InvalidTransactionId;
 	MyProc->pid = MyProcPid;
 	/* backendId, databaseId and roleId will be filled in later */
@@ -574,7 +574,7 @@ InitAuxiliaryProcess(void)
 	MyProc->lxid = InvalidLocalTransactionId;
 	MyProc->fpVXIDLock = false;
 	MyProc->fpLocalTransactionId = InvalidLocalTransactionId;
-	MyProc->xid = InvalidTransactionId;
+	MyProc->xid = InvalidFullTransactionId;
 	MyProc->xmin = InvalidTransactionId;
 	MyProc->backendId = InvalidBackendId;
 	MyProc->databaseId = InvalidOid;
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index eef2b2cdbe..2ed3040959 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -52,8 +52,8 @@
 #define FullTransactionIdPrecedesOrEquals(a, b) ((a).value <= (b).value)
 #define FullTransactionIdFollows(a, b) ((a).value > (b).value)
 #define FullTransactionIdFollowsOrEquals(a, b) ((a).value >= (b).value)
-#define FullTransactionIdIsValid(x)		TransactionIdIsValid(XidFromFullTransactionId(x))
 #define InvalidFullTransactionId		FullTransactionIdFromEpochAndXid(0, InvalidTransactionId)
+#define BootstrapFullTransactionId		FullTransactionIdFromEpochAndXid(0, BootstrapTransactionId)
 #define FirstNormalFullTransactionId	FullTransactionIdFromEpochAndXid(0, FirstNormalTransactionId)
 #define FullTransactionIdIsNormal(x)	FullTransactionIdFollowsOrEquals(x, FirstNormalFullTransactionId)
 
@@ -67,6 +67,19 @@ typedef struct FullTransactionId
 	uint64		value;
 } FullTransactionId;
 
+static inline bool
+FullTransactionIdIsValid(FullTransactionId fxid)
+{
+	/* XXX: why without epoch? Should it be fxid.value == InvalidTransactionId? */
+	return TransactionIdIsValid(XidFromFullTransactionId(fxid));
+}
+
+static inline bool
+FullTransactionIdIsInvalid(FullTransactionId fxid)
+{
+	return !FullTransactionIdIsValid(fxid);
+}
+
 static inline FullTransactionId
 FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
 {
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index e87fd25d64..bc40bae6d5 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -176,7 +176,7 @@ struct PGPROC
 	Latch		procLatch;		/* generic latch for process */
 
 
-	TransactionId xid;			/* id of top-level transaction currently being
+	FullTransactionId xid;		/* id of top-level transaction currently being
 								 * executed by this proc, if running and XID
 								 * is assigned; else InvalidTransactionId.
 								 * mirrored in ProcGlobal->xids[pgxactoff] */
-- 
2.42.0

