PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
xid8funcs.c File Reference
#include "postgres.h"
#include "access/transam.h"
#include "access/xact.h"
#include "funcapi.h"
#include "lib/qunique.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "storage/lwlock.h"
#include "storage/procarray.h"
#include "storage/procnumber.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

 StaticAssertDecl (MAX_BACKENDS *2<=PG_SNAPSHOT_MAX_NXIP, "possible overflow in pg_current_snapshot()")
 
static bool TransactionIdInRecentPast (FullTransactionId fxid, TransactionId *extracted_xid)
 
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, Node *escontext)
 
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 72 of file xid8funcs.c.

◆ PG_SNAPSHOT_SIZE

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

Definition at line 70 of file xid8funcs.c.

◆ USE_BSEARCH_IF_NXIP_GREATER

#define USE_BSEARCH_IF_NXIP_GREATER   30

Definition at line 48 of file xid8funcs.c.

Function Documentation

◆ buf_add_txid()

static void buf_add_txid ( StringInfo  buf,
FullTransactionId  fxid 
)
static

Definition at line 237 of file xid8funcs.c.

238{
239 pg_snapshot *snap = (pg_snapshot *) buf->data;
240
241 /* do this before possible realloc */
242 snap->nxip++;
243
244 appendBinaryStringInfo(buf, &fxid, sizeof(fxid));
245}
static char * buf
Definition: pg_test_fsync.c:72
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
uint32 nxip
Definition: xid8funcs.c:63

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

Referenced by parse_snapshot().

◆ buf_finalize()

static pg_snapshot * buf_finalize ( StringInfo  buf)
static

Definition at line 248 of file xid8funcs.c.

249{
250 pg_snapshot *snap = (pg_snapshot *) buf->data;
251
252 SET_VARSIZE(snap, buf->len);
253
254 /* buf is not needed anymore */
255 buf->data = NULL;
256 pfree(buf);
257
258 return snap;
259}
void pfree(void *pointer)
Definition: mcxt.c:1524
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References buf, pfree(), and SET_VARSIZE.

Referenced by parse_snapshot().

◆ buf_init()

static StringInfo buf_init ( FullTransactionId  xmin,
FullTransactionId  xmax 
)
static

Definition at line 222 of file xid8funcs.c.

223{
224 pg_snapshot snap;
226
227 snap.xmin = xmin;
228 snap.xmax = xmax;
229 snap.nxip = 0;
230
233 return buf;
234}
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72
FullTransactionId xmax
Definition: xid8funcs.c:65
FullTransactionId xmin
Definition: xid8funcs.c:64
#define PG_SNAPSHOT_SIZE(nxip)
Definition: xid8funcs.c:70

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 153 of file xid8funcs.c.

154{
155 FullTransactionId a = *(const FullTransactionId *) aa;
156 FullTransactionId b = *(const FullTransactionId *) bb;
157
159 return -1;
161 return 1;
162 return 0;
163}
int b
Definition: isn.c:71
int a
Definition: isn.c:70
#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 187 of file xid8funcs.c.

188{
190 return true;
191 else if (!FullTransactionIdPrecedes(value, snap->xmax))
192 return false;
193#ifdef USE_BSEARCH_IF_NXIP_GREATER
194 else if (snap->nxip > USE_BSEARCH_IF_NXIP_GREATER)
195 {
196 void *res;
197
198 res = bsearch(&value, snap->xip, snap->nxip, sizeof(FullTransactionId),
199 cmp_fxid);
200 /* if found, transaction is still in progress */
201 return (res) ? false : true;
202 }
203#endif
204 else
205 {
206 uint32 i;
207
208 for (i = 0; i < snap->nxip; i++)
209 {
210 if (FullTransactionIdEquals(value, snap->xip[i]))
211 return false;
212 }
213 return true;
214 }
215}
uint32_t uint32
Definition: c.h:502
static struct @165 value
return false
Definition: isn.c:132
int i
Definition: isn.c:74
FullTransactionId xip[FLEXIBLE_ARRAY_MEMBER]
Definition: xid8funcs.c:67
#define FullTransactionIdEquals(a, b)
Definition: transam.h:50
static int cmp_fxid(const void *aa, const void *bb)
Definition: xid8funcs.c:153
#define USE_BSEARCH_IF_NXIP_GREATER
Definition: xid8funcs.c:48

