PostgreSQL Source Code  git master
txid.c File Reference
#include "postgres.h"
#include "access/clog.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "libpq/pqformat.h"
#include "postmaster/postmaster.h"
#include "storage/lwlock.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
Include dependency graph for txid.c:

Go to the source code of this file.

Data Structures

struct  TxidSnapshot
 
struct  TxidEpoch
 

Macros

#define MAX_TXID   ((uint64) PG_INT64_MAX)
 
#define TXID_FMT   UINT64_FORMAT
 
#define USE_BSEARCH_IF_NXIP_GREATER   30
 
#define TXID_SNAPSHOT_SIZE(nxip)   (offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip))
 
#define TXID_SNAPSHOT_MAX_NXIP   ((MaxAllocSize - offsetof(TxidSnapshot, xip)) / sizeof(txid))
 

Typedefs

typedef uint64 txid
 

Functions

static void load_xid_epoch (TxidEpoch *state)
 
static bool TransactionIdInRecentPast (uint64 xid_with_epoch, TransactionId *extracted_xid)
 
static txid convert_xid (TransactionId xid, const TxidEpoch *state)
 
static int cmp_txid (const void *aa, const void *bb)
 
static void sort_snapshot (TxidSnapshot *snap)
 
static bool is_visible_txid (txid value, const TxidSnapshot *snap)
 
static StringInfo buf_init (txid xmin, txid xmax)
 
static void buf_add_txid (StringInfo buf, txid xid)
 
static TxidSnapshotbuf_finalize (StringInfo buf)
 
static txid str2txid (const char *s, const char **endp)
 
static TxidSnapshotparse_snapshot (const char *str)
 
Datum txid_current (PG_FUNCTION_ARGS)
 
Datum txid_current_if_assigned (PG_FUNCTION_ARGS)
 
Datum txid_current_snapshot (PG_FUNCTION_ARGS)
 
Datum txid_snapshot_in (PG_FUNCTION_ARGS)
 
Datum txid_snapshot_out (PG_FUNCTION_ARGS)
 
Datum txid_snapshot_recv (PG_FUNCTION_ARGS)
 
Datum txid_snapshot_send (PG_FUNCTION_ARGS)
 
Datum txid_visible_in_snapshot (PG_FUNCTION_ARGS)
 
Datum txid_snapshot_xmin (PG_FUNCTION_ARGS)
 
Datum txid_snapshot_xmax (PG_FUNCTION_ARGS)
 
Datum txid_snapshot_xip (PG_FUNCTION_ARGS)
 
