PostgreSQL Source Code git master
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 "varatt.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 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 238 of file xid8funcs.c.

239{
240 pg_snapshot *snap = (pg_snapshot *) buf->data;
241
242 /* do this before possible realloc */
243 snap->nxip++;
244
245 appendBinaryStringInfo(buf, &fxid, sizeof(fxid));
246}
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: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 249 of file xid8funcs.c.

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

References buf, pfree(), and SET_VARSIZE().

Referenced by parse_snapshot().

◆ buf_init()

static StringInfo buf_init ( FullTransactionId  xmin,
FullTransactionId  xmax 
)
static

Definition at line 223 of file xid8funcs.c.

224{
225 pg_snapshot snap;
227
228 snap.xmin = xmin;
229 snap.xmax = xmax;
230 snap.nxip = 0;
231
234 return buf;
235}
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72
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 154 of file xid8funcs.c.

155{
156 FullTransactionId a = *(const FullTransactionId *) aa;
157 FullTransactionId b = *(const FullTransactionId *) bb;
158
160 return -1;
162 return 1;
163 return 0;
164}
int b
Definition: isn.c:74
int a
Definition: isn.c:73
#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 188 of file xid8funcs.c.

189{
191 return true;
192 else if (!FullTransactionIdPrecedes(value, snap->xmax))
193 return false;
194#ifdef USE_BSEARCH_IF_NXIP_GREATER
195 else if (snap->nxip > USE_BSEARCH_IF_NXIP_GREATER)
196 {
197 void *res;
198
199 res = bsearch(&value, snap->xip, snap->nxip, sizeof(FullTransactionId),
200 cmp_fxid);
201 /* if found, transaction is still in progress */
202 return (res) ? false : true;
203 }
204#endif
205 else
206 {
207 uint32 i;
208
209 for (i = 0; i < snap->nxip; i++)
210 {
211 if (FullTransactionIdEquals(value, snap->xip[i]))
212 return false;
213 }
214 return true;
215 }
216}
uint32_t uint32
Definition: c.h:541
static struct @171 value
return false
Definition: isn.c:135
int i
Definition: isn.c:77
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:154
#define USE_BSEARCH_IF_NXIP_GREATER
Definition: xid8funcs.c:49

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

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

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

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

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

336{
337 /*
338 * Must prevent during recovery because if an xid is not assigned we try
339 * to assign one, which would fail. Programs already rely on this function
340 * to always return a valid current xid, so we should not change this to
341 * return NULL or similar invalid xid.
342 */
343 PreventCommandDuringRecovery("pg_current_xact_id()");
344
346}
void PreventCommandDuringRecovery(const char *cmdname)
Definition: utility.c:443
FullTransactionId GetTopFullTransactionId(void)
Definition: xact.c:484
#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 353 of file xid8funcs.c.

354{
356
357 if (!FullTransactionIdIsValid(topfxid))
359
361}
#define PG_RETURN_NULL()
Definition: fmgr.h:345
FullTransactionId GetTopFullTransactionIdIfAny(void)
Definition: xact.c:500

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

◆ pg_snapshot_in()

Datum pg_snapshot_in ( PG_FUNCTION_ARGS  )

Definition at line 421 of file xid8funcs.c.

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

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

◆ pg_snapshot_out()

Datum pg_snapshot_out ( PG_FUNCTION_ARGS  )

Definition at line 437 of file xid8funcs.c.

438{
441 uint32 i;
442
444
449
450 for (i = 0; i < snap->nxip; i++)
451 {
452 if (i > 0)
456 }
457
459}
#define UINT64_FORMAT
Definition: c.h:560
#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 469 of file xid8funcs.c.