References cmp_fxid(), false, FullTransactionIdEquals, FullTransactionIdPrecedes, i, pg_snapshot::nxip, 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,
Node escontext 
)
static

Definition at line 265 of file xid8funcs.c.

266{
271 const char *str_start = str;
272 char *endp;
274
275 xmin = FullTransactionIdFromU64(strtou64(str, &endp, 10));
276 if (*endp != ':')
277 goto bad_format;
278 str = endp + 1;
279
280 xmax = FullTransactionIdFromU64(strtou64(str, &endp, 10));
281 if (*endp != ':')
282 goto bad_format;
283 str = endp + 1;
284
285 /* it should look sane */
286 if (!FullTransactionIdIsValid(xmin) ||
288 FullTransactionIdPrecedes(xmax, xmin))
289 goto bad_format;
290
291 /* allocate buffer */
292 buf = buf_init(xmin, xmax);
293
294 /* loop over values */
295 while (*str != '\0')
296 {
297 /* read next value */
298 val = FullTransactionIdFromU64(strtou64(str, &endp, 10));
299 str = endp;
300
301 /* require the input to be in order */
302 if (FullTransactionIdPrecedes(val, xmin) ||
305 goto bad_format;
306
307 /* skip duplicates */
308 if (!FullTransactionIdEquals(val, last_val))
310 last_val = val;
311
312 if (*str == ',')
313 str++;
314 else if (*str != '\0')
315 goto bad_format;
316 }
317
318 return buf_finalize(buf);
319
320bad_format:
321 ereturn(escontext, NULL,
322 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
323 errmsg("invalid input syntax for type %s: \"%s\"",
324 "pg_snapshot", str_start)));
325}
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
const char * str
long val
Definition: informix.c:689
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 pg_snapshot * buf_finalize(StringInfo buf)
Definition: xid8funcs.c:248
static StringInfo buf_init(FullTransactionId xmin, FullTransactionId xmax)
Definition: xid8funcs.c:222
static void buf_add_txid(StringInfo buf, FullTransactionId fxid)
Definition: xid8funcs.c:237

References buf, buf_add_txid(), buf_finalize(), buf_init(), ereturn, errcode(), errmsg(), FullTransactionIdEquals, FullTransactionIdFollowsOrEquals, FullTransactionIdFromU64(), FullTransactionIdIsValid, FullTransactionIdPrecedes, InvalidFullTransactionId, str, and val.

Referenced by pg_snapshot_in().

◆ pg_current_snapshot()

Datum pg_current_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 370 of file xid8funcs.c.

371{
372 pg_snapshot *snap;
373 uint32 nxip,
374 i;
377
379 if (cur == NULL)
380 elog(ERROR, "no active snapshot set");
381
382 /* allocate */
383 nxip = cur->xcnt;
384 snap = palloc(PG_SNAPSHOT_SIZE(nxip));
385
386 /*
387 * Fill. This is the current backend's active snapshot, so MyProc->xmin
388 * is <= all these XIDs. As long as that remains so, oldestXid can't
389 * advance past any of these XIDs. Hence, these XIDs remain allowable
390 * relative to next_fxid.
391 */
392 snap->xmin = FullTransactionIdFromAllowableAt(next_fxid, cur->xmin);
393 snap->xmax = FullTransactionIdFromAllowableAt(next_fxid, cur->xmax);
394 snap->nxip = nxip;
395 for (i = 0; i < nxip; i++)
396 snap->xip[i] =
397 FullTransactionIdFromAllowableAt(next_fxid, cur->xip[i]);
398
399 /*
400 * We want them guaranteed to be in ascending order. This also removes
401 * any duplicate xids. Normally, an XID can only be assigned to one
402 * backend, but when preparing a transaction for two-phase commit, there
403 * is a transient state when both the original backend and the dummy
404 * PGPROC entry reserved for the prepared transaction hold the same XID.
405 */
406 sort_snapshot(snap);
407
408 /* set size after sorting, because it may have removed duplicate xips */
409 SET_VARSIZE(snap, PG_SNAPSHOT_SIZE(snap->nxip));
410
411 PG_RETURN_POINTER(snap);
412}
struct cursor * cur
Definition: ecpg.c:29
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
void * palloc(Size size)
Definition: mcxt.c:1317
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:787
static FullTransactionId FullTransactionIdFromAllowableAt(FullTransactionId nextFullXid, TransactionId xid)
Definition: transam.h:381
FullTransactionId ReadNextFullTransactionId(void)
Definition: varsup.c:288
static void sort_snapshot(pg_snapshot *snap)
Definition: xid8funcs.c:173

