PostgreSQL Source Code  git master
xid8funcs.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 "lib/qunique.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "storage/lwlock.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
#include "utils/xid8.h"
Include dependency graph for xid8funcs.c:

Go to the source code of this file.

Data Structures

struct  pg_snapshot
 

Macros

#define USE_BSEARCH_IF_NXIP_GREATER   30
 
#define PG_SNAPSHOT_SIZE(nxip)    (offsetof(pg_snapshot, xip) + sizeof(FullTransactionId) * (nxip))
 
#define PG_SNAPSHOT_MAX_NXIP    ((MaxAllocSize - offsetof(pg_snapshot, xip)) / sizeof(FullTransactionId))
 

Functions

static bool TransactionIdInRecentPast (FullTransactionId fxid, TransactionId *extracted_xid)
 
static FullTransactionId widen_snapshot_xid (TransactionId xid, FullTransactionId next_fxid)
 
static int cmp_fxid (const void *aa, const void *bb)
 
static void sort_snapshot (pg_snapshot *snap)
 
static bool is_visible_fxid (FullTransactionId value, const pg_snapshot *snap)
 
static StringInfo buf_init (FullTransactionId xmin, FullTransactionId xmax)
 
static void buf_add_txid (StringInfo buf, FullTransactionId fxid)
 
static pg_snapshotbuf_finalize (StringInfo buf)
 
static pg_snapshotparse_snapshot (const char *str)
 
Datum pg_current_xact_id (PG_FUNCTION_ARGS)
 
Datum pg_current_xact_id_if_assigned (PG_FUNCTION_ARGS)
 
Datum pg_current_snapshot (PG_FUNCTION_ARGS)
 
Datum pg_snapshot_in (PG_FUNCTION_ARGS)
 
Datum pg_snapshot_out (PG_FUNCTION_ARGS)
 
Datum pg_snapshot_recv (PG_FUNCTION_ARGS)
 
Datum pg_snapshot_send (PG_FUNCTION_ARGS)
 
Datum pg_visible_in_snapshot (PG_FUNCTION_ARGS)
 
Datum pg_snapshot_xmin (PG_FUNCTION_ARGS)
 
Datum pg_snapshot_xmax (PG_FUNCTION_ARGS)
 
Datum pg_snapshot_xip (PG_FUNCTION_ARGS)
 
