From 8e6dc7951708d65d993ec82618806ad39c7920ed Mon Sep 17 00:00:00 2001
From: Ivan Bykov <i.bykov@modernsys.ru>
Date: Fri, 24 Oct 2025 22:04:16 +0500
Subject: [PATCH] [PATCH v9] Introduce NextMultiXactId()

---
 src/backend/access/transam/multixact.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 17c95fc18fc..b4a3ff3bf83 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -219,6 +219,12 @@ PreviousMultiXactId(MultiXactId multi)
 	return multi == FirstMultiXactId ? MaxMultiXactId : multi - 1;
 }
 
+static inline MultiXactId
+NextMultiXactId(MultiXactId multi)
+{
+	return multi == MaxMultiXactId ? FirstMultiXactId : multi + 1;
+}
+
 /*
  * Links to shared-memory data structures for MultiXact control
  */
@@ -909,7 +915,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 	int			i;
 	LWLock	   *lock;
 	LWLock	   *prevlock = NULL;
-	MultiXactId next = multi + 1;
+	MultiXactId next;
 	int			next_pageno;
 
 	pageno = MultiXactIdToOffsetPage(multi);
@@ -919,8 +925,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 	 * We must also fill next offset to keep current multi readable
 	 * Handle wraparound as GetMultiXactIdMembers() does it.
 	 */
-	if (next < FirstMultiXactId)
-		next = FirstMultiXactId;
+	next = NextMultiXactId(multi);
 	next_pageno = MultiXactIdToOffsetPage(next);
 
 	lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
@@ -1165,7 +1170,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
 	}
 
 	/* Make sure there is room for the MXID and next offset in the file. */
-	ExtendMultiXactOffset(MultiXactState->nextMXact + 1);
+	ExtendMultiXactOffset(NextMultiXactId(MultiXactState->nextMXact));
 
 	/*
 	 * Reserve the members space, similarly to above.  Also, be careful not to
@@ -1275,7 +1280,8 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
 	 * with either case.  Similarly, nextOffset may be zero, but we won't use
 	 * that as the actual start offset of the next multixact.
 	 */
-	(MultiXactState->nextMXact)++;
+	
+	MultiXactState->nextMXact = NextMultiXactId(MultiXactState->nextMXact);
 
 	MultiXactState->nextOffset += nmembers;
 
@@ -1455,7 +1461,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
 	 * Use the same increment rule as GetNewMultiXactId(), that is, don't
 	 * handle wraparound explicitly until needed.
 	 */
-	tmpMXact = multi + 1;
+	tmpMXact = NextMultiXactId(multi);
 
 	if (nextMXact == tmpMXact)
 	{
@@ -1466,10 +1472,6 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
 	{
 		MultiXactOffset nextMXOffset;
 
-		/* handle wraparound if needed */
-		if (tmpMXact < FirstMultiXactId)
-			tmpMXact = FirstMultiXactId;
-
 		prev_pageno = pageno;
 
 		pageno = MultiXactIdToOffsetPage(tmpMXact);
@@ -3373,7 +3375,7 @@ multixact_redo(XLogReaderState *record)
 						   xlrec->members);
 
 		/* Make sure nextMXact/nextOffset are beyond what this record has */
-		MultiXactAdvanceNextMXact(xlrec->mid + 1,
+		MultiXactAdvanceNextMXact(NextMultiXactId(xlrec->mid),
 								  xlrec->moff + xlrec->nmembers);
 
 		/*
-- 
2.39.5