References cur, elog, ERROR, FullTransactionIdFromAllowableAt(), GetActiveSnapshot(), i, pg_snapshot::nxip, palloc(), PG_RETURN_POINTER, PG_SNAPSHOT_SIZE, ReadNextFullTransactionId(), SET_VARSIZE, sort_snapshot(), 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 334 of file xid8funcs.c.

335{
336 /*
337 * Must prevent during recovery because if an xid is not assigned we try
338 * to assign one, which would fail. Programs already rely on this function
339 * to always return a valid current xid, so we should not change this to
340 * return NULL or similar invalid xid.
341 */
342 PreventCommandDuringRecovery("pg_current_xact_id()");
343
345}
void PreventCommandDuringRecovery(const char *cmdname)
Definition: utility.c:441
FullTransactionId GetTopFullTransactionId(void)
Definition: xact.c:483
#define PG_RETURN_FULLTRANSACTIONID(X)
Definition: xid8.h:30

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 352 of file xid8funcs.c.

353{
355
356 if (!FullTransactionIdIsValid(topfxid))
358
360}
#define PG_RETURN_NULL()
Definition: fmgr.h:345
FullTransactionId GetTopFullTransactionIdIfAny(void)
Definition: xact.c:499

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

◆ pg_snapshot_in()

Datum pg_snapshot_in ( PG_FUNCTION_ARGS  )

Definition at line 420 of file xid8funcs.c.

421{
422 char *str = PG_GETARG_CSTRING(0);
423 pg_snapshot *snap;
424
425 snap = parse_snapshot(str, fcinfo->context);
426
427 PG_RETURN_POINTER(snap);
428}
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
static pg_snapshot * parse_snapshot(const char *str, Node *escontext)
Definition: xid8funcs.c:265

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

◆ pg_snapshot_out()

Datum pg_snapshot_out ( PG_FUNCTION_ARGS  )

Definition at line 436 of file xid8funcs.c.

437{
440 uint32 i;
441
443
448
449 for (i = 0; i < snap->nxip; i++)
450 {
451 if (i > 0)
455 }
456
458}
#define UINT64_FORMAT
Definition: c.h:521
#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:145
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
#define U64FromFullTransactionId(x)
Definition: transam.h:49

References appendStringInfo(), appendStringInfoChar(), i, initStringInfo(), pg_snapshot::nxip, PG_GETARG_VARLENA_P, PG_RETURN_CSTRING, 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 468 of file xid8funcs.c.