Datum txid_status (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ MAX_TXID

#define MAX_TXID   ((uint64) PG_INT64_MAX)

Definition at line 39 of file txid.c.

Referenced by str2txid(), and txid_snapshot_recv().

◆ TXID_FMT

#define TXID_FMT   UINT64_FORMAT

Definition at line 45 of file txid.c.

Referenced by txid_snapshot_out().

◆ TXID_SNAPSHOT_MAX_NXIP

#define TXID_SNAPSHOT_MAX_NXIP   ((MaxAllocSize - offsetof(TxidSnapshot, xip)) / sizeof(txid))

Definition at line 75 of file txid.c.

Referenced by txid_current_snapshot(), and txid_snapshot_recv().

◆ TXID_SNAPSHOT_SIZE

#define TXID_SNAPSHOT_SIZE (   nxip)    (offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip))

Definition at line 73 of file txid.c.

Referenced by buf_init(), txid_current_snapshot(), and txid_snapshot_recv().

◆ USE_BSEARCH_IF_NXIP_GREATER

#define USE_BSEARCH_IF_NXIP_GREATER   30

Definition at line 51 of file txid.c.

Referenced by is_visible_txid().

Typedef Documentation

◆ txid

typedef uint64 txid

Definition at line 42 of file txid.c.

Function Documentation

◆ buf_add_txid()

static void buf_add_txid ( StringInfo  buf,
txid  xid 
)
static

Definition at line 292 of file txid.c.

References appendBinaryStringInfo(), StringInfoData::data, and TxidSnapshot::nxip.

Referenced by parse_snapshot().

293 {
294  TxidSnapshot *snap = (TxidSnapshot *) buf->data;
295 
296  /* do this before possible realloc */
297  snap->nxip++;
298 
299  appendBinaryStringInfo(buf, (char *) &xid, sizeof(xid));
300 }
uint32 nxip
Definition: txid.c:66
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:214

◆ buf_finalize()

static TxidSnapshot* buf_finalize ( StringInfo  buf)
static

Definition at line 303 of file txid.c.

References StringInfoData::data, StringInfoData::len, pfree(), and SET_VARSIZE.

Referenced by parse_snapshot().

304 {
305  TxidSnapshot *snap = (TxidSnapshot *) buf->data;
306 
307  SET_VARSIZE(snap, buf->len);
308 
309  /* buf is not needed anymore */
310  buf->data = NULL;
311  pfree(buf);
312 
313  return snap;
314 }
void pfree(void *pointer)
Definition: mcxt.c:1056
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329

◆ buf_init()

static StringInfo buf_init ( txid  xmin,
txid  xmax 
)
static

Definition at line 277 of file txid.c.

References appendBinaryStringInfo(), buf, makeStringInfo(), TxidSnapshot::nxip, TXID_SNAPSHOT_SIZE, TxidSnapshot::xmax, and TxidSnapshot::xmin.

Referenced by parse_snapshot().

278 {
279  TxidSnapshot snap;
280  StringInfo buf;
281 
282  snap.xmin = xmin;
283  snap.xmax = xmax;
284  snap.nxip = 0;
285 
286  buf = makeStringInfo();
287  appendBinaryStringInfo(buf, (char *) &snap, TXID_SNAPSHOT_SIZE(0));
288  return buf;
289 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
txid xmin
Definition: txid.c:67
static char * buf
Definition: pg_test_fsync.c:68
#define TXID_SNAPSHOT_SIZE(nxip)
Definition: txid.c:73
uint32 nxip
Definition: txid.c:66
txid xmax
Definition: txid.c:68
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:214

◆ cmp_txid()

static int cmp_txid ( const void *  aa,
const void *  bb 
)
static

Definition at line 194 of file txid.c.

Referenced by is_visible_txid(), and sort_snapshot().

195 {
196  txid a = *(const txid *) aa;
197  txid b = *(const txid *) bb;
198 
199  if (a < b)
200  return -1;
201  if (a > b)
202  return 1;
203  return 0;
204 }
uint64 txid
Definition: txid.c:42

◆ convert_xid()

static txid convert_xid ( TransactionId  xid,
const TxidEpoch state 
)
static

Definition at line 170 of file txid.c.

References epoch, TxidEpoch::epoch, TxidEpoch::last_xid, TransactionIdFollows(), TransactionIdIsNormal, and TransactionIdPrecedes().

Referenced by txid_current(), txid_current_if_assigned(), and txid_current_snapshot().

171 {
172  uint64 epoch;
173 
174  /* return special xid's as-is */
175  if (!TransactionIdIsNormal(xid))
176  return (txid) xid;
177 
178  /* xid can be on either side when near wrap-around */
179  epoch = (uint64) state->epoch;
180  if (xid > state->last_xid &&
181  TransactionIdPrecedes(xid, state->last_xid))
182  epoch--;
183  else if (xid < state->last_xid &&
184  TransactionIdFollows(xid, state->last_xid))
185  epoch++;
186 
187  return (epoch << 32) | xid;
188 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
TransactionId last_xid
Definition: txid.c:83
uint64 txid
Definition: txid.c:42
uint32 epoch
Definition: txid.c:84
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static const unsigned __int64 epoch
Definition: gettimeofday.c:34
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ is_visible_txid()

static bool is_visible_txid ( txid  value,
const TxidSnapshot snap 
)
static

Definition at line 243 of file txid.c.

References cmp_txid(), false, i, TxidSnapshot::nxip, USE_BSEARCH_IF_NXIP_GREATER, TxidSnapshot::xip, and TxidSnapshot::xmax.

Referenced by txid_visible_in_snapshot().

244 {
245  if (value < snap->xmin)
246  return true;
247  else if (value >= snap->xmax)
248  return false;
249 #ifdef USE_BSEARCH_IF_NXIP_GREATER
250  else if (snap->nxip > USE_BSEARCH_IF_NXIP_GREATER)
251  {
252  void *res;
253 
254  res = bsearch(&value, snap->xip, snap->nxip, sizeof(txid), cmp_txid);
255  /* if found, transaction is still in progress */
256  return (res) ? false : true;
257  }
258 #endif
259  else
260  {
261  uint32 i;
262 
263  for (i = 0; i < snap->nxip; i++)
264  {
265  if (value == snap->xip[i])
266  return false;
267  }
268  return true;
269  }
270 }
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
#define USE_BSEARCH_IF_NXIP_GREATER
Definition: txid.c:51
static struct @145 value
#define false
Definition: c.h:316
uint64 txid
Definition: txid.c:42
static int cmp_txid(const void *aa, const void *bb)
Definition: txid.c:194
unsigned int uint32
Definition: c.h:358
int i
uint32 nxip
Definition: txid.c:66
txid xmax
Definition: txid.c:68

◆ load_xid_epoch()

static void load_xid_epoch ( TxidEpoch state)
static

Definition at line 92 of file txid.c.

References TxidEpoch::epoch, EpochFromFullTransactionId, TxidEpoch::last_xid, ReadNextFullTransactionId(), and XidFromFullTransactionId.

Referenced by txid_current(), txid_current_if_assigned(), and txid_current_snapshot().

93 {
95 
96  state->last_xid = XidFromFullTransactionId(fullXid);
97  state->epoch = EpochFromFullTransactionId(fullXid);
98 }
TransactionId last_xid
Definition: txid.c:83
#define XidFromFullTransactionId(x)
Definition: transam.h:48
uint32 epoch
Definition: txid.c:84
FullTransactionId ReadNextFullTransactionId(void)
Definition: varsup.c:246
#define EpochFromFullTransactionId(x)
Definition: transam.h:47

◆ parse_snapshot()

static TxidSnapshot* parse_snapshot ( const char *  str)
static

Definition at line 356 of file txid.c.

References buf, buf_add_txid(), buf_finalize(), buf_init(), ereport, errcode(), errmsg(), ERROR, generate_unaccent_rules::str, str2txid(), and val.

Referenced by txid_snapshot_in().

357 {
358  txid xmin;
359  txid xmax;
360  txid last_val = 0,
361  val;
362  const char *str_start = str;
363  const char *endp;
364  StringInfo buf;
365 
366  xmin = str2txid(str, &endp);
367  if (*endp != ':')
368  goto bad_format;
369  str = endp + 1;
370 
371  xmax = str2txid(str, &endp);
372  if (*endp != ':')
373  goto bad_format;
374  str = endp + 1;
375 
376  /* it should look sane */
377  if (xmin == 0 || xmax == 0 || xmin > xmax)
378  goto bad_format;
379 
380  /* allocate buffer */
381  buf = buf_init(xmin, xmax);
382 
383  /* loop over values */
384  while (*str != '\0')
385  {
386  /* read next value */
387  val = str2txid(str, &endp);
388  str = endp;
389 
390  /* require the input to be in order */
391  if (val < xmin || val >= xmax || val < last_val)
392  goto bad_format;
393 
394  /* skip duplicates */
395  if (val != last_val)
396  buf_add_txid(buf, val);
397  last_val = val;
398 
399  if (*str == ',')
400  str++;
401  else if (*str != '\0')
402  goto bad_format;
403  }
404 
405  return buf_finalize(buf);
406 
407 bad_format:
408  ereport(ERROR,
409  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
410  errmsg("invalid input syntax for type %s: \"%s\"",
411  "txid_snapshot", str_start)));
412  return NULL; /* keep compiler quiet */
413 }
static void buf_add_txid(StringInfo buf, txid xid)
Definition: txid.c:292
static TxidSnapshot * buf_finalize(StringInfo buf)
Definition: txid.c:303
int errcode(int sqlerrcode)
Definition: elog.c:570
uint64 txid
Definition: txid.c:42
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:68
static StringInfo buf_init(txid xmin, txid xmax)
Definition: txid.c:277
#define ereport(elevel, rest)
Definition: elog.h:141
static txid str2txid(const char *s, const char **endp)
Definition: txid.c:322
int errmsg(const char *fmt,...)
Definition: elog.c:784
long val
Definition: informix.c:684

◆ sort_snapshot()

static void sort_snapshot ( TxidSnapshot snap)
static

Definition at line 214 of file txid.c.

References cmp_txid(), TxidSnapshot::nxip, qsort, and TxidSnapshot::xip.

Referenced by txid_current_snapshot().

215 {
216  txid last = 0;
217  int nxip,
218  idx1,
219  idx2;
220 
221  if (snap->nxip > 1)
222  {
223  qsort(snap->xip, snap->nxip, sizeof(txid), cmp_txid);
224 
225  /* remove duplicates */
226  nxip = snap->nxip;
227  idx1 = idx2 = 0;
228  while (idx1 < nxip)
229  {
230  if (snap->xip[idx1] != last)
231  last = snap->xip[idx2++] = snap->xip[idx1];
232  else
233  snap->nxip--;
234  idx1++;
235  }
236  }
237 }
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
uint64 txid
Definition: txid.c:42
static int cmp_txid(const void *aa, const void *bb)
Definition: txid.c:194
uint32 nxip
Definition: txid.c:66
#define qsort(a, b, c, d)
Definition: port.h:492

◆ str2txid()

static txid str2txid ( const char *  s,
const char **  endp 
)
static

Definition at line 322 of file txid.c.

References MAX_TXID, and val.

Referenced by parse_snapshot().

323 {
324  txid val = 0;
325  txid cutoff = MAX_TXID / 10;
326  txid cutlim = MAX_TXID % 10;
327 
328  for (; *s; s++)
329  {
330  unsigned d;
331 
332  if (*s < '0' || *s > '9')
333  break;
334  d = *s - '0';
335 
336  /*
337  * check for overflow
338  */
339  if (val > cutoff || (val == cutoff && d > cutlim))
340  {
341  val = 0;
342  break;
343  }
344 
345  val = val * 10 + d;
346  }
347  if (endp)
348  *endp = s;
349  return val;
350 }
uint64 txid
Definition: txid.c:42
#define MAX_TXID
Definition: txid.c:39
long val
Definition: informix.c:684

◆ TransactionIdInRecentPast()

static bool TransactionIdInRecentPast ( uint64  xid_with_epoch,
TransactionId extracted_xid 
)
static

Definition at line 114 of file txid.c.

References Assert, EpochFromFullTransactionId, ereport, errcode(), errmsg(), ERROR, LWLockHeldByMe(), VariableCacheData::oldestClogXid, psprintf(), ReadNextFullTransactionId(), ShmemVariableCache, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), U64FromFullTransactionId, UINT64_FORMAT, and XidFromFullTransactionId.

Referenced by txid_status().

115 {
116  uint32 xid_epoch = (uint32) (xid_with_epoch >> 32);
117  TransactionId xid = (TransactionId) xid_with_epoch;
118  uint32 now_epoch;
119  TransactionId now_epoch_next_xid;
120  FullTransactionId now_fullxid;
121 
122  now_fullxid = ReadNextFullTransactionId();
123  now_epoch_next_xid = XidFromFullTransactionId(now_fullxid);
124  now_epoch = EpochFromFullTransactionId(now_fullxid);
125 
126  if (extracted_xid != NULL)
127  *extracted_xid = xid;
128 
129  if (!TransactionIdIsValid(xid))
130  return false;
131 
132  /* For non-normal transaction IDs, we can ignore the epoch. */
133  if (!TransactionIdIsNormal(xid))
134  return true;
135 
136  /* If the transaction ID is in the future, throw an error. */
137  if (xid_with_epoch >= U64FromFullTransactionId(now_fullxid))
138  ereport(ERROR,
139  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
140  errmsg("transaction ID %s is in the future",
141  psprintf(UINT64_FORMAT, xid_with_epoch))));
142 
143  /*
144  * ShmemVariableCache->oldestClogXid is protected by CLogTruncationLock,
145  * but we don't acquire that lock here. Instead, we require the caller to
146  * acquire it, because the caller is presumably going to look up the
147  * returned XID. If we took and released the lock within this function, a
148  * CLOG truncation could occur before the caller finished with the XID.
149  */
150  Assert(LWLockHeldByMe(CLogTruncationLock));
151 
152  /*
153  * If the transaction ID has wrapped around, it's definitely too old to
154  * determine the commit status. Otherwise, we can compare it to
155  * ShmemVariableCache->oldestClogXid to determine whether the relevant
156  * CLOG entry is guaranteed to still exist.
157  */
158  if (xid_epoch + 1 < now_epoch
159  || (xid_epoch + 1 == now_epoch && xid < now_epoch_next_xid)
161  return false;
162 
163  return true;
164 }
uint32 TransactionId
Definition: c.h:507
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1842
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int errcode(int sqlerrcode)
Definition: elog.c:570
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define ERROR
Definition: elog.h:43
TransactionId oldestClogXid
Definition: transam.h:188
VariableCache ShmemVariableCache
Definition: varsup.c:34
unsigned int uint32
Definition: c.h:358
#define ereport(elevel, rest)
Definition: elog.h:141
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
FullTransactionId ReadNextFullTransactionId(void)
Definition: varsup.c:246
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
#define Assert(condition)
Definition: c.h:732
#define U64FromFullTransactionId(x)
Definition: transam.h:49
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define UINT64_FORMAT
Definition: c.h:401

◆ txid_current()

Datum txid_current ( PG_FUNCTION_ARGS  )

Definition at line 433 of file txid.c.

References convert_xid(), GetTopTransactionId(), load_xid_epoch(), PG_RETURN_INT64, PreventCommandDuringRecovery(), and val.

434 {
435  txid val;
437 
438  /*
439  * Must prevent during recovery because if an xid is not assigned we try
440  * to assign one, which would fail. Programs already rely on this function
441  * to always return a valid current xid, so we should not change this to
442  * return NULL or similar invalid xid.
443  */
444  PreventCommandDuringRecovery("txid_current()");
445 
446  load_xid_epoch(&state);
447 
448  val = convert_xid(GetTopTransactionId(), &state);
449 
450  PG_RETURN_INT64(val);
451 }
static void load_xid_epoch(TxidEpoch *state)
Definition: txid.c:92
Definition: txid.c:81
#define PG_RETURN_INT64(x)
Definition: fmgr.h:357
TransactionId GetTopTransactionId(void)
Definition: xact.c:395
uint64 txid
Definition: txid.c:42
static txid convert_xid(TransactionId xid, const TxidEpoch *state)
Definition: txid.c:170
void PreventCommandDuringRecovery(const char *cmdname)
Definition: utility.c:276
ts_parserstate state
Definition: tsquery.c:81
long val
Definition: informix.c:684

◆ txid_current_if_assigned()

Datum txid_current_if_assigned ( PG_FUNCTION_ARGS  )

Definition at line 458 of file txid.c.

References convert_xid(), GetTopTransactionIdIfAny(), InvalidTransactionId, load_xid_epoch(), PG_RETURN_INT64, PG_RETURN_NULL, and val.

459 {
460  txid val;
463 
464  if (topxid == InvalidTransactionId)
465  PG_RETURN_NULL();
466 
467  load_xid_epoch(&state);
468 
469  val = convert_xid(topxid, &state);
470 
471  PG_RETURN_INT64(val);
472 }
static void load_xid_epoch(TxidEpoch *state)
Definition: txid.c:92
Definition: txid.c:81
uint32 TransactionId
Definition: c.h:507
#define PG_RETURN_INT64(x)
Definition: fmgr.h:357
uint64 txid
Definition: txid.c:42
static txid convert_xid(TransactionId xid, const TxidEpoch *state)
Definition: txid.c:170
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:410
ts_parserstate state
Definition: tsquery.c:81
long val
Definition: informix.c:684
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ txid_current_snapshot()

Datum txid_current_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 482 of file txid.c.

References convert_xid(), cur, elog, ERROR, GetActiveSnapshot(), i, load_xid_epoch(), MAX_BACKENDS, TxidSnapshot::nxip, palloc(), PG_RETURN_POINTER, SET_VARSIZE, sort_snapshot(), StaticAssertStmt, TXID_SNAPSHOT_MAX_NXIP, TXID_SNAPSHOT_SIZE, SnapshotData::xcnt, TxidSnapshot::xip, SnapshotData::xip, TxidSnapshot::xmax, SnapshotData::xmax, TxidSnapshot::xmin, and SnapshotData::xmin.

483 {
484  TxidSnapshot *snap;
485  uint32 nxip,
486  i;
488  Snapshot cur;
489 
490  cur = GetActiveSnapshot();
491  if (cur == NULL)
492  elog(ERROR, "no active snapshot set");
493 
494  load_xid_epoch(&state);
495 
496  /*
497  * Compile-time limits on the procarray (MAX_BACKENDS processes plus
498  * MAX_BACKENDS prepared transactions) guarantee nxip won't be too large.
499  */
501  "possible overflow in txid_current_snapshot()");
502 
503  /* allocate */
504  nxip = cur->xcnt;
505  snap = palloc(TXID_SNAPSHOT_SIZE(nxip));
506 
507  /* fill */
508  snap->xmin = convert_xid(cur->xmin, &state);
509  snap->xmax = convert_xid(cur->xmax, &state);
510  snap->nxip = nxip;
511  for (i = 0; i < nxip; i++)
512  snap->xip[i] = convert_xid(cur->xip[i], &state);
513 
514  /*
515  * We want them guaranteed to be in ascending order. This also removes
516  * any duplicate xids. Normally, an XID can only be assigned to one
517  * backend, but when preparing a transaction for two-phase commit, there
518  * is a transient state when both the original backend and the dummy
519  * PGPROC entry reserved for the prepared transaction hold the same XID.
520  */
521  sort_snapshot(snap);
522 
523  /* set size after sorting, because it may have removed duplicate xips */
524  SET_VARSIZE(snap, TXID_SNAPSHOT_SIZE(snap->nxip));
525 
526  PG_RETURN_POINTER(snap);
527 }
static void load_xid_epoch(TxidEpoch *state)
Definition: txid.c:92
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
Definition: txid.c:81
static void sort_snapshot(TxidSnapshot *snap)
Definition: txid.c:214
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:841
struct cursor * cur
Definition: ecpg.c:28
txid xmin
Definition: txid.c:67
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:842
static txid convert_xid(TransactionId xid, const TxidEpoch *state)
Definition: txid.c:170
#define ERROR
Definition: elog.h:43
#define MAX_BACKENDS
Definition: postmaster.h:75
unsigned int uint32
Definition: c.h:358
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
TransactionId * xip
Definition: snapshot.h:168
ts_parserstate state
Definition: tsquery.c:81
#define TXID_SNAPSHOT_SIZE(nxip)
Definition: txid.c:73
uint32 xcnt
Definition: snapshot.h:169
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:226
int i
uint32 nxip
Definition: txid.c:66
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
txid xmax
Definition: txid.c:68
#define TXID_SNAPSHOT_MAX_NXIP
Definition: txid.c:75

