PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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

#define MAX_TXID   ((uint64) PG_INT64_MAX)

Definition at line 39 of file txid.c.

Referenced by str2txid(), and txid_snapshot_recv().

#define TXID_FMT   UINT64_FORMAT

Definition at line 45 of file txid.c.

Referenced by txid_snapshot_out().

#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().

#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().

#define USE_BSEARCH_IF_NXIP_GREATER   30

Definition at line 51 of file txid.c.

Referenced by is_visible_txid().

Typedef Documentation

typedef uint64 txid

Definition at line 42 of file txid.c.

Function Documentation

static void buf_add_txid ( StringInfo  buf,
txid  xid 
)
static

Definition at line 287 of file txid.c.

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

Referenced by parse_snapshot().

288 {
289  TxidSnapshot *snap = (TxidSnapshot *) buf->data;
290 
291  /* do this before possible realloc */
292  snap->nxip++;
293 
294  appendBinaryStringInfo(buf, (char *) &xid, sizeof(xid));
295 }
uint32 nxip
Definition: txid.c:66
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:208
static TxidSnapshot* buf_finalize ( StringInfo  buf)
static

Definition at line 298 of file txid.c.

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

Referenced by parse_snapshot().

299 {
300  TxidSnapshot *snap = (TxidSnapshot *) buf->data;
301 
302  SET_VARSIZE(snap, buf->len);
303 
304  /* buf is not needed anymore */
305  buf->data = NULL;
306  pfree(buf);
307 
308  return snap;
309 }
void pfree(void *pointer)
Definition: mcxt.c:950
#define NULL
Definition: c.h:229
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
static StringInfo buf_init ( txid  xmin,
txid  xmax 
)
static

Definition at line 272 of file txid.c.

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

Referenced by parse_snapshot().

273 {
274  TxidSnapshot snap;
275  StringInfo buf;
276 
277  snap.xmin = xmin;
278  snap.xmax = xmax;
279  snap.nxip = 0;
280 
281  buf = makeStringInfo();
282  appendBinaryStringInfo(buf, (char *) &snap, TXID_SNAPSHOT_SIZE(0));
283  return buf;
284 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
txid xmin
Definition: txid.c:67
static char * buf
Definition: pg_test_fsync.c:66
#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:208
static int cmp_txid ( const void *  aa,
const void *  bb 
)
static

Definition at line 189 of file txid.c.

Referenced by is_visible_txid(), and sort_snapshot().

190 {
191  txid a = *(const txid *) aa;
192  txid b = *(const txid *) bb;
193 
194  if (a < b)
195  return -1;
196  if (a > b)
197  return 1;
198  return 0;
199 }
uint64 txid
Definition: txid.c:42
static txid convert_xid ( TransactionId  xid,
const TxidEpoch state 
)
static

Definition at line 165 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().

166 {
167  uint64 epoch;
168 
169  /* return special xid's as-is */
170  if (!TransactionIdIsNormal(xid))
171  return (txid) xid;
172 
173  /* xid can be on either side when near wrap-around */
174  epoch = (uint64) state->epoch;
175  if (xid > state->last_xid &&
176  TransactionIdPrecedes(xid, state->last_xid))
177  epoch--;
178  else if (xid < state->last_xid &&
179  TransactionIdFollows(xid, state->last_xid))
180  epoch++;
181 
182  return (epoch << 32) | xid;
183 }
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
static bool is_visible_txid ( txid  value,
const TxidSnapshot snap 
)
static

Definition at line 238 of file txid.c.

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

Referenced by txid_visible_in_snapshot().

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

Definition at line 92 of file txid.c.

References TxidEpoch::epoch, GetNextXidAndEpoch(), and TxidEpoch::last_xid.

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

93 {
94  GetNextXidAndEpoch(&state->last_xid, &state->epoch);
95 }
TransactionId last_xid
Definition: txid.c:83
void GetNextXidAndEpoch(TransactionId *xid, uint32 *epoch)
Definition: xlog.c:8290
uint32 epoch
Definition: txid.c:84
static TxidSnapshot* parse_snapshot ( const char *  str)
static

Definition at line 351 of file txid.c.

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

Referenced by txid_snapshot_in().

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

Definition at line 209 of file txid.c.

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

Referenced by txid_current_snapshot().

210 {
211  txid last = 0;
212  int nxip,
213  idx1,
214  idx2;
215 
216  if (snap->nxip > 1)
217  {
218  qsort(snap->xip, snap->nxip, sizeof(txid), cmp_txid);
219 
220  /* remove duplicates */
221  nxip = snap->nxip;
222  idx1 = idx2 = 0;
223  while (idx1 < nxip)
224  {
225  if (snap->xip[idx1] != last)
226  last = snap->xip[idx2++] = snap->xip[idx1];
227  else
228  snap->nxip--;
229  idx1++;
230  }
231  }
232 }
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:189
uint32 nxip
Definition: txid.c:66
#define qsort(a, b, c, d)
Definition: port.h:443
static txid str2txid ( const char *  s,
const char **  endp 
)
static

Definition at line 317 of file txid.c.

References MAX_TXID, and val.

Referenced by parse_snapshot().

318 {
319  txid val = 0;
320  txid cutoff = MAX_TXID / 10;
321  txid cutlim = MAX_TXID % 10;
322 
323  for (; *s; s++)
324  {
325  unsigned d;
326 
327  if (*s < '0' || *s > '9')
328  break;
329  d = *s - '0';
330 
331  /*
332  * check for overflow
333  */
334  if (val > cutoff || (val == cutoff && d > cutlim))
335  {
336  val = 0;
337  break;
338  }
339 
340  val = val * 10 + d;
341  }
342  if (endp)
343  *endp = s;
344  return val;
345 }
uint64 txid
Definition: txid.c:42
#define MAX_TXID
Definition: txid.c:39
long val
Definition: informix.c:689
static bool TransactionIdInRecentPast ( uint64  xid_with_epoch,
TransactionId extracted_xid 
)
static

Definition at line 111 of file txid.c.

References Assert, ereport, errcode(), errmsg(), ERROR, GetNextXidAndEpoch(), LWLockHeldByMe(), NULL, VariableCacheData::oldestClogXid, ShmemVariableCache, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), and UINT64_FORMAT.