469{
471 pg_snapshot *snap;
473 int nxip;
474 int i;
477
478 /* load and validate nxip */
479 nxip = pq_getmsgint(buf, 4);
480 if (nxip < 0 || nxip > PG_SNAPSHOT_MAX_NXIP)
481 goto bad_format;
482
485 if (!FullTransactionIdIsValid(xmin) ||
487 FullTransactionIdPrecedes(xmax, xmin))
488 goto bad_format;
489
490 snap = palloc(PG_SNAPSHOT_SIZE(nxip));
491 snap->xmin = xmin;
492 snap->xmax = xmax;
493
494 for (i = 0; i < nxip; i++)
495 {
498
499 if (FullTransactionIdPrecedes(cur, last) ||
502 goto bad_format;
503
504 /* skip duplicate xips */
505 if (FullTransactionIdEquals(cur, last))
506 {
507 i--;
508 nxip--;
509 continue;
510 }
511
512 snap->xip[i] = cur;
513 last = cur;
514 }
515 snap->nxip = nxip;
516 SET_VARSIZE(snap, PG_SNAPSHOT_SIZE(nxip));
517 PG_RETURN_POINTER(snap);
518
519bad_format:
521 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
522 errmsg("invalid external pg_snapshot data")));
523 PG_RETURN_POINTER(NULL); /* keep compiler quiet */
524}
uint64_t uint64
Definition: c.h:503
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
StringInfoData * StringInfo
Definition: stringinfo.h:54
#define PG_SNAPSHOT_MAX_NXIP
Definition: xid8funcs.c:72

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 534 of file xid8funcs.c.

535{
538 uint32 i;
539
541 pq_sendint32(&buf, snap->nxip);
544 for (i = 0; i < snap->nxip; i++)
547}
int64_t int64
Definition: c.h:499
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152

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 595 of file xid8funcs.c.

596{
597 FuncCallContext *fctx;
598 pg_snapshot *snap;
600
601 /* on first call initialize fctx and get copy of snapshot */
602 if (SRF_IS_FIRSTCALL())
603 {
605
606 fctx = SRF_FIRSTCALL_INIT();
607
608 /* make a copy of user snapshot */
610 memcpy(snap, arg, VARSIZE(arg));
611
612 fctx->user_fctx = snap;
613 }
614
615 /* return values one-by-one */
616 fctx = SRF_PERCALL_SETUP();
617 snap = fctx->user_fctx;
618 if (fctx->call_cntr < snap->nxip)
619 {
620 value = snap->xip[fctx->call_cntr];
622 }
623 else
624 {
625 SRF_RETURN_DONE(fctx);
626 }
627}
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
void * arg
void * user_fctx
Definition: funcapi.h:82
uint64 call_cntr
Definition: funcapi.h:65
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
#define VARSIZE(PTR)
Definition: varatt.h:279
static Datum FullTransactionIdGetDatum(FullTransactionId X)
Definition: xid8.h:24

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 582 of file xid8funcs.c.

583{
585
587}

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 569 of file xid8funcs.c.

570{
572
574}

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 555 of file xid8funcs.c.

556{
559
561}
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define PG_GETARG_FULLTRANSACTIONID(X)
Definition: xid8.h:29
static bool is_visible_fxid(FullTransactionId value, const pg_snapshot *snap)
Definition: xid8funcs.c:187

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 640 of file xid8funcs.c.

641{
642 const char *status;
644 TransactionId xid;
645
646 /*
647 * We must protect against concurrent truncation of clog entries to avoid
648 * an I/O error on SLRU lookup.
649 */
650 LWLockAcquire(XactTruncationLock, LW_SHARED);
651 if (TransactionIdInRecentPast(fxid, &xid))
652 {
654
655 /*
656 * Like when doing visibility checks on a row, check whether the
657 * transaction is still in progress before looking into the CLOG.
658 * Otherwise we would incorrectly return "committed" for a transaction
659 * that is committing and has already updated the CLOG, but hasn't
660 * removed its XID from the proc array yet. (See comment on that race
661 * condition at the top of heapam_visibility.c)
662 */
664 status = "in progress";
665 else if (TransactionIdDidCommit(xid))
666 status = "committed";
667 else
668 {
669 /* it must have aborted or crashed */
670 status = "aborted";
671 }
672 }
673 else
674 {
675 status = NULL;
676 }
677 LWLockRelease(XactTruncationLock);
678
679 if (status == NULL)
681 else
683}
uint32 TransactionId
Definition: c.h:623
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
Assert(PointerIsAligned(start, uint64))
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1179
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1899
@ LW_SHARED
Definition: lwlock.h:115
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1402
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:126
#define TransactionIdIsValid(xid)
Definition: transam.h:41
text * cstring_to_text(const char *s)
Definition: varlena.c:192
static bool TransactionIdInRecentPast(FullTransactionId fxid, TransactionId *extracted_xid)
Definition: xid8funcs.c:97

