Skip to content

Commit bb3b1c4

Browse files
committed
Move pg_multixact SLRU page format definitions to a separate header
This makes them accessible from pg_upgrade, needed by the next commit. I'm doing this mechanical move as a separate commit to make the next commit's changes to these definitions more obvious. Author: Maxim Orlov <orlovmg@gmail.com> Discussion: https://www.postgresql.org/message-id/CACG%3DezbZo_3_fnx%3DS5BfepwRftzrpJ%2B7WET4EkTU6wnjDTsnjg@mail.gmail.com
1 parent e9443a5 commit bb3b1c4

File tree

2 files changed

+141
-119
lines changed

2 files changed

+141
-119
lines changed

src/backend/access/transam/multixact.c

Lines changed: 1 addition & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
#include "postgres.h"
7070

7171
#include "access/multixact.h"
72+
#include "access/multixact_internal.h"
7273
#include "access/slru.h"
7374
#include "access/twophase.h"
7475
#include "access/twophase_rmgr.h"
@@ -88,125 +89,6 @@
8889
#include "utils/memutils.h"
8990

9091

91-
/*
92-
* Defines for MultiXactOffset page sizes. A page is the same BLCKSZ as is
93-
* used everywhere else in Postgres.
94-
*
95-
* Note: because MultiXactOffsets are 32 bits and wrap around at 0xFFFFFFFF,
96-
* MultiXact page numbering also wraps around at
97-
* 0xFFFFFFFF/MULTIXACT_OFFSETS_PER_PAGE, and segment numbering at
98-
* 0xFFFFFFFF/MULTIXACT_OFFSETS_PER_PAGE/SLRU_PAGES_PER_SEGMENT. We need
99-
* take no explicit notice of that fact in this module, except when comparing
100-
* segment and page numbers in TruncateMultiXact (see
101-
* MultiXactOffsetPagePrecedes).
102-
*/
103-
104-
/* We need four bytes per offset */
105-
#define MULTIXACT_OFFSETS_PER_PAGE (BLCKSZ / sizeof(MultiXactOffset))
106-
107-
static inline int64
108-
MultiXactIdToOffsetPage(MultiXactId multi)
109-
{
110-
return multi / MULTIXACT_OFFSETS_PER_PAGE;
111-
}
112-
113-
static inline int
114-
MultiXactIdToOffsetEntry(MultiXactId multi)
115-
{
116-
return multi % MULTIXACT_OFFSETS_PER_PAGE;
117-
}
118-
119-
static inline int64
120-
MultiXactIdToOffsetSegment(MultiXactId multi)
121-
{
122-
return MultiXactIdToOffsetPage(multi) / SLRU_PAGES_PER_SEGMENT;
123-
}
124-
125-
/*
126-
* The situation for members is a bit more complex: we store one byte of
127-
* additional flag bits for each TransactionId. To do this without getting
128-
* into alignment issues, we store four bytes of flags, and then the
129-
* corresponding 4 Xids. Each such 5-word (20-byte) set we call a "group", and
130-
* are stored as a whole in pages. Thus, with 8kB BLCKSZ, we keep 409 groups
131-
* per page. This wastes 12 bytes per page, but that's OK -- simplicity (and
132-
* performance) trumps space efficiency here.
133-
*
134-
* Note that the "offset" macros work with byte offset, not array indexes, so
135-
* arithmetic must be done using "char *" pointers.
136-
*/
137-
/* We need eight bits per xact, so one xact fits in a byte */
138-
#define MXACT_MEMBER_BITS_PER_XACT 8
139-
#define MXACT_MEMBER_FLAGS_PER_BYTE 1
140-
#define MXACT_MEMBER_XACT_BITMASK ((1 << MXACT_MEMBER_BITS_PER_XACT) - 1)
141-
142-
/* how many full bytes of flags are there in a group? */
143-
#define MULTIXACT_FLAGBYTES_PER_GROUP 4
144-
#define MULTIXACT_MEMBERS_PER_MEMBERGROUP \
145-
(MULTIXACT_FLAGBYTES_PER_GROUP * MXACT_MEMBER_FLAGS_PER_BYTE)
146-
/* size in bytes of a complete group */
147-
#define MULTIXACT_MEMBERGROUP_SIZE \
148-
(sizeof(TransactionId) * MULTIXACT_MEMBERS_PER_MEMBERGROUP + MULTIXACT_FLAGBYTES_PER_GROUP)
149-
#define MULTIXACT_MEMBERGROUPS_PER_PAGE (BLCKSZ / MULTIXACT_MEMBERGROUP_SIZE)
150-
#define MULTIXACT_MEMBERS_PER_PAGE \
151-
(MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)
152-
153-
/*
154-
* Because the number of items per page is not a divisor of the last item
155-
* number (member 0xFFFFFFFF), the last segment does not use the maximum number
156-
* of pages, and moreover the last used page therein does not use the same
157-
* number of items as previous pages. (Another way to say it is that the
158-
* 0xFFFFFFFF member is somewhere in the middle of the last page, so the page
159-
* has some empty space after that item.)
160-
*
161-
* This constant is the number of members in the last page of the last segment.
162-
*/
163-
#define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE \
164-
((uint32) ((0xFFFFFFFF % MULTIXACT_MEMBERS_PER_PAGE) + 1))
165-
166-
/* page in which a member is to be found */
167-
static inline int64
168-
MXOffsetToMemberPage(MultiXactOffset offset)
169-
{
170-
return offset / MULTIXACT_MEMBERS_PER_PAGE;
171-
}
172-
173-
static inline int64
174-
MXOffsetToMemberSegment(MultiXactOffset offset)
175-
{
176-
return MXOffsetToMemberPage(offset) / SLRU_PAGES_PER_SEGMENT;
177-
}
178-
179-
/* Location (byte offset within page) of flag word for a given member */
180-
static inline int
181-
MXOffsetToFlagsOffset(MultiXactOffset offset)
182-
{
183-
MultiXactOffset group = offset / MULTIXACT_MEMBERS_PER_MEMBERGROUP;
184-
int grouponpg = group % MULTIXACT_MEMBERGROUPS_PER_PAGE;
185-
int byteoff = grouponpg * MULTIXACT_MEMBERGROUP_SIZE;
186-
187-
return byteoff;
188-
}
189-
190-
static inline int
191-
MXOffsetToFlagsBitShift(MultiXactOffset offset)
192-
{
193-
int member_in_group = offset % MULTIXACT_MEMBERS_PER_MEMBERGROUP;
194-
int bshift = member_in_group * MXACT_MEMBER_BITS_PER_XACT;
195-
196-
return bshift;
197-
}
198-
199-
/* Location (byte offset within page) of TransactionId of given member */
200-
static inline int
201-
MXOffsetToMemberOffset(MultiXactOffset offset)
202-
{
203-
int member_in_group = offset % MULTIXACT_MEMBERS_PER_MEMBERGROUP;
204-
205-
return MXOffsetToFlagsOffset(offset) +
206-
MULTIXACT_FLAGBYTES_PER_GROUP +
207-
member_in_group * sizeof(TransactionId);
208-
}
209-
21092
/* Multixact members wraparound thresholds. */
21193
#define MULTIXACT_MEMBER_SAFE_THRESHOLD (MaxMultiXactOffset / 2)
21294
#define MULTIXACT_MEMBER_DANGER_THRESHOLD \
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* multixact_internal.h
3+
*
4+
* PostgreSQL multi-transaction-log manager internal declarations
5+
*
6+
* These functions and definitions are for dealing with pg_multixact SLRU
7+
* pages. They are internal to multixact.c, but they are exported here to
8+
* allow pg_upgrade to write pg_multixact files directly.
9+
*
10+
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
11+
* Portions Copyright (c) 1994, Regents of the University of California
12+
*
13+
* src/include/access/multixact_internal.h
14+
*/
15+
#ifndef MULTIXACT_INTERNAL_H
16+
#define MULTIXACT_INTERNAL_H
17+
18+
#include "access/multixact.h"
19+
20+
21+
/*
22+
* Defines for MultiXactOffset page sizes. A page is the same BLCKSZ as is
23+
* used everywhere else in Postgres.
24+
*
25+
* Note: because MultiXactOffsets are 32 bits and wrap around at 0xFFFFFFFF,
26+
* MultiXact page numbering also wraps around at
27+
* 0xFFFFFFFF/MULTIXACT_OFFSETS_PER_PAGE, and segment numbering at
28+
* 0xFFFFFFFF/MULTIXACT_OFFSETS_PER_PAGE/SLRU_PAGES_PER_SEGMENT. We need
29+
* take no explicit notice of that fact in this module, except when comparing
30+
* segment and page numbers in TruncateMultiXact (see
31+
* MultiXactOffsetPagePrecedes).
32+
*/
33+
34+
/* We need four bytes per offset */
35+
#define MULTIXACT_OFFSETS_PER_PAGE (BLCKSZ / sizeof(MultiXactOffset))
36+
37+
static inline int64
38+
MultiXactIdToOffsetPage(MultiXactId multi)
39+
{
40+
return multi / MULTIXACT_OFFSETS_PER_PAGE;
41+
}
42+
43+
static inline int
44+
MultiXactIdToOffsetEntry(MultiXactId multi)
45+
{
46+
return multi % MULTIXACT_OFFSETS_PER_PAGE;
47+
}
48+
49+
static inline int64
50+
MultiXactIdToOffsetSegment(MultiXactId multi)
51+
{
52+
return MultiXactIdToOffsetPage(multi) / SLRU_PAGES_PER_SEGMENT;
53+
}
54+
55+
/*
56+
* The situation for members is a bit more complex: we store one byte of
57+
* additional flag bits for each TransactionId. To do this without getting
58+
* into alignment issues, we store four bytes of flags, and then the
59+
* corresponding 4 Xids. Each such 5-word (20-byte) set we call a "group", and
60+
* are stored as a whole in pages. Thus, with 8kB BLCKSZ, we keep 409 groups
61+
* per page. This wastes 12 bytes per page, but that's OK -- simplicity (and
62+
* performance) trumps space efficiency here.
63+
*
64+
* Note that the "offset" macros work with byte offset, not array indexes, so
65+
* arithmetic must be done using "char *" pointers.
66+
*/
67+
/* We need eight bits per xact, so one xact fits in a byte */
68+
#define MXACT_MEMBER_BITS_PER_XACT 8
69+
#define MXACT_MEMBER_FLAGS_PER_BYTE 1
70+
#define MXACT_MEMBER_XACT_BITMASK ((1 << MXACT_MEMBER_BITS_PER_XACT) - 1)
71+
72+
/* how many full bytes of flags are there in a group? */
73+
#define MULTIXACT_FLAGBYTES_PER_GROUP 4
74+
#define MULTIXACT_MEMBERS_PER_MEMBERGROUP \
75+
(MULTIXACT_FLAGBYTES_PER_GROUP * MXACT_MEMBER_FLAGS_PER_BYTE)
76+
/* size in bytes of a complete group */
77+
#define MULTIXACT_MEMBERGROUP_SIZE \
78+
(sizeof(TransactionId) * MULTIXACT_MEMBERS_PER_MEMBERGROUP + MULTIXACT_FLAGBYTES_PER_GROUP)
79+
#define MULTIXACT_MEMBERGROUPS_PER_PAGE (BLCKSZ / MULTIXACT_MEMBERGROUP_SIZE)
80+
#define MULTIXACT_MEMBERS_PER_PAGE \
81+
(MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)
82+
83+
/*
84+
* Because the number of items per page is not a divisor of the last item
85+
* number (member 0xFFFFFFFF), the last segment does not use the maximum number
86+
* of pages, and moreover the last used page therein does not use the same
87+
* number of items as previous pages. (Another way to say it is that the
88+
* 0xFFFFFFFF member is somewhere in the middle of the last page, so the page
89+
* has some empty space after that item.)
90+
*
91+
* This constant is the number of members in the last page of the last segment.
92+
*/
93+
#define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE \
94+
((uint32) ((0xFFFFFFFF % MULTIXACT_MEMBERS_PER_PAGE) + 1))
95+
96+
/* page in which a member is to be found */
97+
static inline int64
98+
MXOffsetToMemberPage(MultiXactOffset offset)
99+
{
100+
return offset / MULTIXACT_MEMBERS_PER_PAGE;
101+
}
102+
103+
static inline int64
104+
MXOffsetToMemberSegment(MultiXactOffset offset)
105+
{
106+
return MXOffsetToMemberPage(offset) / SLRU_PAGES_PER_SEGMENT;
107+
}
108+
109+
/* Location (byte offset within page) of flag word for a given member */
110+
static inline int
111+
MXOffsetToFlagsOffset(MultiXactOffset offset)
112+
{
113+
MultiXactOffset group = offset / MULTIXACT_MEMBERS_PER_MEMBERGROUP;
114+
int grouponpg = group % MULTIXACT_MEMBERGROUPS_PER_PAGE;
115+
int byteoff = grouponpg * MULTIXACT_MEMBERGROUP_SIZE;
116+
117+
return byteoff;
118+
}
119+
120+
static inline int
121+
MXOffsetToFlagsBitShift(MultiXactOffset offset)
122+
{
123+
int member_in_group = offset % MULTIXACT_MEMBERS_PER_MEMBERGROUP;
124+
int bshift = member_in_group * MXACT_MEMBER_BITS_PER_XACT;
125+
126+
return bshift;
127+
}
128+
129+
/* Location (byte offset within page) of TransactionId of given member */
130+
static inline int
131+
MXOffsetToMemberOffset(MultiXactOffset offset)
132+
{
133+
int member_in_group = offset % MULTIXACT_MEMBERS_PER_MEMBERGROUP;
134+
135+
return MXOffsetToFlagsOffset(offset) +
136+
MULTIXACT_FLAGBYTES_PER_GROUP +
137+
member_in_group * sizeof(TransactionId);
138+
}
139+
140+
#endif /* MULTIXACT_INTERNAL_H */

0 commit comments

Comments
 (0)