470{
472 pg_snapshot *snap;
474 int nxip;
475 int i;
478
479 /* load and validate nxip */
480 nxip = pq_getmsgint(buf, 4);
481 if (nxip < 0 || nxip > PG_SNAPSHOT_MAX_NXIP)
482 goto bad_format;
483
486 if (!FullTransactionIdIsValid(xmin) ||
488 FullTransactionIdPrecedes(xmax, xmin))
489 goto bad_format;
490
491 snap = palloc(PG_SNAPSHOT_SIZE(nxip));
492 snap->xmin = xmin;
493 snap->xmax = xmax;
494
495 for (i = 0; i < nxip; i++)
496 {
499
500 if (FullTransactionIdPrecedes(cur, last) ||
503 goto bad_format;
504
505 /* skip duplicate xips */
506 if (FullTransactionIdEquals(cur, last))
507 {
508 i--;
509 nxip--;
510 continue;
511 }
512
513 snap->xip[i] = cur;
514 last = cur;
515 }
516 snap->nxip = nxip;
517 SET_VARSIZE(snap, PG_SNAPSHOT_SIZE(nxip));
518 PG_RETURN_POINTER(snap);
519
520bad_format:
522 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
523 errmsg("invalid external pg_snapshot data")));
524 PG_RETURN_POINTER(NULL); /* keep compiler quiet */
525}
uint64_t uint64
Definition: c.h:542
#define ereport(elevel,...)
Definition: elog.h:150
#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
struct StringInfoData * StringInfo
Definition: string.h:15
#define PG_SNAPSHOT_MAX_NXIP
Definition: xid8funcs.c:73

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

536{
539 uint32 i;
540
542 pq_sendint32(&buf, snap->nxip);
545 for (i = 0; i < snap->nxip; i++)
548}
int64_t int64
Definition: c.h:538
#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 596 of file xid8funcs.c.

597{
598 FuncCallContext *fctx;
599 pg_snapshot *snap;
601
602 /* on first call initialize fctx and get copy of snapshot */
603 if (SRF_IS_FIRSTCALL())
604 {
606
607 fctx = SRF_FIRSTCALL_INIT();
608
609 /* make a copy of user snapshot */
611 memcpy(snap, arg, VARSIZE(arg));
612
613 fctx->user_fctx = snap;
614 }
615
616 /* return values one-by-one */
617 fctx = SRF_PERCALL_SETUP();
618 snap = fctx->user_fctx;
619 if (fctx->call_cntr < snap->nxip)
620 {
621 value = snap->xip[fctx->call_cntr];
623 }
624 else
625 {
626 SRF_RETURN_DONE(fctx);
627 }
628}
#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:1229
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
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298
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 583 of file xid8funcs.c.

584{
586
588}

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

571{
573
575}

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

557{
560
562}
#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:188

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

642{
643 const char *status;
645 TransactionId xid;
646
647 /*
648 * We must protect against concurrent truncation of clog entries to avoid
649 * an I/O error on SLRU lookup.
650 */
651 LWLockAcquire(XactTruncationLock, LW_SHARED);
652 if (TransactionIdInRecentPast(fxid, &xid))
653 {
655
656 /*
657 * Like when doing visibility checks on a row, check whether the
658 * transaction is still in progress before looking into the CLOG.
659 * Otherwise we would incorrectly return "committed" for a transaction
660 * that is committing and has already updated the CLOG, but hasn't
661 * removed its XID from the proc array yet. (See comment on that race
662 * condition at the top of heapam_visibility.c)
663 */
665 status = "in progress";
666 else if (TransactionIdDidCommit(xid))
667 status = "committed";
668 else
669 {
670 /* it must have aborted or crashed */
671 status = "aborted";
672 }
673 }
674 else
675 {
676 status = NULL;
677 }
678 LWLockRelease(XactTruncationLock);
679
680 if (status == NULL)
682 else
684}
uint32 TransactionId
Definition: c.h:660
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
Assert(PointerIsAligned(start, uint64))
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894
@ LW_SHARED
Definition: lwlock.h:113
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:181
static bool TransactionIdInRecentPast(FullTransactionId fxid, TransactionId *extracted_xid)
Definition: xid8funcs.c:98

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

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

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