Referenced by txid_status().

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

Definition at line 428 of file txid.c.

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

429 {
430  txid val;
432 
433  /*
434  * Must prevent during recovery because if an xid is not assigned we try
435  * to assign one, which would fail. Programs already rely on this function
436  * to always return a valid current xid, so we should not change this to
437  * return NULL or similar invalid xid.
438  */
439  PreventCommandDuringRecovery("txid_current()");
440 
441  load_xid_epoch(&state);
442 
443  val = convert_xid(GetTopTransactionId(), &state);
444 
445  PG_RETURN_INT64(val);
446 }
static void load_xid_epoch(TxidEpoch *state)
Definition: txid.c:92
Definition: txid.c:81
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
uint64 txid
Definition: txid.c:42
static txid convert_xid(TransactionId xid, const TxidEpoch *state)
Definition: txid.c:165
void PreventCommandDuringRecovery(const char *cmdname)
Definition: utility.c:273
long val
Definition: informix.c:689
Datum txid_current_if_assigned ( PG_FUNCTION_ARGS  )

Definition at line 453 of file txid.c.

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

454 {
455  txid val;
458 
459  if (topxid == InvalidTransactionId)
460  PG_RETURN_NULL();
461 
462  load_xid_epoch(&state);
463 
464  val = convert_xid(topxid, &state);
465 
466  PG_RETURN_INT64(val);
467 }
static void load_xid_epoch(TxidEpoch *state)
Definition: txid.c:92
Definition: txid.c:81
uint32 TransactionId
Definition: c.h:397
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
uint64 txid
Definition: txid.c:42
static txid convert_xid(TransactionId xid, const TxidEpoch *state)
Definition: txid.c:165
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum txid_current_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 477 of file txid.c.

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

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

Definition at line 530 of file txid.c.

References parse_snapshot(), PG_GETARG_CSTRING, and PG_RETURN_POINTER.

