PostgreSQL Source Code git master
multixact_read_v18.c File Reference
#include "postgres_fe.h"
#include "multixact_read_v18.h"
#include "pg_upgrade.h"
Include dependency graph for multixact_read_v18.c:

Go to the source code of this file.

Macros

#define MultiXactOffset   should_not_be_used
 
#define MULTIXACT_OFFSETS_PER_PAGE   (BLCKSZ / sizeof(MultiXactOffset32))
 
#define MXACT_MEMBER_BITS_PER_XACT   8
 
#define MXACT_MEMBER_FLAGS_PER_BYTE   1
 
#define MXACT_MEMBER_XACT_BITMASK   ((1 << MXACT_MEMBER_BITS_PER_XACT) - 1)
 
#define MULTIXACT_FLAGBYTES_PER_GROUP   4
 
#define MULTIXACT_MEMBERS_PER_MEMBERGROUP    (MULTIXACT_FLAGBYTES_PER_GROUP * MXACT_MEMBER_FLAGS_PER_BYTE)
 
#define MULTIXACT_MEMBERGROUP_SIZE    (sizeof(TransactionId) * MULTIXACT_MEMBERS_PER_MEMBERGROUP + MULTIXACT_FLAGBYTES_PER_GROUP)
 
#define MULTIXACT_MEMBERGROUPS_PER_PAGE   (BLCKSZ / MULTIXACT_MEMBERGROUP_SIZE)
 
#define MULTIXACT_MEMBERS_PER_PAGE    (MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)
 

Functions

static int64 MultiXactIdToOffsetPage (MultiXactId multi)
 
static int MultiXactIdToOffsetEntry (MultiXactId multi)
 
static int64 MXOffsetToMemberPage (MultiXactOffset32 offset)
 
static int MXOffsetToFlagsOffset (MultiXactOffset32 offset)
 
static int MXOffsetToMemberOffset (MultiXactOffset32 offset)
 
static int MXOffsetToFlagsBitShift (MultiXactOffset32 offset)
 
OldMultiXactReaderAllocOldMultiXactRead (char *pgdata, MultiXactId nextMulti, MultiXactOffset32 nextOffset)
 
bool GetOldMultiXactIdSingleMember (OldMultiXactReader *state, MultiXactId multi, MultiXactMember *member)
 
void FreeOldMultiXactReader (OldMultiXactReader *state)
 

Macro Definition Documentation

◆ MULTIXACT_FLAGBYTES_PER_GROUP

#define MULTIXACT_FLAGBYTES_PER_GROUP   4

Definition at line 65 of file multixact_read_v18.c.

◆ MULTIXACT_MEMBERGROUP_SIZE

#define MULTIXACT_MEMBERGROUP_SIZE    (sizeof(TransactionId) * MULTIXACT_MEMBERS_PER_MEMBERGROUP + MULTIXACT_FLAGBYTES_PER_GROUP)

Definition at line 69 of file multixact_read_v18.c.

◆ MULTIXACT_MEMBERGROUPS_PER_PAGE

#define MULTIXACT_MEMBERGROUPS_PER_PAGE   (BLCKSZ / MULTIXACT_MEMBERGROUP_SIZE)

Definition at line 71 of file multixact_read_v18.c.

◆ MULTIXACT_MEMBERS_PER_MEMBERGROUP

#define MULTIXACT_MEMBERS_PER_MEMBERGROUP    (MULTIXACT_FLAGBYTES_PER_GROUP * MXACT_MEMBER_FLAGS_PER_BYTE)

Definition at line 66 of file multixact_read_v18.c.

◆ MULTIXACT_MEMBERS_PER_PAGE

#define MULTIXACT_MEMBERS_PER_PAGE    (MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)

Definition at line 72 of file multixact_read_v18.c.

◆ MULTIXACT_OFFSETS_PER_PAGE

#define MULTIXACT_OFFSETS_PER_PAGE   (BLCKSZ / sizeof(MultiXactOffset32))

