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}
#define pg_malloc_object(type)
Definition: fe_memutils.h:50
#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_object, and pg_sprintf().

Referenced by rewrite_multixacts().

◆ FreeOldMultiXactReader()

void FreeOldMultiXactReader ( OldMultiXactReader state)

Definition at line 357 of file multixact_read_v18.c.

358{
359 FreeSlruRead(state->offset);
360 FreeSlruRead(state->members);
361
362 pfree(state);
363}
void pfree(void *pointer)
Definition: mcxt.c:1616
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 161 of file multixact_read_v18.c.

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