531 {
532  char *str = PG_GETARG_CSTRING(0);
533  TxidSnapshot *snap;
534 
535  snap = parse_snapshot(str);
536 
537  PG_RETURN_POINTER(snap);
538 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
static TxidSnapshot * parse_snapshot(const char *str)
Definition: txid.c:351
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
Datum txid_snapshot_out ( PG_FUNCTION_ARGS  )

Definition at line 546 of file txid.c.

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

547 {
549  StringInfoData str;
550  uint32 i;
551 
552  initStringInfo(&str);
553 
554  appendStringInfo(&str, TXID_FMT ":", snap->xmin);
555  appendStringInfo(&str, TXID_FMT ":", snap->xmax);
556 
557  for (i = 0; i < snap->nxip; i++)
558  {
559  if (i > 0)
560  appendStringInfoChar(&str, ',');
561  appendStringInfo(&str, TXID_FMT, snap->xip[i]);
562  }
563 
564  PG_RETURN_CSTRING(str.data);
565 }
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:251
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
unsigned int uint32
Definition: c.h:268
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:322
int i
uint32 nxip
Definition: txid.c:66
txid xmax
Definition: txid.c:68
Datum txid_snapshot_recv ( PG_FUNCTION_ARGS  )

Definition at line 575 of file txid.c.

References buf, cur, ereport, errcode(), errmsg(), ERROR, i, MAX_TXID, NULL, 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.

576 {
578  TxidSnapshot *snap;
579  txid last = 0;
580  int nxip;
581  int i;
582  txid xmin,
583  xmax;
584 
585  /* load and validate nxip */
586  nxip = pq_getmsgint(buf, 4);
587  if (nxip < 0 || nxip > TXID_SNAPSHOT_MAX_NXIP)
588  goto bad_format;
589 
590  xmin = pq_getmsgint64(buf);
591  xmax = pq_getmsgint64(buf);
592  if (xmin == 0 || xmax == 0 || xmin > xmax || xmax > MAX_TXID)
593  goto bad_format;
594 
595  snap = palloc(TXID_SNAPSHOT_SIZE(nxip));
596  snap->xmin = xmin;
597  snap->xmax = xmax;
598 
599  for (i = 0; i < nxip; i++)
600  {
601  txid cur = pq_getmsgint64(buf);
602 
603  if (cur < last || cur < xmin || cur >= xmax)
604  goto bad_format;
605 
606  /* skip duplicate xips */
607  if (cur == last)
608  {
609  i--;
610  nxip--;
611  continue;
612  }
613 
614  snap->xip[i] = cur;
615  last = cur;
616  }
617  snap->nxip = nxip;
618  SET_VARSIZE(snap, TXID_SNAPSHOT_SIZE(nxip));
619  PG_RETURN_POINTER(snap);
620 
621 bad_format:
622  ereport(ERROR,
623  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
624  errmsg("invalid external txid_snapshot data")));
625  PG_RETURN_POINTER(NULL); /* keep compiler quiet */
626 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
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:575
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
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:66
#define ereport(elevel, rest)
Definition: elog.h:122
#define TXID_SNAPSHOT_SIZE(nxip)
Definition: txid.c:73
#define NULL
Definition: c.h:229
#define MAX_TXID
Definition: txid.c:39
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:486
uint32 nxip
Definition: txid.c:66
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:448
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
txid xmax
Definition: txid.c:68
#define TXID_SNAPSHOT_MAX_NXIP
Definition: txid.c:75
Datum txid_snapshot_send ( PG_FUNCTION_ARGS  )

Definition at line 636 of file txid.c.

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

637 {
640  uint32 i;
641 
642  pq_begintypsend(&buf);
643  pq_sendint(&buf, snap->nxip, 4);
644  pq_sendint64(&buf, snap->xmin);
645  pq_sendint64(&buf, snap->xmax);
646  for (i = 0; i < snap->nxip; i++)
647  pq_sendint64(&buf, snap->xip[i]);
649 }
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:359
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:329
txid xmin
Definition: txid.c:67
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:379
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:251
static char * buf
Definition: pg_test_fsync.c:66
unsigned int uint32
Definition: c.h:268
void pq_sendint(StringInfo buf, int i, int b)
Definition: pqformat.c:236
int i
uint32 nxip
Definition: txid.c:66
txid xmax
Definition: txid.c:68
void pq_sendint64(StringInfo buf, int64 i)
Definition: pqformat.c:271
Datum txid_snapshot_xip ( PG_FUNCTION_ARGS  )

Definition at line 697 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.

698 {
699  FuncCallContext *fctx;
700  TxidSnapshot *snap;
701  txid value;
702 
703  /* on first call initialize snap_state and get copy of snapshot */
704  if (SRF_IS_FIRSTCALL())
705  {
707 
708  fctx = SRF_FIRSTCALL_INIT();
709 
710  /* make a copy of user snapshot */
712  memcpy(snap, arg, VARSIZE(arg));
713 
714  fctx->user_fctx = snap;
715  }
716 
717  /* return values one-by-one */
718  fctx = SRF_PERCALL_SETUP();
719  snap = fctx->user_fctx;
720  if (fctx->call_cntr < snap->nxip)
721  {
722  value = snap->xip[fctx->call_cntr];
723  SRF_RETURN_NEXT(fctx, Int64GetDatum(value));
724  }
725  else
726  {
727  SRF_RETURN_DONE(fctx);
728  }
729 }
uint64 call_cntr
Definition: funcapi.h:65
txid xip[FLEXIBLE_ARRAY_MEMBER]
Definition: txid.c:70
#define VARSIZE(PTR)
Definition: postgres.h:304
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
uint64 txid
Definition: txid.c:42
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:251
static struct @121 value
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
void * user_fctx
Definition: funcapi.h:90
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
uint32 nxip
Definition: txid.c:66
void * arg
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
Datum txid_snapshot_xmax ( PG_FUNCTION_ARGS  )

Definition at line 684 of file txid.c.

References PG_GETARG_VARLENA_P, PG_RETURN_INT64, and TxidSnapshot::xmax.

685 {
687 
688  PG_RETURN_INT64(snap->xmax);
689 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:251
txid xmax
Definition: txid.c:68
Datum txid_snapshot_xmin ( PG_FUNCTION_ARGS  )

Definition at line 671 of file txid.c.

References PG_GETARG_VARLENA_P, PG_RETURN_INT64, and TxidSnapshot::xmin.

672 {
674 
675  PG_RETURN_INT64(snap->xmin);
676 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
txid xmin
Definition: txid.c:67
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:251
Datum txid_status ( PG_FUNCTION_ARGS  )

Definition at line 742 of file txid.c.

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

743 {
744  const char *status;
745  uint64 xid_with_epoch = PG_GETARG_INT64(0);
746  TransactionId xid;
747 
748  /*
749  * We must protect against concurrent truncation of clog entries to avoid
750  * an I/O error on SLRU lookup.
751  */
752  LWLockAcquire(CLogTruncationLock, LW_SHARED);
753  if (TransactionIdInRecentPast(xid_with_epoch, &xid))
754  {
756 
758  status = gettext_noop("in progress");
759  else if (TransactionIdDidCommit(xid))
760  status = gettext_noop("committed");
761  else if (TransactionIdDidAbort(xid))
762  status = gettext_noop("aborted");
763  else
764  {
765  /*
766  * The xact is not marked as either committed or aborted in clog.
767  *
768  * It could be a transaction that ended without updating clog or
769  * writing an abort record due to a crash. We can safely assume
770  * it's aborted if it isn't committed and is older than our
771  * snapshot xmin.
772  *
773  * Otherwise it must be in-progress (or have been at the time we
774  * checked commit/abort status).
775  */
776  if (TransactionIdPrecedes(xid, GetActiveSnapshot()->xmin))
777  status = gettext_noop("aborted");
778  else
779  status = gettext_noop("in progress");
780  }
781  }
782  else
783  {
784  status = NULL;
785  }
786  LWLockRelease(CLogTruncationLock);
787 
788  if (status == NULL)
789  PG_RETURN_NULL();
790  else
792 }
uint32 TransactionId
Definition: c.h:397
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:773
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:839
#define gettext_noop(x)
Definition: c.h:139
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static bool TransactionIdInRecentPast(uint64 xid_with_epoch, TransactionId *extracted_xid)
Definition: txid.c:111
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:330
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum txid_visible_in_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 657 of file txid.c.

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

658 {
661 
662  PG_RETURN_BOOL(is_visible_txid(value, snap));
663 }
uint64 txid
Definition: txid.c:42
#define PG_GETARG_VARLENA_P(n)
Definition: fmgr.h:251
static struct @121 value
static bool is_visible_txid(txid value, const TxidSnapshot *snap)
Definition: txid.c:238
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247