Datum pg_xact_status (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ PG_SNAPSHOT_MAX_NXIP

#define PG_SNAPSHOT_MAX_NXIP    ((MaxAllocSize - offsetof(pg_snapshot, xip)) / sizeof(FullTransactionId))

Definition at line 73 of file xid8funcs.c.

◆ PG_SNAPSHOT_SIZE

#define PG_SNAPSHOT_SIZE (   nxip)     (offsetof(pg_snapshot, xip) + sizeof(FullTransactionId) * (nxip))

Definition at line 71 of file xid8funcs.c.

◆ USE_BSEARCH_IF_NXIP_GREATER

#define USE_BSEARCH_IF_NXIP_GREATER   30

Definition at line 49 of file xid8funcs.c.

Function Documentation

◆ buf_add_txid()

static void buf_add_txid ( StringInfo  buf,
FullTransactionId  fxid 
)
static

Definition at line 259 of file xid8funcs.c.

260 {
261  pg_snapshot *snap = (pg_snapshot *) buf->data;
262 
263  /* do this before possible realloc */
264  snap->nxip++;
265 
266  appendBinaryStringInfo(buf, (char *) &fxid, sizeof(fxid));
267 }
static char * buf
Definition: pg_test_fsync.c:67
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
uint32 nxip
Definition: xid8funcs.c:64

References appendBinaryStringInfo(), buf, and pg_snapshot::nxip.

Referenced by parse_snapshot().

◆ buf_finalize()

static pg_snapshot* buf_finalize ( StringInfo  buf)
static

Definition at line 270 of file xid8funcs.c.

271 {
272  pg_snapshot *snap = (pg_snapshot *) buf->data;
273 
274  SET_VARSIZE(snap, buf->len);
275 
276  /* buf is not needed anymore */
277  buf->data = NULL;
278  pfree(buf);
279 
280  return snap;
281 }
void pfree(void *pointer)
Definition: mcxt.c:1175
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342

References buf, pfree(), and SET_VARSIZE.

Referenced by parse_snapshot().

◆ buf_init()

static StringInfo buf_init ( FullTransactionId  xmin,
FullTransactionId  xmax 
)
static

Definition at line 244 of file xid8funcs.c.

245 {
246  pg_snapshot snap;
247  StringInfo buf;
248 
249  snap.xmin = xmin;
250  snap.xmax = xmax;
251  snap.nxip = 0;
252 
253  buf = makeStringInfo();
254  appendBinaryStringInfo(buf, (char *) &snap, PG_SNAPSHOT_SIZE(0));
255  return buf;
256 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
FullTransactionId xmax
Definition: xid8funcs.c:66
FullTransactionId xmin
Definition: xid8funcs.c:65
#define PG_SNAPSHOT_SIZE(nxip)
Definition: xid8funcs.c:71

References appendBinaryStringInfo(), buf, makeStringInfo(), pg_snapshot::nxip, PG_SNAPSHOT_SIZE, pg_snapshot::xmax, and pg_snapshot::xmin.

Referenced by parse_snapshot().

◆ cmp_fxid()

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

Definition at line 175 of file xid8funcs.c.

176 {
177  FullTransactionId a = *(const FullTransactionId *) aa;
178  FullTransactionId b = *(const FullTransactionId *) bb;
179 
181  return -1;
183  return 1;
184  return 0;
185 }
int b
Definition: isn.c:70
int a
Definition: isn.c:69
#define FullTransactionIdPrecedes(a, b)
Definition: transam.h:51

References a, b, and FullTransactionIdPrecedes.

Referenced by is_visible_fxid(), and sort_snapshot().

◆ is_visible_fxid()

static bool is_visible_fxid ( FullTransactionId  value,
const pg_snapshot snap 
)
static

Definition at line 209 of file xid8funcs.c.

210 {
212  return true;
213  else if (!FullTransactionIdPrecedes(value, snap->xmax))
214  return false;
215 #ifdef USE_BSEARCH_IF_NXIP_GREATER
216  else if (snap->nxip > USE_BSEARCH_IF_NXIP_GREATER)
217  {
218  void *res;
219 
220  res = bsearch(&value, snap->xip, snap->nxip, sizeof(FullTransactionId),
221  cmp_fxid);
222  /* if found, transaction is still in progress */
223  return (res) ? false : true;
224  }
225 #endif
226  else
227  {
228  uint32 i;
229 
230  for (i = 0; i < snap->nxip; i++)
231  {
232  if (FullTransactionIdEquals(value, snap->xip[i]))
233  return false;
234  }
235  return true;
236  }
237 }
unsigned int uint32
Definition: c.h:441
static struct @151 value
return false
Definition: isn.c:131
int i
Definition: isn.c:73
FullTransactionId xip[FLEXIBLE_ARRAY_MEMBER]
Definition: xid8funcs.c:68
#define FullTransactionIdEquals(a, b)
Definition: transam.h:50
static int cmp_fxid(const void *aa, const void *bb)
Definition: xid8funcs.c:175
#define USE_BSEARCH_IF_NXIP_GREATER
Definition: xid8funcs.c:49

References cmp_fxid(), false, FullTransactionIdEquals, FullTransactionIdPrecedes, i, pg_snapshot::nxip, res, USE_BSEARCH_IF_NXIP_GREATER, value, pg_snapshot::xip, pg_snapshot::xmax, and pg_snapshot::xmin.

Referenced by pg_visible_in_snapshot().

◆ parse_snapshot()

static pg_snapshot* parse_snapshot ( const char *  str)
static

Definition at line 287 of file xid8funcs.c.

288 {
289  FullTransactionId xmin;
290  FullTransactionId xmax;
293  const char *str_start = str;
294  char *endp;
295  StringInfo buf;
296 
297  xmin = FullTransactionIdFromU64(strtou64(str, &endp, 10));
298  if (*endp != ':')
299  goto bad_format;
300  str = endp + 1;
301 
302  xmax = FullTransactionIdFromU64(strtou64(str, &endp, 10));
303  if (*endp != ':')
304  goto bad_format;
305  str = endp + 1;
306 
307  /* it should look sane */
308  if (!FullTransactionIdIsValid(xmin) ||
309  !FullTransactionIdIsValid(xmax) ||
310  FullTransactionIdPrecedes(xmax, xmin))
311  goto bad_format;
312 
313  /* allocate buffer */
314  buf = buf_init(xmin, xmax);
315 
316  /* loop over values */
317  while (*str != '\0')
318  {
319  /* read next value */
320  val = FullTransactionIdFromU64(strtou64(str, &endp, 10));
321  str = endp;
322 
323  /* require the input to be in order */
324  if (FullTransactionIdPrecedes(val, xmin) ||
326  FullTransactionIdPrecedes(val, last_val))
327  goto bad_format;
328 
329  /* skip duplicates */
330  if (!FullTransactionIdEquals(val, last_val))
331  buf_add_txid(buf, val);
332  last_val = val;
333 
334  if (*str == ',')
335  str++;
336  else if (*str != '\0')
337  goto bad_format;
338  }
339 
340  return buf_finalize(buf);
341 
342 bad_format:
343  ereport(ERROR,
344  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
345  errmsg("invalid input syntax for type %s: \"%s\"",
346  "pg_snapshot", str_start)));
347  return NULL; /* keep compiler quiet */
348 }
#define strtou64(str, endptr, base)
Definition: c.h:1322
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
long val
Definition: informix.c:664
static FullTransactionId FullTransactionIdFromU64(uint64 value)
Definition: transam.h:81
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
#define InvalidFullTransactionId
Definition: transam.h:56
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
static StringInfo buf_init(FullTransactionId xmin, FullTransactionId xmax)
Definition: xid8funcs.c:244
static pg_snapshot * buf_finalize(StringInfo buf)
Definition: xid8funcs.c:270
static void buf_add_txid(StringInfo buf, FullTransactionId fxid)
Definition: xid8funcs.c:259

References buf, buf_add_txid(), buf_finalize(), buf_init(), ereport, errcode(), errmsg(), ERROR, FullTransactionIdEquals, FullTransactionIdFollowsOrEquals, FullTransactionIdFromU64(), FullTransactionIdIsValid, FullTransactionIdPrecedes, InvalidFullTransactionId, generate_unaccent_rules::str, strtou64, and val.

Referenced by pg_snapshot_in().

◆ pg_current_snapshot()

Datum pg_current_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 393 of file xid8funcs.c.

394 {
395  pg_snapshot *snap;
396  uint32 nxip,
397  i;
398  Snapshot cur;
400 
402  if (cur == NULL)
403  elog(ERROR, "no active snapshot set");
404 
405  /*
406  * Compile-time limits on the procarray (MAX_BACKENDS processes plus
407  * MAX_BACKENDS prepared transactions) guarantee nxip won't be too large.
408  */
410  "possible overflow in pg_current_snapshot()");
411 
412  /* allocate */
413  nxip = cur->xcnt;
414  snap = palloc(PG_SNAPSHOT_SIZE(nxip));
415 
416  /* fill */
417  snap->xmin = widen_snapshot_xid(cur->xmin, next_fxid);
418  snap->xmax = widen_snapshot_xid(cur->xmax, next_fxid);
419  snap->nxip = nxip;
420  for (i = 0; i < nxip; i++)
421  snap->xip[i] = widen_snapshot_xid(cur->xip[i], next_fxid);
422 
423  /*
424  * We want them guaranteed to be in ascending order. This also removes
425  * any duplicate xids. Normally, an XID can only be assigned to one
426  * backend, but when preparing a transaction for two-phase commit, there
427  * is a transient state when both the original backend and the dummy
428  * PGPROC entry reserved for the prepared transaction hold the same XID.
429  */
430  sort_snapshot(snap);
431 
432  /* set size after sorting, because it may have removed duplicate xips */
433  SET_VARSIZE(snap, PG_SNAPSHOT_SIZE(snap->nxip));
434 
435  PG_RETURN_POINTER(snap);
436 }
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:918
struct cursor * cur
Definition: ecpg.c:28
#define elog(elevel,...)
Definition: elog.h:218
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
void * palloc(Size size)
Definition: mcxt.c:1068
#define MAX_BACKENDS
Definition: postmaster.h:75
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:803
FullTransactionId ReadNextFullTransactionId(void)
Definition: varsup.c:261
#define PG_SNAPSHOT_MAX_NXIP
Definition: xid8funcs.c:73
static void sort_snapshot(pg_snapshot *snap)
Definition: xid8funcs.c:195
static FullTransactionId widen_snapshot_xid(TransactionId xid, FullTransactionId next_fxid)
Definition: xid8funcs.c:149