References Assert(), cstring_to_text(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PG_GETARG_FULLTRANSACTIONID, PG_RETURN_NULL, PG_RETURN_TEXT_P, TransactionIdDidCommit(), TransactionIdInRecentPast(), TransactionIdIsInProgress(), and TransactionIdIsValid.

◆ sort_snapshot()

static void sort_snapshot ( pg_snapshot snap)
static

Definition at line 173 of file xid8funcs.c.

174{
175 if (snap->nxip > 1)
176 {
177 qsort(snap->xip, snap->nxip, sizeof(FullTransactionId), cmp_fxid);
178 snap->nxip = qunique(snap->xip, snap->nxip, sizeof(FullTransactionId),
179 cmp_fxid);
180 }
181}
#define qsort(a, b, c, d)
Definition: port.h:475
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().

◆ StaticAssertDecl()

StaticAssertDecl ( MAX_BACKENDS *2<=  PG_SNAPSHOT_MAX_NXIP,
"possible overflow in pg_current_snapshot()"   
)

◆ TransactionIdInRecentPast()

static bool TransactionIdInRecentPast ( FullTransactionId  fxid,
TransactionId extracted_xid 
)
static

Definition at line 97 of file xid8funcs.c.

98{
100 FullTransactionId now_fullxid;
101 TransactionId oldest_clog_xid;
102 FullTransactionId oldest_clog_fxid;
103
104 now_fullxid = ReadNextFullTransactionId();
105
106 if (extracted_xid != NULL)
107 *extracted_xid = xid;
108
109 if (!TransactionIdIsValid(xid))
110 return false;
111
112 /* For non-normal transaction IDs, we can ignore the epoch. */
113 if (!TransactionIdIsNormal(xid))
114 return true;
115
116 /* If the transaction ID is in the future, throw an error. */
117 if (!FullTransactionIdPrecedes(fxid, now_fullxid))
119 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
120 errmsg("transaction ID %llu is in the future",
121 (unsigned long long) U64FromFullTransactionId(fxid))));
122
123 /*
124 * TransamVariables->oldestClogXid is protected by XactTruncationLock, but
125 * we don't acquire that lock here. Instead, we require the caller to
126 * acquire it, because the caller is presumably going to look up the
127 * returned XID. If we took and released the lock within this function, a
128 * CLOG truncation could occur before the caller finished with the XID.
129 */
130 Assert(LWLockHeldByMe(XactTruncationLock));
131
132 /*
133 * If fxid is not older than TransamVariables->oldestClogXid, the relevant
134 * CLOG entry is guaranteed to still exist.
135 *
136 * TransamVariables->oldestXid governs allowable XIDs. Usually,
137 * oldestClogXid==oldestXid. It's also possible for oldestClogXid to
138 * follow oldestXid, in which case oldestXid might advance after our
139 * ReadNextFullTransactionId() call. If oldestXid has advanced, that
140 * advancement reinstated the usual oldestClogXid==oldestXid. Whether or
141 * not that happened, oldestClogXid is allowable relative to now_fullxid.
142 */
143 oldest_clog_xid = TransamVariables->oldestClogXid;
144 oldest_clog_fxid =
145 FullTransactionIdFromAllowableAt(now_fullxid, oldest_clog_xid);
146 return !FullTransactionIdPrecedes(fxid, oldest_clog_fxid);
147}
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1967
TransactionId oldestClogXid
Definition: transam.h:253
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
TransamVariablesData * TransamVariables
Definition: varsup.c:34

References Assert(), ereport, errcode(), errmsg(), ERROR, FullTransactionIdFromAllowableAt(), FullTransactionIdPrecedes, LWLockHeldByMe(), TransamVariablesData::oldestClogXid, ReadNextFullTransactionId(), TransactionIdIsNormal, TransactionIdIsValid, TransamVariables, U64FromFullTransactionId, and XidFromFullTransactionId.

Referenced by pg_xact_status().