PostgreSQL Source Code git master
multixact_read_v18.h File Reference
#include "access/multixact.h"
#include "slru_io.h"
Include dependency graph for multixact_read_v18.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  OldMultiXactReader
 

Typedefs

typedef uint32 MultiXactOffset32
 
typedef struct OldMultiXactReader OldMultiXactReader
 

Functions

OldMultiXactReaderAllocOldMultiXactRead (char *pgdata, MultiXactId nextMulti, MultiXactOffset32 nextOffset)
 
bool GetOldMultiXactIdSingleMember (OldMultiXactReader *state, MultiXactId multi, MultiXactMember *member)
 
void FreeOldMultiXactReader (OldMultiXactReader *reader)
 

Typedef Documentation

◆ MultiXactOffset32

Definition at line 18 of file multixact_read_v18.h.

◆ OldMultiXactReader

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 reader)

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().