PostgreSQL Source Code  git master
xid_wraparound.c File Reference
#include "postgres.h"
#include "access/xact.h"
#include "miscadmin.h"
#include "storage/proc.h"
#include "utils/xid8.h"
Include dependency graph for xid_wraparound.c:

Go to the source code of this file.

Macros

#define REPORT_INTERVAL   (10 * 1000000)
 
#define COMMIT_TS_XACTS_PER_PAGE   (BLCKSZ / 10)
 
#define SUBTRANS_XACTS_PER_PAGE   (BLCKSZ / sizeof(TransactionId))
 
#define CLOG_XACTS_PER_BYTE   4
 
#define CLOG_XACTS_PER_PAGE   (BLCKSZ * CLOG_XACTS_PER_BYTE)
 

Functions

static int64 consume_xids_shortcut (void)
 
static FullTransactionId consume_xids_common (FullTransactionId untilxid, uint64 nxids)
 
 PG_FUNCTION_INFO_V1 (consume_xids)
 
Datum consume_xids (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (consume_xids_until)
 
Datum consume_xids_until (PG_FUNCTION_ARGS)
 
static uint32 XidSkip (FullTransactionId fullxid)
 

Variables

 PG_MODULE_MAGIC
 

Macro Definition Documentation

◆ CLOG_XACTS_PER_BYTE

#define CLOG_XACTS_PER_BYTE   4

Definition at line 161 of file xid_wraparound.c.

◆ CLOG_XACTS_PER_PAGE

#define CLOG_XACTS_PER_PAGE   (BLCKSZ * CLOG_XACTS_PER_BYTE)

Definition at line 162 of file xid_wraparound.c.

◆ COMMIT_TS_XACTS_PER_PAGE

#define COMMIT_TS_XACTS_PER_PAGE   (BLCKSZ / 10)

Definition at line 159 of file xid_wraparound.c.

◆ REPORT_INTERVAL

#define REPORT_INTERVAL   (10 * 1000000)

◆ SUBTRANS_XACTS_PER_PAGE

#define SUBTRANS_XACTS_PER_PAGE   (BLCKSZ / sizeof(TransactionId))

Definition at line 160 of file xid_wraparound.c.

Function Documentation

◆ consume_xids()

Datum consume_xids ( PG_FUNCTION_ARGS  )

Definition at line 32 of file xid_wraparound.c.

33 {
34  int64 nxids = PG_GETARG_INT64(0);
35  FullTransactionId lastxid;
36 
37  if (nxids < 0)
38  elog(ERROR, "invalid nxids argument: %lld", (long long) nxids);
39 
40  if (nxids == 0)
41  lastxid = ReadNextFullTransactionId();
42  else
43  lastxid = consume_xids_common(InvalidFullTransactionId, (uint64) nxids);
44 
46 }
#define ERROR
Definition: elog.h:39
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define InvalidFullTransactionId
Definition: transam.h:56
FullTransactionId ReadNextFullTransactionId(void)
Definition: varsup.c:288
#define PG_RETURN_FULLTRANSACTIONID(X)
Definition: xid8.h:30
static FullTransactionId consume_xids_common(FullTransactionId untilxid, uint64 nxids)

References consume_xids_common(), elog(), ERROR, InvalidFullTransactionId, PG_GETARG_INT64, PG_RETURN_FULLTRANSACTIONID, and ReadNextFullTransactionId().

◆ consume_xids_common()

static FullTransactionId consume_xids_common ( FullTransactionId  untilxid,
uint64  nxids 
)
static

Definition at line 71 of file xid_wraparound.c.

72 {
73  FullTransactionId lastxid;
74  uint64 last_reported_at = 0;
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 */
81  lastxid = ReadNextFullTransactionId();
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  */
92  (void) GetTopTransactionId();
93 
94  for (;;)
95  {
96  uint64 xids_left;
97 
99 
100  /* How many XIDs do we have left to consume? */
101  if (nxids > 0)
102  {
103  if (consumed >= nxids)
104  break;
105  xids_left = nxids - consumed;
106  }
107  else
108  {
109  if (FullTransactionIdFollowsOrEquals(lastxid, untilxid))
110  break;
111  xids_left = U64FromFullTransactionId(untilxid) - U64FromFullTransactionId(lastxid);
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 &&
119  consumed - last_reported_at < REPORT_INTERVAL &&
121  {
122  int64 consumed_by_shortcut = consume_xids_shortcut();
123 
124  if (consumed_by_shortcut > 0)
125  {
126  consumed += consumed_by_shortcut;
127  continue;
128  }
129  }
130 
131  /* Slow path: Call GetNewTransactionId to allocate a new XID. */
132  lastxid = GetNewTransactionId(true);
133  consumed++;
134 
135  /* Report progress */
136  if (consumed - last_reported_at >= REPORT_INTERVAL)
137  {
138  if (nxids > 0)
139  elog(NOTICE, "consumed %llu / %llu XIDs, latest %u:%u",
140  (unsigned long long) consumed, (unsigned long long) nxids,
142  XidFromFullTransactionId(lastxid));
143  else
144  elog(NOTICE, "consumed up to %u:%u / %u:%u",
146  XidFromFullTransactionId(lastxid),
147  EpochFromFullTransactionId(untilxid),
148  XidFromFullTransactionId(untilxid));
149  last_reported_at = consumed;
150  }
151  }
152 
153  return lastxid;
154 }
#define NOTICE
Definition: elog.h:35
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
PGPROC * MyProc
Definition: proc.c:68
XidCacheStatus subxidStatus
Definition: proc.h:249
bool overflowed
Definition: proc.h:45
#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
FullTransactionId GetNewTransactionId(bool isSubXact)
Definition: varsup.c:77
TransactionId GetTopTransactionId(void)
Definition: xact.c:417
#define REPORT_INTERVAL
static int64 consume_xids_shortcut(void)

References CHECK_FOR_INTERRUPTS, consume_xids_shortcut(), elog(), EpochFromFullTransactionId, FullTransactionIdFollowsOrEquals, GetNewTransactionId(), GetTopTransactionId(), MyProc, NOTICE, XidCacheStatus::overflowed, ReadNextFullTransactionId(), REPORT_INTERVAL, PGPROC::subxidStatus, U64FromFullTransactionId, and XidFromFullTransactionId.

Referenced by consume_xids(), and consume_xids_until().

◆ consume_xids_shortcut()

static int64 consume_xids_shortcut ( void  )
static

Definition at line 200 of file xid_wraparound.c.

201 {
202  FullTransactionId nextXid;
203  uint32 consumed;
204 
205  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
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)
214  TransamVariables->nextXid.value += (uint64) consumed;
215 
216  LWLockRelease(XidGenLock);
217 
218  return consumed;
219 }
unsigned int uint32
Definition: c.h:495
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_EXCLUSIVE
Definition: lwlock.h:116
uint64 value
Definition: transam.h:67
FullTransactionId nextXid
Definition: transam.h:220
TransamVariablesData * TransamVariables
Definition: varsup.c:34
static uint32 XidSkip(FullTransactionId fullxid)

References LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), TransamVariablesData::nextXid, TransamVariables, FullTransactionId::value, and XidSkip().