References cur, elog, ERROR, GetActiveSnapshot(), i, MAX_BACKENDS, pg_snapshot::nxip, palloc(), PG_RETURN_POINTER, PG_SNAPSHOT_MAX_NXIP, PG_SNAPSHOT_SIZE, ReadNextFullTransactionId(), SET_VARSIZE, sort_snapshot(), StaticAssertStmt, widen_snapshot_xid(), pg_snapshot::xip, pg_snapshot::xmax, and pg_snapshot::xmin.

◆ pg_current_xact_id()

Datum pg_current_xact_id ( PG_FUNCTION_ARGS  )

Definition at line 357 of file xid8funcs.c.

358 {
359  /*
360  * Must prevent during recovery because if an xid is not assigned we try
361  * to assign one, which would fail. Programs already rely on this function
362  * to always return a valid current xid, so we should not change this to
363  * return NULL or similar invalid xid.
364  */
365  PreventCommandDuringRecovery("pg_current_xact_id()");
366 
368 }
void PreventCommandDuringRecovery(const char *cmdname)
Definition: utility.c:448
FullTransactionId GetTopFullTransactionId(void)
Definition: xact.c:470
#define PG_RETURN_FULLTRANSACTIONID(X)
Definition: xid8.h:20

References GetTopFullTransactionId(), PG_RETURN_FULLTRANSACTIONID, and PreventCommandDuringRecovery().

