aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/multixact.c45
-rw-r--r--src/include/access/multixact.h2
2 files changed, 34 insertions, 13 deletions
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 9da22c8bdfc..2cdfed4945e 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -133,6 +133,19 @@
#define MULTIXACT_MEMBERS_PER_PAGE \
(MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)
+/*
+ * Because the number of items per page is not a divisor of the last item
+ * number (member 0xFFFFFFFF), the last segment does not use the maximum number
+ * of pages, and moreover the last used page therein does not use the same
+ * number of items as previous pages. (Another way to say it is that the
+ * 0xFFFFFFFF member is somewhere in the middle of the last page, so the page
+ * has some empty space after that item.)
+ *
+ * This constant is the number of members in the last page of the last segment.
+ */
+#define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE \
+ ((uint32) ((0xFFFFFFFF % MULTIXACT_MEMBERS_PER_PAGE) + 1))
+
/* page in which a member is to be found */
#define MXOffsetToMemberPage(xid) ((xid) / (TransactionId) MULTIXACT_MEMBERS_PER_PAGE)
@@ -2278,6 +2291,7 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
{
int flagsoff;
int flagsbit;
+ uint32 difference;
/*
* Only zero when at first entry of a page.
@@ -2299,24 +2313,29 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
}
/*
- * Advance to next page, taking care to properly handle the wraparound
- * case. OK if nmembers goes negative.
+ * Compute the number of items till end of current page. Careful: if
+ * addition of unsigned ints wraps around, we're at the last page of
+ * the last segment; since that page holds a different number of items
+ * than other pages, we need to do it differently.
*/
- if ((unsigned int) (offset + nmembers) < offset)
+ if (offset + MAX_MEMBERS_IN_LAST_MEMBERS_PAGE < offset)
{
- uint32 difference = offset + MULTIXACT_MEMBERS_PER_PAGE;
-
- nmembers -= (unsigned int) (MULTIXACT_MEMBERS_PER_PAGE - difference);
- offset = 0;
+ /*
+ * This is the last page of the last segment; we can compute the
+ * number of items left to allocate in it without modulo
+ * arithmetic.
+ */
+ difference = MaxMultiXactOffset - offset + 1;
}
else
- {
- int difference;
-
difference = MULTIXACT_MEMBERS_PER_PAGE - offset % MULTIXACT_MEMBERS_PER_PAGE;
- nmembers -= difference;
- offset += difference;
- }
+
+ /*
+ * Advance to next page, taking care to properly handle the wraparound
+ * case. OK if nmembers goes negative.
+ */
+ nmembers -= difference;
+ offset += difference;
}
}
diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h
index 1f048e8ed5d..80c70748cf2 100644
--- a/src/include/access/multixact.h
+++ b/src/include/access/multixact.h
@@ -25,6 +25,8 @@
#define MultiXactIdIsValid(multi) ((multi) != InvalidMultiXactId)
+#define MaxMultiXactOffset ((MultiXactOffset) 0xFFFFFFFF)
+
/* Number of SLRU buffers to use for multixact */
#define NUM_MXACTOFFSET_BUFFERS 8
#define NUM_MXACTMEMBER_BUFFERS 16