Referenced by consume_xids_common().

◆ consume_xids_until()

Datum consume_xids_until ( PG_FUNCTION_ARGS  )

Definition at line 53 of file xid_wraparound.c.

54 {
56  FullTransactionId lastxid;
57 
58  if (!FullTransactionIdIsNormal(targetxid))
59  elog(ERROR, "targetxid %llu is not normal",
60  (unsigned long long) U64FromFullTransactionId(targetxid));
61 
62  lastxid = consume_xids_common(targetxid, 0);
63 
65 }
#define FullTransactionIdIsNormal(x)
Definition: transam.h:58
#define PG_GETARG_FULLTRANSACTIONID(X)
Definition: xid8.h:29

References consume_xids_common(), elog(), ERROR, FullTransactionIdIsNormal, PG_GETARG_FULLTRANSACTIONID, PG_RETURN_FULLTRANSACTIONID, and U64FromFullTransactionId.

◆ PG_FUNCTION_INFO_V1() [1/2]

PG_FUNCTION_INFO_V1 ( consume_xids  )

◆ PG_FUNCTION_INFO_V1() [2/2]

PG_FUNCTION_INFO_V1 ( consume_xids_until  )

◆ XidSkip()

static uint32 XidSkip ( FullTransactionId  fullxid)
inlinestatic

Definition at line 171 of file xid_wraparound.c.

172 {
173  uint32 low = XidFromFullTransactionId(fullxid);
174  uint32 rem;
175  uint32 distance;
176 
177  if (low < 5 || low >= UINT32_MAX - 5)
178  return 0;
179  distance = UINT32_MAX - 5 - low;
180 
181  rem = low % COMMIT_TS_XACTS_PER_PAGE;
182  if (rem == 0)
183  return 0;
184  distance = Min(distance, COMMIT_TS_XACTS_PER_PAGE - rem);
185 
186  rem = low % SUBTRANS_XACTS_PER_PAGE;
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 }
#define Min(x, y)
Definition: c.h:993
#define CLOG_XACTS_PER_PAGE
#define COMMIT_TS_XACTS_PER_PAGE
#define SUBTRANS_XACTS_PER_PAGE

References CLOG_XACTS_PER_PAGE, COMMIT_TS_XACTS_PER_PAGE, Min, SUBTRANS_XACTS_PER_PAGE, and XidFromFullTransactionId.

Referenced by consume_xids_shortcut().

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 22 of file xid_wraparound.c.