◆ pg_current_xact_id_if_assigned()

Datum pg_current_xact_id_if_assigned ( PG_FUNCTION_ARGS  )

Definition at line 375 of file xid8funcs.c.

376 {
378 
379  if (!FullTransactionIdIsValid(topfxid))
380  PG_RETURN_NULL();
381 
383 }
#define PG_RETURN_NULL()
Definition: fmgr.h:345
FullTransactionId GetTopFullTransactionIdIfAny(void)
Definition: xact.c:486

References FullTransactionIdIsValid, GetTopFullTransactionIdIfAny(), PG_RETURN_FULLTRANSACTIONID, and PG_RETURN_NULL.

◆ pg_snapshot_in()

Datum pg_snapshot_in ( PG_FUNCTION_ARGS  )

Definition at line 444 of file xid8funcs.c.

445 {
446  char *str = PG_GETARG_CSTRING(0);
447  pg_snapshot *snap;
448 
449  snap = parse_snapshot(str);
450 
451  PG_RETURN_POINTER(snap);
452 }
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
static pg_snapshot * parse_snapshot(const char *str)
Definition: xid8funcs.c:287

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

◆ pg_snapshot_out()

Datum pg_snapshot_out ( PG_FUNCTION_ARGS  )

Definition at line 460 of file xid8funcs.c.

461 {
464  uint32 i;
465 
467 
472 
473  for (i = 0; i < snap->nxip; i++)
474  {
475  if (i > 0)
476  appendStringInfoChar(&str, ',');
478  U64FromFullTransactionId(snap->xip[i]));
479  }
480 
481  PG_RETURN_CSTRING(str.data);
482 }
#define UINT64_FORMAT
Definition: c.h:484
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:287
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define U64FromFullTransactionId(x)
Definition: transam.h:49