◆ txid_snapshot_in()

Datum txid_snapshot_in ( PG_FUNCTION_ARGS  )

Definition at line 535 of file txid.c.

References parse_snapshot(), PG_GETARG_CSTRING, PG_RETURN_POINTER, and generate_unaccent_rules::str.

536 {
537  char *str = PG_GETARG_CSTRING(0);
538  TxidSnapshot *snap;
539 
540  snap = parse_snapshot(str);
541 
542  PG_RETURN_POINTER(snap);
543 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
static TxidSnapshot * parse_snapshot(const char *str)
Definition: txid.c:356
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:272

◆ txid_snapshot_out()

Datum txid_snapshot_out ( PG_FUNCTION_ARGS  )

Definition at line 551 of file txid.c.

References appendStringInfo(), appendStringInfoChar(), StringInfoData::data, i, initStringInfo(), TxidSnapshot::nxip, PG_GETARG_VARLENA_P, PG_RETURN_CSTRING, generate_unaccent_rules::str, TXID_FMT, TxidSnapshot::xip, TxidSnapshot::xmax, and TxidSnapshot::xmin.

552 {
555  uint32 i;
556 
557  initStringInfo(&str);
558 
559  appendStringInfo(&str, TXID_FMT ":", snap->xmin);
560  appendStringInfo(&str, TXID_FMT ":", snap->xmax);
561 
562  for (i = 0; i < snap->nxip; i++)
563  {
564  if (i > 0)
565  appendStringInfoChar(&str, ',');
566  appendStringInfo(&str, TXID_FMT, snap->xip[i]);
567  }
568 
569  PG_RETURN_CSTRING(str.data);
570 }
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
txid xmin
Definition: txid.c:67
#define TXID_FMT
Definition: txid.c:45
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:281
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
unsigned int uint32
Definition: c.h:358
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:352
int i
uint32 nxip
Definition: txid.c:66
txid xmax
Definition: txid.c:68

◆ txid_snapshot_recv()

Datum txid_snapshot_recv ( PG_FUNCTION_ARGS  )

Definition at line 580 of file txid.c.

References buf, cur, ereport, errcode(), errmsg(), ERROR, i, MAX_TXID, TxidSnapshot::nxip, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, pq_getmsgint(), pq_getmsgint64(), SET_VARSIZE, TXID_SNAPSHOT_MAX_NXIP, TXID_SNAPSHOT_SIZE, TxidSnapshot::xip, TxidSnapshot::xmax, and TxidSnapshot::xmin.

581 {
583  TxidSnapshot *snap;
584  txid last = 0;
585  int nxip;
586  int i;
587  txid xmin,
588  xmax;
589 
590  /* load and validate nxip */
591  nxip = pq_getmsgint(buf, 4);
592  if (nxip < 0 || nxip > TXID_SNAPSHOT_MAX_NXIP)
593  goto bad_format;
594 
595  xmin = pq_getmsgint64(buf);
596  xmax = pq_getmsgint64(buf);
597  if (xmin == 0 || xmax == 0 || xmin > xmax || xmax > MAX_TXID)
598  goto bad_format;
599 
600  snap = palloc(TXID_SNAPSHOT_SIZE(nxip));
601  snap->xmin = xmin;
602  snap->xmax = xmax;
603 
604  for (i = 0; i < nxip; i++)
605  {
606  txid cur = pq_getmsgint64(buf);
607 
608  if (cur < last || cur < xmin || cur >= xmax)
609  goto bad_format;
610 
611  /* skip duplicate xips */
612  if (cur == last)
613  {
614  i--;
615  nxip--;
616  continue;
617  }
618 
619  snap->xip[i] = cur;
620  last = cur;
621  }
622  snap->nxip = nxip;
623  SET_VARSIZE(snap, TXID_SNAPSHOT_SIZE(nxip));
624  PG_RETURN_POINTER(snap);
625 
626 bad_format:
627  ereport(ERROR,
628  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
629  errmsg("invalid external txid_snapshot data")));
630  PG_RETURN_POINTER(NULL); /* keep compiler quiet */
631 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
StringInfoData * StringInfo
Definition: stringinfo.h:43
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
txid xmin
Definition: txid.c:67
uint64 txid
Definition: txid.c:42
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:68
#define ereport(elevel, rest)
Definition: elog.h:141
#define TXID_SNAPSHOT_SIZE(nxip)
Definition: txid.c:73
#define MAX_TXID
Definition: txid.c:39
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:455
uint32 nxip
Definition: txid.c:66
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
txid xmax
Definition: txid.c:68
#define TXID_SNAPSHOT_MAX_NXIP
Definition: txid.c:75

◆ txid_snapshot_send()

Datum txid_snapshot_send ( PG_FUNCTION_ARGS  )

Definition at line 641 of file txid.c.

References buf, i, TxidSnapshot::nxip, PG_GETARG_VARLENA_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint32(), pq_sendint64(), TxidSnapshot::xip, TxidSnapshot::xmax, and TxidSnapshot::xmin.

642 {
645  uint32 i;
646 
647  pq_begintypsend(&buf);
648  pq_sendint32(&buf, snap->nxip);
649  pq_sendint64(&buf, snap->xmin);
650  pq_sendint64(&buf, snap->xmax);
651  for (i = 0; i < snap->nxip; i++)
652  pq_sendint64(&buf, snap->xip[i]);
654 }
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:360
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:153
txid xmin
Definition: txid.c:67
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:281
static char * buf
Definition: pg_test_fsync.c:68
unsigned int uint32
Definition: c.h:358
int i
uint32 nxip
Definition: txid.c:66
txid xmax
Definition: txid.c:68

◆ txid_snapshot_xip()

Datum txid_snapshot_xip ( PG_FUNCTION_ARGS  )

Definition at line 702 of file txid.c.

References arg, FuncCallContext::call_cntr, Int64GetDatum(), MemoryContextAlloc(), FuncCallContext::multi_call_memory_ctx, TxidSnapshot::nxip, PG_GETARG_VARLENA_P, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::user_fctx, value, VARSIZE, and TxidSnapshot::xip.

703 {
704  FuncCallContext *fctx;
705  TxidSnapshot *snap;
706  txid value;
707 
708  /* on first call initialize fctx and get copy of snapshot */
709  if (SRF_IS_FIRSTCALL())
710  {
712 
713  fctx = SRF_FIRSTCALL_INIT();
714 
715  /* make a copy of user snapshot */
717  memcpy(snap, arg, VARSIZE(arg));
718 
719  fctx->user_fctx = snap;
720  }
721 
722  /* return values one-by-one */
723  fctx = SRF_PERCALL_SETUP();
724  snap = fctx->user_fctx;
725  if (fctx->call_cntr < snap->nxip)
726  {
727  value = snap->xip[fctx->call_cntr];
728  SRF_RETURN_NEXT(fctx, Int64GetDatum(value));
729  }
730  else
731  {
732  SRF_RETURN_DONE(fctx);
733  }
734 }
uint64 call_cntr
Definition: funcapi.h:66
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
#define VARSIZE(PTR)
Definition: postgres.h:303
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:283
static struct @145 value
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:287
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:289
uint64 txid
Definition: txid.c:42
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:281
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1699
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:102
void * user_fctx
Definition: funcapi.h:83
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
uint32 nxip
Definition: txid.c:66
void * arg
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:307
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:285

◆ txid_snapshot_xmax()

Datum txid_snapshot_xmax ( PG_FUNCTION_ARGS  )

Definition at line 689 of file txid.c.

References PG_GETARG_VARLENA_P, PG_RETURN_INT64, and TxidSnapshot::xmax.

690 {
692 
693  PG_RETURN_INT64(snap->xmax);
694 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:357
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:281
txid xmax
Definition: txid.c:68

◆ txid_snapshot_xmin()

Datum txid_snapshot_xmin ( PG_FUNCTION_ARGS  )

Definition at line 676 of file txid.c.

References PG_GETARG_VARLENA_P, PG_RETURN_INT64, and TxidSnapshot::xmin.

677 {
679 
680  PG_RETURN_INT64(snap->xmin);
681 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:357
txid xmin
Definition: txid.c:67
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:281

◆ txid_status()

Datum txid_status ( PG_FUNCTION_ARGS  )

Definition at line 747 of file txid.c.

References Assert, cstring_to_text(), GetActiveSnapshot(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PG_GETARG_INT64, PG_RETURN_NULL, PG_RETURN_TEXT_P, status(), TransactionIdDidAbort(), TransactionIdDidCommit(), TransactionIdInRecentPast(), TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, and TransactionIdPrecedes().

748 {
749  const char *status;
750  uint64 xid_with_epoch = PG_GETARG_INT64(0);
751  TransactionId xid;
752 
753  /*
754  * We must protect against concurrent truncation of clog entries to avoid
755  * an I/O error on SLRU lookup.
756  */
757  LWLockAcquire(CLogTruncationLock, LW_SHARED);
758  if (TransactionIdInRecentPast(xid_with_epoch, &xid))
759  {
761 
763  status = "in progress";
764  else if (TransactionIdDidCommit(xid))
765  status = "committed";
766  else if (TransactionIdDidAbort(xid))
767  status = "aborted";
768  else
769  {
770  /*
771  * The xact is not marked as either committed or aborted in clog.
772  *
773  * It could be a transaction that ended without updating clog or
774  * writing an abort record due to a crash. We can safely assume
775  * it's aborted if it isn't committed and is older than our
776  * snapshot xmin.
777  *
778  * Otherwise it must be in-progress (or have been at the time we
779  * checked commit/abort status).
780  */
781  if (TransactionIdPrecedes(xid, GetActiveSnapshot()->xmin))
782  status = "aborted";
783  else
784  status = "in progress";
785  }
786  }
787  else
788  {
789  status = NULL;
790  }
791  LWLockRelease(CLogTruncationLock);
792 
793  if (status == NULL)
794  PG_RETURN_NULL();
795  else
797 }
uint32 TransactionId
Definition: c.h:507
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:854
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:841
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static bool TransactionIdInRecentPast(uint64 xid_with_epoch, TransactionId *extracted_xid)
Definition: txid.c:114
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
text * cstring_to_text(const char *s)
Definition: varlena.c:171
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ txid_visible_in_snapshot()

Datum txid_visible_in_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 662 of file txid.c.

References is_visible_txid(), PG_GETARG_INT64, PG_GETARG_VARLENA_P, PG_RETURN_BOOL, and value.

663 {
666 
667  PG_RETURN_BOOL(is_visible_txid(value, snap));
668 }
static struct @145 value
uint64 txid
Definition: txid.c:42
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:281
static bool is_visible_txid(txid value, const TxidSnapshot *snap)
Definition: txid.c:243
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277