Definition at line 33 of file multixact_read_v18.c.

◆ MultiXactOffset

#define MultiXactOffset   should_not_be_used

Definition at line 30 of file multixact_read_v18.c.

◆ MXACT_MEMBER_BITS_PER_XACT

#define MXACT_MEMBER_BITS_PER_XACT   8

Definition at line 60 of file multixact_read_v18.c.

◆ MXACT_MEMBER_FLAGS_PER_BYTE

#define MXACT_MEMBER_FLAGS_PER_BYTE   1

Definition at line 61 of file multixact_read_v18.c.

◆ MXACT_MEMBER_XACT_BITMASK

#define MXACT_MEMBER_XACT_BITMASK   ((1 << MXACT_MEMBER_BITS_PER_XACT) - 1)

Definition at line 62 of file multixact_read_v18.c.

Function Documentation

◆ AllocOldMultiXactRead()

OldMultiXactReader * AllocOldMultiXactRead ( char *  pgdata,
MultiXactId  nextMulti,
MultiXactOffset32  nextOffset 
)

Definition at line 119 of file multixact_read_v18.c.

121{
123 char dir[MAXPGPATH] = {0};
124
125 state->nextMXact = nextMulti;
126 state->nextOffset = nextOffset;
127
128 pg_sprintf(dir, "%s/pg_multixact/offsets", pgdata);
129 state->offset = AllocSlruRead(dir, false);
130
131 pg_sprintf(dir, "%s/pg_multixact/members", pgdata);
132 state->members = AllocSlruRead(dir, false);
133
134 return state;
135}
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define MAXPGPATH
int int int int pg_sprintf(char *str, const char *fmt,...) pg_attribute_printf(2
SlruSegState * AllocSlruRead(const char *dir, bool long_segment_names)
Definition: slru_io.c:62
Definition: regguts.h:323

References AllocSlruRead(), MAXPGPATH, pg_malloc(), and pg_sprintf().

Referenced by rewrite_multixacts().

◆ FreeOldMultiXactReader()

void FreeOldMultiXactReader ( OldMultiXactReader state)

Definition at line 334 of file multixact_read_v18.c.

335{
336 FreeSlruRead(state->offset);
337 FreeSlruRead(state->members);
338
339 pfree(state);
340}
void pfree(void *pointer)
Definition: mcxt.c:1594
void FreeSlruRead(SlruSegState *state)
Definition: slru_io.c:153

References FreeSlruRead(), and pfree().

Referenced by rewrite_multixacts().

◆ GetOldMultiXactIdSingleMember()

bool GetOldMultiXactIdSingleMember ( OldMultiXactReader state,
MultiXactId  multi,
MultiXactMember member 
)

Definition at line 158 of file multixact_read_v18.c.

160{
161 MultiXactId nextMXact,
162 nextOffset,
163 tmpMXact;
164 int64 pageno,
165 prev_pageno;
166 int entryno,
167 length;
168 char *buf;
169 MultiXactOffset32 *offptr,
170 offset;
171 MultiXactOffset32 nextMXOffset;
173 MultiXactStatus result_status = 0;
174
175 nextMXact = state->nextMXact;
176 nextOffset = state->nextOffset;
177
178 /*
179 * Comment copied from GetMultiXactIdMembers in PostgreSQL v18
180 * multixact.c:
181 *
182 * Find out the offset at which we need to start reading MultiXactMembers
183 * and the number of members in the multixact. We determine the latter as
184 * the difference between this multixact's starting offset and the next
185 * one's. However, there are some corner cases to worry about:
186 *
187 * 1. This multixact may be the latest one created, in which case there is
188 * no next one to look at. The next multixact's offset should be set
189 * already, as we set it in RecordNewMultiXact(), but we used to not do
190 * that in older minor versions. To cope with that case, if this
191 * multixact is the latest one created, use the nextOffset value we read
192 * above as the endpoint.
193 *
194 * 2. Because GetNewMultiXactId skips over offset zero, to reserve zero
195 * for to mean "unset", there is an ambiguity near the point of offset
196 * wraparound. If we see next multixact's offset is one, is that our
197 * multixact's actual endpoint, or did it end at zero with a subsequent
198 * increment? We handle this using the knowledge that if the zero'th
199 * member slot wasn't filled, it'll contain zero, and zero isn't a valid
200 * transaction ID so it can't be a multixact member. Therefore, if we
201 * read a zero from the members array, just ignore it.
202 */
203
204 pageno = MultiXactIdToOffsetPage(multi);
205 entryno = MultiXactIdToOffsetEntry(multi);
206
207 buf = SlruReadSwitchPage(state->offset, pageno);
208 offptr = (MultiXactOffset32 *) buf;
209 offptr += entryno;
210 offset = *offptr;
211
212 if (offset == 0)
213 {
214 /* Invalid entry */
215 return false;
216 }
217
218 /*
219 * Use the same increment rule as GetNewMultiXactId(), that is, don't
220 * handle wraparound explicitly until needed.
221 */
222 tmpMXact = multi + 1;
223
224 if (nextMXact == tmpMXact)
225 {
226 /* Corner case 1: there is no next multixact */
227 nextMXOffset = nextOffset;
228 }
229 else
230 {
231 /* handle wraparound if needed */
232 if (tmpMXact < FirstMultiXactId)
233 tmpMXact = FirstMultiXactId;
234
235 prev_pageno = pageno;
236
237 pageno = MultiXactIdToOffsetPage(tmpMXact);
238 entryno = MultiXactIdToOffsetEntry(tmpMXact);
239
240 if (pageno != prev_pageno)
241 buf = SlruReadSwitchPage(state->offset, pageno);
242
243 offptr = (MultiXactOffset32 *) buf;
244 offptr += entryno;
245 nextMXOffset = *offptr;
246 }
247
248 if (nextMXOffset == 0)
249 {
250 /* Invalid entry */
251 return false;
252 }
253 length = nextMXOffset - offset;
254
255 /* read the members */
256 prev_pageno = -1;
257 for (int i = 0; i < length; i++, offset++)
258 {
259 TransactionId *xactptr;
260 uint32 *flagsptr;
261 int flagsoff;
262 int bshift;
263 int memberoff;
264 MultiXactStatus status;
265
266 pageno = MXOffsetToMemberPage(offset);
267 memberoff = MXOffsetToMemberOffset(offset);
268
269 if (pageno != prev_pageno)
270 {
271 buf = SlruReadSwitchPage(state->members, pageno);
272 prev_pageno = pageno;
273 }
274
275 xactptr = (TransactionId *) (buf + memberoff);
276 if (!TransactionIdIsValid(*xactptr))
277 {
278 /*
279 * Corner case 2: we are looking at unused slot zero
280 */
281 if (offset == 0)
282 continue;
283
284 /*
285 * Otherwise this is an invalid entry that should not be
286 * referenced from anywhere in the heap. We could return 'false'
287 * here, but we prefer to continue reading the members and
288 * converting them the best we can, to preserve evidence in case
289 * this is corruption that should not happen.
290 */
291 }
292
293 flagsoff = MXOffsetToFlagsOffset(offset);
294 bshift = MXOffsetToFlagsBitShift(offset);
295 flagsptr = (uint32 *) (buf + flagsoff);
296
297 status = (*flagsptr >> bshift) & MXACT_MEMBER_XACT_BITMASK;
298
299 /*
300 * Remember the updating XID among the members, or first locking XID
301 * if no updating XID.
302 */
303 if (ISUPDATE_from_mxstatus(status))
304 {
305 /* sanity check */
306 if (ISUPDATE_from_mxstatus(result_status))
307 {
308 /*
309 * We don't expect to see more than one updating member, even
310 * if the server had crashed.
311 */
312 pg_fatal("multixact %u has more than one updating member",
313 multi);
314 }
315 result_xid = *xactptr;
316 result_status = status;
317 }
318 else if (!TransactionIdIsValid(result_xid))
319 {
320 result_xid = *xactptr;
321 result_status = status;
322 }
323 }
324
325 member->xid = result_xid;
326 member->status = result_status;
327 return true;
328}
int64_t int64
Definition: c.h:549
TransactionId MultiXactId
Definition: c.h:681
uint32_t uint32
Definition: c.h:552
uint32 TransactionId
Definition: c.h:671
int i
Definition: isn.c:77
#define FirstMultiXactId
Definition: multixact.h:26
MultiXactStatus
Definition: multixact.h:37
#define ISUPDATE_from_mxstatus(status)
Definition: multixact.h:51
static int MXOffsetToFlagsBitShift(MultiXactOffset32 offset)
#define MXACT_MEMBER_XACT_BITMASK
static int64 MXOffsetToMemberPage(MultiXactOffset32 offset)
static int MXOffsetToMemberOffset(MultiXactOffset32 offset)
static int MultiXactIdToOffsetEntry(MultiXactId multi)
static int64 MultiXactIdToOffsetPage(MultiXactId multi)
static int MXOffsetToFlagsOffset(MultiXactOffset32 offset)
uint32 MultiXactOffset32
#define pg_fatal(...)
static char buf[DEFAULT_XLOG_SEG_SIZE]
Definition: pg_test_fsync.c:71
static char * SlruReadSwitchPage(SlruSegState *state, uint64 pageno)
Definition: slru_io.h:33
TransactionId xid
Definition: multixact.h:57
MultiXactStatus status
Definition: multixact.h:58
#define InvalidTransactionId
Definition: transam.h:31
#define TransactionIdIsValid(xid)
Definition: transam.h:41

References buf, FirstMultiXactId, i, InvalidTransactionId, ISUPDATE_from_mxstatus, MultiXactIdToOffsetEntry(), MultiXactIdToOffsetPage(), MXACT_MEMBER_XACT_BITMASK, MXOffsetToFlagsBitShift(), MXOffsetToFlagsOffset(), MXOffsetToMemberOffset(), MXOffsetToMemberPage(), pg_fatal, SlruReadSwitchPage(), MultiXactMember::status, TransactionIdIsValid, and MultiXactMember::xid.

Referenced by rewrite_multixacts().

◆ MultiXactIdToOffsetEntry()

static int MultiXactIdToOffsetEntry ( MultiXactId  multi)
inlinestatic

◆ MultiXactIdToOffsetPage()

◆ MXOffsetToFlagsBitShift()

static int MXOffsetToFlagsBitShift ( MultiXactOffset32  offset)
inlinestatic

Definition at line 105 of file multixact_read_v18.c.

106{
107 int member_in_group = offset % MULTIXACT_MEMBERS_PER_MEMBERGROUP;
108 int bshift = member_in_group * MXACT_MEMBER_BITS_PER_XACT;
109
110 return bshift;
111}
#define MXACT_MEMBER_BITS_PER_XACT
#define MULTIXACT_MEMBERS_PER_MEMBERGROUP

References MULTIXACT_MEMBERS_PER_MEMBERGROUP, and MXACT_MEMBER_BITS_PER_XACT.

Referenced by ExtendMultiXactMember(), GetMultiXactIdMembers(), GetOldMultiXactIdSingleMember(), RecordMultiXactMembers(), and RecordNewMultiXact().

◆ MXOffsetToFlagsOffset()

static int MXOffsetToFlagsOffset ( MultiXactOffset32  offset)
inlinestatic

◆ MXOffsetToMemberOffset()

static int MXOffsetToMemberOffset ( MultiXactOffset32  offset)
inlinestatic

◆ MXOffsetToMemberPage()