References appendStringInfo(), appendStringInfoChar(), i, initStringInfo(), pg_snapshot::nxip, PG_GETARG_VARLENA_P, PG_RETURN_CSTRING, generate_unaccent_rules::str, U64FromFullTransactionId, UINT64_FORMAT, pg_snapshot::xip, pg_snapshot::xmax, and pg_snapshot::xmin.

◆ pg_snapshot_recv()

Datum pg_snapshot_recv ( PG_FUNCTION_ARGS  )

Definition at line 492 of file xid8funcs.c.

493 {
495  pg_snapshot *snap;
497  int nxip;
498  int i;
499  FullTransactionId xmin;
500  FullTransactionId xmax;
501 
502  /* load and validate nxip */
503  nxip = pq_getmsgint(buf, 4);
504  if (nxip < 0 || nxip > PG_SNAPSHOT_MAX_NXIP)
505  goto bad_format;
506 
507  xmin = FullTransactionIdFromU64((uint64) pq_getmsgint64(buf));
508  xmax = FullTransactionIdFromU64((uint64) pq_getmsgint64(buf));
509  if (!FullTransactionIdIsValid(xmin) ||
510  !FullTransactionIdIsValid(xmax) ||
511  FullTransactionIdPrecedes(xmax, xmin))
512  goto bad_format;
513 
514  snap = palloc(PG_SNAPSHOT_SIZE(nxip));
515  snap->xmin = xmin;
516  snap->xmax = xmax;
517 
518  for (i = 0; i < nxip; i++)
519  {
522 
523  if (FullTransactionIdPrecedes(cur, last) ||
526  goto bad_format;
527 
528  /* skip duplicate xips */
529  if (FullTransactionIdEquals(cur, last))
530  {
531  i--;
532  nxip--;
533  continue;
534  }
535 
536  snap->xip[i] = cur;
537  last = cur;
538  }
539  snap->nxip = nxip;
540  SET_VARSIZE(snap, PG_SNAPSHOT_SIZE(nxip));
541  PG_RETURN_POINTER(snap);
542 
543 bad_format:
544  ereport(ERROR,
545  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
546  errmsg("invalid external pg_snapshot data")));
547  PG_RETURN_POINTER(NULL); /* keep compiler quiet */
548 }
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:455
StringInfoData * StringInfo
Definition: stringinfo.h:44

References buf, cur, ereport, errcode(), errmsg(), ERROR, FullTransactionIdEquals, FullTransactionIdFromU64(), FullTransactionIdIsValid, FullTransactionIdPrecedes, i, InvalidFullTransactionId, pg_snapshot::nxip, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PG_SNAPSHOT_MAX_NXIP, PG_SNAPSHOT_SIZE, pq_getmsgint(), pq_getmsgint64(), SET_VARSIZE, pg_snapshot::xip, pg_snapshot::xmax, and pg_snapshot::xmin.

◆ pg_snapshot_send()

Datum pg_snapshot_send ( PG_FUNCTION_ARGS  )

Definition at line 558 of file xid8funcs.c.

559 {
562  uint32 i;
563 
565  pq_sendint32(&buf, snap->nxip);
566  pq_sendint64(&buf, (int64) U64FromFullTransactionId(snap->xmin));
567  pq_sendint64(&buf, (int64) U64FromFullTransactionId(snap->xmax));
568  for (i = 0; i < snap->nxip; i++)
569  pq_sendint64(&buf, (int64) U64FromFullTransactionId(snap->xip[i]));
571 }
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:153

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

◆ pg_snapshot_xip()

Datum pg_snapshot_xip ( PG_FUNCTION_ARGS  )

Definition at line 619 of file xid8funcs.c.

