PostgreSQL Source Code git master
Loading...
Searching...
No Matches
xid_wraparound.c
Go to the documentation of this file.
1/*--------------------------------------------------------------------------
2 *
3 * xid_wraparound.c
4 * Utilities for testing XID wraparound
5 *
6 *
7 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 * IDENTIFICATION
11 * src/test/modules/xid_wraparound/xid_wraparound.c
12 *
13 * -------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include "access/xact.h"
18#include "miscadmin.h"
19#include "storage/proc.h"
20#include "utils/xid8.h"
21
23
24static int64 consume_xids_shortcut(void);
26
27/*
28 * Consume the specified number of XIDs.
29 */
47
48/*
49 * Consume XIDs, up to the given XID.
50 */
66
67/*
68 * Common functionality between the two public functions.
69 */
72{
75 uint64 consumed = 0;
76
77 /* Print a NOTICE every REPORT_INTERVAL xids */
78#define REPORT_INTERVAL (10 * 1000000)
79
80 /* initialize 'lastxid' with the system's current next XID */
82
83 /*
84 * We consume XIDs by calling GetNewTransactionId(true), which marks the
85 * consumed XIDs as subtransactions of the current top-level transaction.
86 * For that to work, this transaction must have a top-level XID.
87 *
88 * GetNewTransactionId registers them in the subxid cache in PGPROC, until
89 * the cache overflows, but beyond that, we don't keep track of the
90 * consumed XIDs.
91 */
93
94 for (;;)
95 {
97
99
100 /* How many XIDs do we have left to consume? */
101 if (nxids > 0)
102 {
103 if (consumed >= nxids)
104 break;
106 }
107 else
108 {
110 break;
112 }
113
114 /*
115 * If we still have plenty of XIDs to consume, try to take a shortcut
116 * and bump up the nextXid counter directly.
117 */
118 if (xids_left > 2000 &&
121 {
123
124 if (consumed_by_shortcut > 0)
125 {
127 continue;
128 }
129 }
130
131 /* Slow path: Call GetNewTransactionId to allocate a new XID. */
133 consumed++;
134
135 /* Report progress */
137 {
138 if (nxids > 0)
139 elog(NOTICE, "consumed %" PRIu64 " / %" PRIu64 " XIDs, latest %u:%u",
143 else
144 elog(NOTICE, "consumed up to %u:%u / %u:%u",
150 }
151 }
152
153 return lastxid;
154}
155
156/*
157 * These constants copied from .c files, because they're private.
158 */
159#define COMMIT_TS_XACTS_PER_PAGE (BLCKSZ / 10)
160#define SUBTRANS_XACTS_PER_PAGE (BLCKSZ / sizeof(TransactionId))
161#define CLOG_XACTS_PER_BYTE 4
162#define CLOG_XACTS_PER_PAGE (BLCKSZ * CLOG_XACTS_PER_BYTE)
163
164/*
165 * All the interesting action in GetNewTransactionId happens when we extend
166 * the SLRUs, or at the uint32 wraparound. If the nextXid counter is not close
167 * to any of those interesting values, take a shortcut and bump nextXID
168 * directly, close to the next "interesting" value.
169 */
170static inline uint32
172{
174 uint32 rem;
175 uint32 distance;
176
178 return 0;
179 distance = UINT32_MAX - 5 - low;
180
182 if (rem == 0)
183 return 0;
184 distance = Min(distance, COMMIT_TS_XACTS_PER_PAGE - rem);
185
187 if (rem == 0)
188 return 0;
189 distance = Min(distance, SUBTRANS_XACTS_PER_PAGE - rem);
190
191 rem = low % CLOG_XACTS_PER_PAGE;
192 if (rem == 0)
193 return 0;
194 distance = Min(distance, CLOG_XACTS_PER_PAGE - rem);
195
196 return distance;
197}
198
199static int64
201{
202 FullTransactionId nextXid;
204
206 nextXid = TransamVariables->nextXid;
207
208 /*
209 * Go slow near the "interesting values". The interesting zones include 5
210 * transactions before and after SLRU page switches.
211 */
212 consumed = XidSkip(nextXid);
213 if (consumed > 0)
215
217
218 return consumed;
219}
#define Min(x, y)
Definition c.h:997
int64_t int64
Definition c.h:543
uint64_t uint64
Definition c.h:547
uint32_t uint32
Definition c.h:546
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define NOTICE
Definition elog.h:35
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_FUNCTION_INFO_V1(funcname)
Definition fmgr.h:417
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
@ LW_EXCLUSIVE
Definition lwlock.h:112
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
PGPROC * MyProc
Definition proc.c:67
XidCacheStatus subxidStatus
Definition proc.h:286
FullTransactionId nextXid
Definition transam.h:220
bool overflowed
Definition proc.h:46
#define FullTransactionIdIsNormal(x)
Definition transam.h:58
#define EpochFromFullTransactionId(x)
Definition transam.h:47
#define U64FromFullTransactionId(x)
Definition transam.h:49
#define FullTransactionIdFollowsOrEquals(a, b)
Definition transam.h:54
#define XidFromFullTransactionId(x)
Definition transam.h:48
#define InvalidFullTransactionId
Definition transam.h:56
FullTransactionId ReadNextFullTransactionId(void)
Definition varsup.c:288
FullTransactionId GetNewTransactionId(bool isSubXact)
Definition varsup.c:77
TransamVariablesData * TransamVariables
Definition varsup.c:34
TransactionId GetTopTransactionId(void)
Definition xact.c:427
#define PG_GETARG_FULLTRANSACTIONID(X)
Definition xid8.h:29
#define PG_RETURN_FULLTRANSACTIONID(X)
Definition xid8.h:30
static uint32 XidSkip(FullTransactionId fullxid)
#define CLOG_XACTS_PER_PAGE
#define COMMIT_TS_XACTS_PER_PAGE
#define SUBTRANS_XACTS_PER_PAGE
Datum consume_xids_until(PG_FUNCTION_ARGS)
PG_MODULE_MAGIC
static FullTransactionId consume_xids_common(FullTransactionId untilxid, uint64 nxids)
Datum consume_xids(PG_FUNCTION_ARGS)
#define REPORT_INTERVAL
static int64 consume_xids_shortcut(void)