1/*--------------------------------------------------------------------------
4 * Utilities for testing XID wraparound
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/test/modules/xid_wraparound/xid_wraparound.c
13 * -------------------------------------------------------------------------
28 * Consume the specified number of XIDs.
38 elog(
ERROR,
"invalid nxids argument: %" PRId64, nxids);
49 * Consume XIDs, up to the given XID.
59 elog(
ERROR,
"targetxid %" PRIu64
" is not normal",
68 * Common functionality between the two public functions.
74 uint64 last_reported_at = 0;
77 /* Print a NOTICE every REPORT_INTERVAL xids */
78#define REPORT_INTERVAL (10 * 1000000)
80 /* initialize 'lastxid' with the system's current next XID */
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.
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
100 /* How many XIDs do we have left to consume? */
103 if (consumed >= nxids)
105 xids_left = nxids - consumed;
115 * If we still have plenty of XIDs to consume, try to take a shortcut
116 * and bump up the nextXid counter directly.
118 if (xids_left > 2000 &&
124 if (consumed_by_shortcut > 0)
126 consumed += consumed_by_shortcut;
131 /* Slow path: Call GetNewTransactionId to allocate a new XID. */
135 /* Report progress */
139 elog(
NOTICE,
"consumed %" PRIu64
" / %" PRIu64
" XIDs, latest %u:%u",
149 last_reported_at = consumed;
157 * These constants copied from .c files, because they're private.
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)
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.
177 if (low < 5 || low >= UINT32_MAX - 5)
179 distance = UINT32_MAX - 5 - low;
209 * Go slow near the "interesting values". The interesting zones include 5
210 * transactions before and after SLRU page switches.
#define PG_GETARG_INT64(n)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
#define CHECK_FOR_INTERRUPTS()
XidCacheStatus subxidStatus
FullTransactionId nextXid
#define FullTransactionIdIsNormal(x)
#define EpochFromFullTransactionId(x)
#define U64FromFullTransactionId(x)
#define FullTransactionIdFollowsOrEquals(a, b)
#define XidFromFullTransactionId(x)
#define InvalidFullTransactionId
FullTransactionId ReadNextFullTransactionId(void)
FullTransactionId GetNewTransactionId(bool isSubXact)
TransamVariablesData * TransamVariables
TransactionId GetTopTransactionId(void)
#define PG_GETARG_FULLTRANSACTIONID(X)
#define PG_RETURN_FULLTRANSACTIONID(X)
PG_FUNCTION_INFO_V1(consume_xids)
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)
static FullTransactionId consume_xids_common(FullTransactionId untilxid, uint64 nxids)
Datum consume_xids(PG_FUNCTION_ARGS)
static int64 consume_xids_shortcut(void)