620 {
621  FuncCallContext *fctx;
622  pg_snapshot *snap;
624 
625  /* on first call initialize fctx and get copy of snapshot */
626  if (SRF_IS_FIRSTCALL())
627  {
629 
630  fctx = SRF_FIRSTCALL_INIT();
631 
632  /* make a copy of user snapshot */
634  memcpy(snap, arg, VARSIZE(arg));
635 
636  fctx->user_fctx = snap;
637  }
638 
639  /* return values one-by-one */
640  fctx = SRF_PERCALL_SETUP();
641  snap = fctx->user_fctx;
642  if (fctx->call_cntr < snap->nxip)
643  {
644  value = snap->xip[fctx->call_cntr];
646  }
647  else
648  {
649  SRF_RETURN_DONE(fctx);
650  }
651 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:299
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:303
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:305
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:301
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:323
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
void * arg
#define VARSIZE(PTR)
Definition: postgres.h:316
void * user_fctx
Definition: funcapi.h:82
uint64 call_cntr
Definition: funcapi.h:65
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
#define FullTransactionIdGetDatum(X)
Definition: xid8.h:18

References arg, FuncCallContext::call_cntr, FullTransactionIdGetDatum, MemoryContextAlloc(), FuncCallContext::multi_call_memory_ctx, pg_snapshot::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 pg_snapshot::xip.

◆ pg_snapshot_xmax()

Datum pg_snapshot_xmax ( PG_FUNCTION_ARGS  )

Definition at line 606 of file xid8funcs.c.

607 {
609 
611 }

References PG_GETARG_VARLENA_P, PG_RETURN_FULLTRANSACTIONID, and pg_snapshot::xmax.

◆ pg_snapshot_xmin()

Datum pg_snapshot_xmin ( PG_FUNCTION_ARGS  )

Definition at line 593 of file xid8funcs.c.

594 {
596 
598 }

References PG_GETARG_VARLENA_P, PG_RETURN_FULLTRANSACTIONID, and pg_snapshot::xmin.

◆ pg_visible_in_snapshot()

Datum pg_visible_in_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 579 of file xid8funcs.c.

580 {
583 
585 }
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define PG_GETARG_FULLTRANSACTIONID(X)
Definition: xid8.h:19
static bool is_visible_fxid(FullTransactionId value, const pg_snapshot *snap)
Definition: xid8funcs.c:209

References is_visible_fxid(), PG_GETARG_FULLTRANSACTIONID, PG_GETARG_VARLENA_P, PG_RETURN_BOOL, and value.

◆ pg_xact_status()

Datum pg_xact_status ( PG_FUNCTION_ARGS  )

Definition at line 664 of file xid8funcs.c.

665 {
666  const char *status;
668  TransactionId xid;
669 
670  /*
671  * We must protect against concurrent truncation of clog entries to avoid
672  * an I/O error on SLRU lookup.
673  */
674  LWLockAcquire(XactTruncationLock, LW_SHARED);
675  if (TransactionIdInRecentPast(fxid, &xid))
676  {
678 
680  status = "in progress";
681  else if (TransactionIdDidCommit(xid))
682  status = "committed";
683  else if (TransactionIdDidAbort(xid))
684  status = "aborted";
685  else
686  {
687  /*
688  * The xact is not marked as either committed or aborted in clog.
689  *
690  * It could be a transaction that ended without updating clog or
691  * writing an abort record due to a crash. We can safely assume
692  * it's aborted if it isn't committed and is older than our
693  * snapshot xmin.
694  *
695  * Otherwise it must be in-progress (or have been at the time we
696  * checked commit/abort status).
697  */
698  if (TransactionIdPrecedes(xid, GetActiveSnapshot()->xmin))
699  status = "aborted";
700  else
701  status = "in progress";
702  }
703  }
704  else
705  {
706  status = NULL;
707  }
708  LWLockRelease(XactTruncationLock);
709 
710  if (status == NULL)
711  PG_RETURN_NULL();
712  else
714 }
uint32 TransactionId
Definition: c.h:587
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
Assert(fmt[strlen(fmt) - 1] !='\n')
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1196
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1800
@ LW_SHARED
Definition: lwlock.h:105
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
#define TransactionIdIsValid(xid)
Definition: transam.h:41
text * cstring_to_text(const char *s)
Definition: varlena.c:188
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:922
static bool TransactionIdInRecentPast(FullTransactionId fxid, TransactionId *extracted_xid)
Definition: xid8funcs.c:90

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

◆ sort_snapshot()

static void sort_snapshot ( pg_snapshot snap)
static

Definition at line 195 of file xid8funcs.c.

196 {
197  if (snap->nxip > 1)
198  {
199  qsort(snap->xip, snap->nxip, sizeof(FullTransactionId), cmp_fxid);
200  snap->nxip = qunique(snap->xip, snap->nxip, sizeof(FullTransactionId),
201  cmp_fxid);
202  }
203 }
#define qsort(a, b, c, d)
Definition: port.h:495
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition: qunique.h:21

References cmp_fxid(), pg_snapshot::nxip, qsort, qunique(), and pg_snapshot::xip.

Referenced by pg_current_snapshot().

◆ TransactionIdInRecentPast()

static bool TransactionIdInRecentPast ( FullTransactionId  fxid,
TransactionId extracted_xid 
)
static

Definition at line 90 of file xid8funcs.c.

91 {
92  uint32 xid_epoch = EpochFromFullTransactionId(fxid);
94  uint32 now_epoch;
95  TransactionId now_epoch_next_xid;
96  FullTransactionId now_fullxid;
97 
98  now_fullxid = ReadNextFullTransactionId();
99  now_epoch_next_xid = XidFromFullTransactionId(now_fullxid);
100  now_epoch = EpochFromFullTransactionId(now_fullxid);
101 
102  if (extracted_xid != NULL)
103  *extracted_xid = xid;
104 
105  if (!TransactionIdIsValid(xid))
106  return false;
107 
108  /* For non-normal transaction IDs, we can ignore the epoch. */
109  if (!TransactionIdIsNormal(xid))
110  return true;
111 
112  /* If the transaction ID is in the future, throw an error. */
113  if (!FullTransactionIdPrecedes(fxid, now_fullxid))
114  ereport(ERROR,
115  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
116  errmsg("transaction ID %llu is in the future",
117  (unsigned long long) U64FromFullTransactionId(fxid))));
118 
119  /*
120  * ShmemVariableCache->oldestClogXid is protected by XactTruncationLock,
121  * but we don't acquire that lock here. Instead, we require the caller to
122  * acquire it, because the caller is presumably going to look up the
123  * returned XID. If we took and released the lock within this function, a
124  * CLOG truncation could occur before the caller finished with the XID.
125  */
126  Assert(LWLockHeldByMe(XactTruncationLock));
127 
128  /*
129  * If the transaction ID has wrapped around, it's definitely too old to
130  * determine the commit status. Otherwise, we can compare it to
131  * ShmemVariableCache->oldestClogXid to determine whether the relevant
132  * CLOG entry is guaranteed to still exist.
133  */
134  if (xid_epoch + 1 < now_epoch
135  || (xid_epoch + 1 == now_epoch && xid < now_epoch_next_xid)
137  return false;
138 
139  return true;
140 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1916
TransactionId oldestClogXid
Definition: transam.h:253
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
VariableCache ShmemVariableCache
Definition: varsup.c:34

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

Referenced by pg_xact_status().

◆ widen_snapshot_xid()

static FullTransactionId widen_snapshot_xid ( TransactionId  xid,
FullTransactionId  next_fxid 
)
static

Definition at line 149 of file xid8funcs.c.

150 {
151  TransactionId next_xid = XidFromFullTransactionId(next_fxid);
153 
154  /* Special transaction ID. */
155  if (!TransactionIdIsNormal(xid))
156  return FullTransactionIdFromEpochAndXid(0, xid);
157 
158  /*
159  * The 64 bit result must be <= next_fxid, since next_fxid hadn't been
160  * issued yet when the snapshot was created. Every TransactionId in the
161  * snapshot must therefore be from the same epoch as next_fxid, or the
162  * epoch before. We know this because next_fxid is never allow to get
163  * more than one epoch ahead of the TransactionIds in any snapshot.
164  */
165  if (xid > next_xid)
166  epoch--;
167 
169 }
static const unsigned __int64 epoch
Definition: gettimeofday.c:34
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71

References epoch, EpochFromFullTransactionId, FullTransactionIdFromEpochAndXid(), TransactionIdIsNormal, and XidFromFullTransactionId.

Referenced by pg_current_snapshot().