PostgreSQL Source Code git master
Loading...
Searching...
No Matches
multixact_rewrite.c
Go to the documentation of this file.
1/*
2 * multixact_rewrite.c
3 *
4 * Functions to convert multixact SLRUs from the pre-v19 format to the current
5 * format with 64-bit MultiXactOffsets.
6 *
7 * Copyright (c) 2025-2026, PostgreSQL Global Development Group
8 * src/bin/pg_upgrade/multixact_rewrite.c
9 */
10
11#include "postgres_fe.h"
12
14#include "multixact_read_v18.h"
15#include "pg_upgrade.h"
16
18 MultiXactOffset offset);
20 MultiXactOffset offset,
21 int nmembers, MultiXactMember *members);
22
23/*
24 * Convert pg_multixact/offset and /members from the old pre-v19 format with
25 * 32-bit offsets to the current format.
26 *
27 * Multixids in the range [from_multi, to_multi) are read from the old
28 * cluster, and written in the new format.
29 *
30 * Returns the new nextOffset value; the caller should set it in the new
31 * control file. The new members always start from offset 1, regardless of
32 * the offset range used in the old cluster.
33 */
36{
37 MultiXactOffset next_offset;
40 char dir[MAXPGPATH] = {0};
41 bool prev_multixid_valid = false;
43
44 /*
45 * The range of valid multi XIDs is unchanged by the conversion (they are
46 * referenced from the heap tables), but the members SLRU is rewritten to
47 * start from offset 1.
48 */
49 next_offset = 1;
50
51 /* Prepare to write the new SLRU files */
52 pg_sprintf(dir, "%s/pg_multixact/offsets", new_cluster.pgdata);
53 offsets_writer = AllocSlruWrite(dir, false);
55
56 pg_sprintf(dir, "%s/pg_multixact/members", new_cluster.pgdata);
57 members_writer = AllocSlruWrite(dir, true /* use long segment names */ );
59
60 /*
61 * Convert old multixids, if needed, by reading them one-by-one from the
62 * old cluster.
63 */
67
68 for (MultiXactId multi = from_multi; multi != to_multi;)
69 {
70 MultiXactMember member;
71 bool multixid_valid;
72
73 /*
74 * Read this multixid's members.
75 *
76 * Locking-only XIDs that may be part of multi-xids don't matter after
77 * upgrade, as there can be no transactions running across upgrade. So
78 * as a small optimization, we only read one member from each
79 * multixid: the one updating one, or if there was no update,
80 * arbitrarily the first locking xid.
81 */
83
84 /*
85 * Write the new offset to pg_multixact/offsets.
86 *
87 * Even if this multixid is invalid, we still need to write its offset
88 * if the *previous* multixid was valid. That's because when reading
89 * a multixid, the number of members is calculated from the difference
90 * between the two offsets.
91 */
93 (multixid_valid || prev_multixid_valid) ? next_offset : 0);
94
95 /* Write the members */
97 {
98 RecordMultiXactMembers(members_writer, next_offset, 1, &member);
99 next_offset += 1;
100 }
101
102 /* Advance to next multixid, handling wraparound */
103 multi++;
104 if (multi < FirstMultiXactId)
105 multi = FirstMultiXactId;
107 }
108
110
111 /* Write the final 'next' offset to the last SLRU page */
113 prev_multixid_valid ? next_offset : 0);
114
115 /* Flush the last SLRU pages */
118
119 return next_offset;
120}
121
122
123/*
124 * Write one offset to the offset SLRU
125 */
126static void
128 MultiXactOffset offset)
129{
130 int64 pageno;
131 int entryno;
132 char *buf;
134
135 pageno = MultiXactIdToOffsetPage(multi);
137
140 offptr[entryno] = offset;
141}
142
143/*
144 * Write the members for one multixid in the members SLRU
145 *
146 * (Currently, this is only ever called with nmembers == 1)
147 */
148static void
150 MultiXactOffset offset,
151 int nmembers, MultiXactMember *members)
152{
153 for (int i = 0; i < nmembers; i++, offset++)
154 {
155 int64 pageno;
156 char *buf;
160 int bshift;
161 int flagsoff;
162 int memberoff;
163
164 Assert(members[i].status <= MultiXactStatusUpdate);
165
166 pageno = MXOffsetToMemberPage(offset);
170
172
174
175 *memberptr = members[i].xid;
176
177 flagsptr = (uint32 *) (buf + flagsoff);
178
180 flagsval &= ~(((1 << MXACT_MEMBER_BITS_PER_XACT) - 1) << bshift);
181 flagsval |= (members[i].status << bshift);
183 }
184}
#define Assert(condition)
Definition c.h:1002
int64_t int64
Definition c.h:680
TransactionId MultiXactId
Definition c.h:805
uint64 MultiXactOffset
Definition c.h:807
uint32_t uint32
Definition c.h:683
uint32 TransactionId
Definition c.h:795
int i
Definition isn.c:77
#define FirstMultiXactId
Definition multixact.h:26
@ MultiXactStatusUpdate
Definition multixact.h:45
#define MXACT_MEMBER_BITS_PER_XACT
static int MXOffsetToFlagsBitShift(MultiXactOffset32 offset)
static int64 MXOffsetToMemberPage(MultiXactOffset32 offset)
bool GetOldMultiXactIdSingleMember(OldMultiXactReader *state, MultiXactId multi, MultiXactMember *member)
static int MXOffsetToMemberOffset(MultiXactOffset32 offset)
static int MultiXactIdToOffsetEntry(MultiXactId multi)
static int64 MultiXactIdToOffsetPage(MultiXactId multi)
OldMultiXactReader * AllocOldMultiXactRead(char *pgdata, MultiXactId nextMulti, MultiXactOffset32 nextOffset)
void FreeOldMultiXactReader(OldMultiXactReader *state)
static int MXOffsetToFlagsOffset(MultiXactOffset32 offset)
static void RecordMultiXactOffset(SlruSegState *offsets_writer, MultiXactId multi, MultiXactOffset offset)
static void RecordMultiXactMembers(SlruSegState *members_writer, MultiXactOffset offset, int nmembers, MultiXactMember *members)
MultiXactOffset rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi)
#define MAXPGPATH
static char buf[DEFAULT_XLOG_SEG_SIZE]
ClusterInfo new_cluster
Definition pg_upgrade.c:74
ClusterInfo old_cluster
Definition pg_upgrade.c:73
int int int int pg_sprintf(char *str, const char *fmt,...) pg_attribute_printf(2
static int fb(int x)
void FreeSlruWrite(SlruSegState *state)
Definition slru_io.c:260
SlruSegState * AllocSlruWrite(const char *dir, bool long_segment_names)
Definition slru_io.c:166
static char * SlruWriteSwitchPage(SlruSegState *state, uint64 pageno)
Definition slru_io.h:45
char * pgdata
Definition pg_upgrade.h:275
ControlData controldata
Definition pg_upgrade.h:272
uint32 chkpnt_nxtmulti
Definition pg_upgrade.h:220
uint64 chkpnt_nxtmxoff
Definition pg_upgrade.h:221
TransactionId xid
Definition multixact.h:57
MultiXactStatus status
Definition multixact.h:58