PostgreSQL Source Code  git master
snapmgr.c File Reference
#include "postgres.h"
#include <sys/stat.h>
#include <unistd.h>
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "datatype/timestamp.h"
#include "lib/pairingheap.h"
#include "miscadmin.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/sinval.h"
#include "storage/sinvaladt.h"
#include "storage/spin.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/old_snapshot.h"
#include "utils/rel.h"
#include "utils/resowner_private.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
Include dependency graph for snapmgr.c:

Go to the source code of this file.

Data Structures

struct  ActiveSnapshotElt
 
struct  ExportedSnapshot
 
struct  SerializedSnapshotData
 

Macros

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"
 

Typedefs

typedef struct ActiveSnapshotElt ActiveSnapshotElt
 
typedef struct ExportedSnapshot ExportedSnapshot
 
typedef struct SerializedSnapshotData SerializedSnapshotData
 

Functions

static int xmin_cmp (const pairingheap_node *a, const pairingheap_node *b, void *arg)
 
static TimestampTz AlignTimestampToMinuteBoundary (TimestampTz ts)
 
static Snapshot CopySnapshot (Snapshot snapshot)
 
static void FreeSnapshot (Snapshot snapshot)
 
static void SnapshotResetXmin (void)
 
Size SnapMgrShmemSize (void)
 
void SnapMgrInit (void)
 
Snapshot GetTransactionSnapshot (void)
 
Snapshot GetLatestSnapshot (void)
 
Snapshot GetOldestSnapshot (void)
 
Snapshot GetCatalogSnapshot (Oid relid)
 
Snapshot GetNonHistoricCatalogSnapshot (Oid relid)
 
void InvalidateCatalogSnapshot (void)
 
void InvalidateCatalogSnapshotConditionally (void)
 
void SnapshotSetCommandId (CommandId curcid)
 
static void SetTransactionSnapshot (Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
 
void PushActiveSnapshot (Snapshot snap)
 
void PushCopiedSnapshot (Snapshot snapshot)
 
void UpdateActiveSnapshotCommandId (void)
 
void PopActiveSnapshot (void)
 
Snapshot GetActiveSnapshot (void)
 
bool ActiveSnapshotSet (void)
 
Snapshot RegisterSnapshot (Snapshot snapshot)
 
Snapshot RegisterSnapshotOnOwner (Snapshot snapshot, ResourceOwner owner)
 
void UnregisterSnapshot (Snapshot snapshot)
 
void UnregisterSnapshotFromOwner (Snapshot snapshot, ResourceOwner owner)
 
void AtSubCommit_Snapshot (int level)
 
void AtSubAbort_Snapshot (int level)
 
void AtEOXact_Snapshot (bool isCommit, bool resetXmin)
 
char * ExportSnapshot (Snapshot snapshot)
 
Datum pg_export_snapshot (PG_FUNCTION_ARGS)
 
static int parseIntFromText (const char *prefix, char **s, const char *filename)
 
static TransactionId parseXidFromText (const char *prefix, char **s, const char *filename)
 
static void parseVxidFromText (const char *prefix, char **s, const char *filename, VirtualTransactionId *vxid)
 
void ImportSnapshot (const char *idstr)
 
bool XactHasExportedSnapshots (void)
 
void DeleteAllExportedSnapshotFiles (void)
 
bool ThereAreNoPriorRegisteredSnapshots (void)
 
TimestampTz GetSnapshotCurrentTimestamp (void)
 
TimestampTz GetOldSnapshotThresholdTimestamp (void)
 
void SetOldSnapshotThresholdTimestamp (TimestampTz ts, TransactionId xlimit)
 
void SnapshotTooOldMagicForTest (void)
 
static bool GetOldSnapshotFromTimeMapping (TimestampTz ts, TransactionId *xlimitp)
 
bool TransactionIdLimitedForOldSnapshots (TransactionId recentXmin, Relation relation, TransactionId *limit_xid, TimestampTz *limit_ts)
 
void MaintainOldSnapshotTimeMapping (TimestampTz whenTaken, TransactionId xmin)
 
void SetupHistoricSnapshot (Snapshot historic_snapshot, HTAB *tuplecids)
 
void TeardownHistoricSnapshot (bool is_error)
 
bool HistoricSnapshotActive (void)
 
HTABHistoricSnapshotGetTupleCids (void)
 
Size EstimateSnapshotSpace (Snapshot snap)
 
void SerializeSnapshot (Snapshot snapshot, char *start_address)
 
Snapshot RestoreSnapshot (char *start_address)
 
void RestoreTransactionSnapshot (Snapshot snapshot, void *source_pgproc)
 
bool XidInMVCCSnapshot (TransactionId xid, Snapshot snapshot)
 

Variables

int old_snapshot_threshold
 
volatile OldSnapshotControlDataoldSnapshotControl
 
static SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC}
 
static SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC}
 
SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC}
 
SnapshotData SnapshotSelfData = {SNAPSHOT_SELF}
 
SnapshotData SnapshotAnyData = {SNAPSHOT_ANY}
 
static Snapshot CurrentSnapshot = NULL
 
static Snapshot SecondarySnapshot = NULL
 
static Snapshot CatalogSnapshot = NULL
 
static Snapshot HistoricSnapshot = NULL
 
TransactionId TransactionXmin = FirstNormalTransactionId
 
TransactionId RecentXmin = FirstNormalTransactionId
 
static HTABtuplecid_data = NULL
 
static ActiveSnapshotEltActiveSnapshot = NULL
 
static ActiveSnapshotEltOldestActiveSnapshot = NULL
 
static pairingheap RegisteredSnapshots = {&xmin_cmp, NULL, NULL}
 
bool FirstSnapshotSet = false
 
static Snapshot FirstXactSnapshot = NULL
 
static ListexportedSnapshots = NIL
 

Macro Definition Documentation

◆ SNAPSHOT_EXPORT_DIR

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"

Definition at line 159 of file snapmgr.c.

Referenced by DeleteAllExportedSnapshotFiles(), ExportSnapshot(), and ImportSnapshot().

Typedef Documentation

◆ ActiveSnapshotElt

◆ ExportedSnapshot

◆ SerializedSnapshotData

Function Documentation

◆ ActiveSnapshotSet()

bool ActiveSnapshotSet ( void  )

Definition at line 798 of file snapmgr.c.

Referenced by _SPI_commit(), _SPI_execute_plan(), BuildCachedPlan(), index_concurrently_build(), OldSnapshotThresholdActive(), pg_plan_query(), PortalRunUtility(), postquel_start(), RevalidateCachedQuery(), and vacuum().

799 {
800  return ActiveSnapshot != NULL;
801 }
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134

◆ AlignTimestampToMinuteBoundary()

static TimestampTz AlignTimestampToMinuteBoundary ( TimestampTz  ts)
static

Definition at line 1621 of file snapmgr.c.

References USECS_PER_MINUTE.

Referenced by GetOldSnapshotFromTimeMapping(), MaintainOldSnapshotTimeMapping(), and TransactionIdLimitedForOldSnapshots().

1622 {
1623  TimestampTz retval = ts + (USECS_PER_MINUTE - 1);
1624 
1625  return retval - (retval % USECS_PER_MINUTE);
1626 }
int64 TimestampTz
Definition: timestamp.h:39
#define USECS_PER_MINUTE
Definition: timestamp.h:93

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1006 of file snapmgr.c.

References ActiveSnapshotElt::as_next, Assert, elog, FirstSnapshotSet, InvalidateCatalogSnapshot(), lfirst, MyProc, NIL, pairingheap_is_empty, pairingheap_remove(), pairingheap_reset, SnapshotData::ph_node, SnapshotData::regd_count, ExportedSnapshot::snapfile, ExportedSnapshot::snapshot, SnapshotResetXmin(), WARNING, and PGPROC::xmin.

Referenced by CleanupTransaction(), CommitTransaction(), OldSnapshotThresholdActive(), and PrepareTransaction().

1007 {
1008  /*
1009  * In transaction-snapshot mode we must release our privately-managed
1010  * reference to the transaction snapshot. We must remove it from
1011  * RegisteredSnapshots to keep the check below happy. But we don't bother
1012  * to do FreeSnapshot, for two reasons: the memory will go away with
1013  * TopTransactionContext anyway, and if someone has left the snapshot
1014  * stacked as active, we don't want the code below to be chasing through a
1015  * dangling pointer.
1016  */
1017  if (FirstXactSnapshot != NULL)
1018  {
1022  }
1023  FirstXactSnapshot = NULL;
1024 
1025  /*
1026  * If we exported any snapshots, clean them up.
1027  */
1028  if (exportedSnapshots != NIL)
1029  {
1030  ListCell *lc;
1031 
1032  /*
1033  * Get rid of the files. Unlink failure is only a WARNING because (1)
1034  * it's too late to abort the transaction, and (2) leaving a leaked
1035  * file around has little real consequence anyway.
1036  *
1037  * We also need to remove the snapshots from RegisteredSnapshots to
1038  * prevent a warning below.
1039  *
1040  * As with the FirstXactSnapshot, we don't need to free resources of
1041  * the snapshot itself as it will go away with the memory context.
1042  */
1043  foreach(lc, exportedSnapshots)
1044  {
1045  ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1046 
1047  if (unlink(esnap->snapfile))
1048  elog(WARNING, "could not unlink file \"%s\": %m",
1049  esnap->snapfile);
1050 
1052  &esnap->snapshot->ph_node);
1053  }
1054 
1056  }
1057 
1058  /* Drop catalog snapshot if any */
1060 
1061  /* On commit, complain about leftover snapshots */
1062  if (isCommit)
1063  {
1064  ActiveSnapshotElt *active;
1065 
1067  elog(WARNING, "registered snapshots seem to remain after cleanup");
1068 
1069  /* complain about unpopped active snapshots */
1070  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1071  elog(WARNING, "snapshot %p still active", active);
1072  }
1073 
1074  /*
1075  * And reset our state. We don't need to free the memory explicitly --
1076  * it'll go away with TopTransactionContext.
1077  */
1078  ActiveSnapshot = NULL;
1079  OldestActiveSnapshot = NULL;
1081 
1082  CurrentSnapshot = NULL;
1083  SecondarySnapshot = NULL;
1084 
1085  FirstSnapshotSet = false;
1086 
1087  /*
1088  * During normal commit processing, we call ProcArrayEndTransaction() to
1089  * reset the MyProc->xmin. That call happens prior to the call to
1090  * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1091  */
1092  if (resetXmin)
1094 
1095  Assert(resetXmin || MyProc->xmin == 0);
1096 }
#define NIL
Definition: pg_list.h:65
#define pairingheap_reset(h)
Definition: pairingheap.h:93
PGPROC * MyProc
Definition: proc.c:67
static void SnapshotResetXmin(void)
Definition: snapmgr.c:925
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:156
uint32 regd_count
Definition: snapshot.h:205
static Snapshot CurrentSnapshot
Definition: snapmgr.c:102
static List * exportedSnapshots
Definition: snapmgr.c:169
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
bool FirstSnapshotSet
Definition: snapmgr.c:149
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:137
TransactionId xmin
Definition: proc.h:129
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:130
Snapshot snapshot
Definition: snapmgr.c:165
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134
char * snapfile
Definition: snapmgr.c:164
#define WARNING
Definition: elog.h:40
pairingheap_node ph_node
Definition: snapshot.h:206
#define Assert(condition)
Definition: c.h:745
#define lfirst(lc)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:214
static Snapshot SecondarySnapshot
Definition: snapmgr.c:103
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170

◆ AtSubAbort_Snapshot()

void AtSubAbort_Snapshot ( int  level)

Definition at line 970 of file snapmgr.c.

References SnapshotData::active_count, ActiveSnapshotElt::as_level, ActiveSnapshotElt::as_next, ActiveSnapshotElt::as_snap, Assert, FreeSnapshot(), next, pfree(), SnapshotData::regd_count, and SnapshotResetXmin().

Referenced by AbortSubTransaction(), and OldSnapshotThresholdActive().

971 {
972  /* Forget the active snapshots set by this subtransaction */
973  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
974  {
976 
977  next = ActiveSnapshot->as_next;
978 
979  /*
980  * Decrement the snapshot's active count. If it's still registered or
981  * marked as active by an outer subtransaction, we can't free it yet.
982  */
985 
986  if (ActiveSnapshot->as_snap->active_count == 0 &&
989 
990  /* and free the stack element */
992 
994  if (ActiveSnapshot == NULL)
995  OldestActiveSnapshot = NULL;
996  }
997 
999 }
Snapshot as_snap
Definition: snapmgr.c:128
static int32 next
Definition: blutils.c:219
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
static void SnapshotResetXmin(void)
Definition: snapmgr.c:925
uint32 regd_count
Definition: snapshot.h:205
void pfree(void *pointer)
Definition: mcxt.c:1057
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:137
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:130
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134
#define Assert(condition)
Definition: c.h:745
uint32 active_count
Definition: snapshot.h:204

◆ AtSubCommit_Snapshot()

void AtSubCommit_Snapshot ( int  level)

Definition at line 949 of file snapmgr.c.

References ActiveSnapshotElt::as_level, and ActiveSnapshotElt::as_next.

Referenced by CommitSubTransaction(), and OldSnapshotThresholdActive().

950 {
951  ActiveSnapshotElt *active;
952 
953  /*
954  * Relabel the active snapshots set in this subtransaction as though they
955  * are owned by the parent subxact.
956  */
957  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
958  {
959  if (active->as_level < level)
960  break;
961  active->as_level = level - 1;
962  }
963 }
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:130
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134

◆ CopySnapshot()

static Snapshot CopySnapshot ( Snapshot  snapshot)
static

Definition at line 606 of file snapmgr.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, InvalidSnapshot, MemoryContextAlloc(), SnapshotData::regd_count, SnapshotData::snapXactCompletionCount, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TopTransactionContext, SnapshotData::xcnt, and SnapshotData::xip.

Referenced by ExportSnapshot(), GetTransactionSnapshot(), PushActiveSnapshot(), PushCopiedSnapshot(), RegisterSnapshotOnOwner(), and SetTransactionSnapshot().

607 {
608  Snapshot newsnap;
609  Size subxipoff;
610  Size size;
611 
612  Assert(snapshot != InvalidSnapshot);
613 
614  /* We allocate any XID arrays needed in the same palloc block. */
615  size = subxipoff = sizeof(SnapshotData) +
616  snapshot->xcnt * sizeof(TransactionId);
617  if (snapshot->subxcnt > 0)
618  size += snapshot->subxcnt * sizeof(TransactionId);
619 
621  memcpy(newsnap, snapshot, sizeof(SnapshotData));
622 
623  newsnap->regd_count = 0;
624  newsnap->active_count = 0;
625  newsnap->copied = true;
626  newsnap->snapXactCompletionCount = 0;
627 
628  /* setup XID array */
629  if (snapshot->xcnt > 0)
630  {
631  newsnap->xip = (TransactionId *) (newsnap + 1);
632  memcpy(newsnap->xip, snapshot->xip,
633  snapshot->xcnt * sizeof(TransactionId));
634  }
635  else
636  newsnap->xip = NULL;
637 
638  /*
639  * Setup subXID array. Don't bother to copy it if it had overflowed,
640  * though, because it's not used anywhere in that case. Except if it's a
641  * snapshot taken during recovery; all the top-level XIDs are in subxip as
642  * well in that case, so we mustn't lose them.
643  */
644  if (snapshot->subxcnt > 0 &&
645  (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
646  {
647  newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
648  memcpy(newsnap->subxip, snapshot->subxip,
649  snapshot->subxcnt * sizeof(TransactionId));
650  }
651  else
652  newsnap->subxip = NULL;
653 
654  return newsnap;
655 }
uint64 snapXactCompletionCount
Definition: snapshot.h:216
MemoryContext TopTransactionContext
Definition: mcxt.c:49
uint32 TransactionId
Definition: c.h:520
bool copied
Definition: snapshot.h:185
bool suboverflowed
Definition: snapshot.h:182
struct SnapshotData * Snapshot
Definition: snapshot.h:121
uint32 regd_count
Definition: snapshot.h:205
struct SnapshotData SnapshotData
TransactionId * xip
Definition: snapshot.h:168
#define InvalidSnapshot
Definition: snapshot.h:123
#define Assert(condition)
Definition: c.h:745
bool takenDuringRecovery
Definition: snapshot.h:184
size_t Size
Definition: c.h:473
uint32 xcnt
Definition: snapshot.h:169
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
TransactionId * subxip
Definition: snapshot.h:180
uint32 active_count
Definition: snapshot.h:204
int32 subxcnt
Definition: snapshot.h:181

◆ DeleteAllExportedSnapshotFiles()

void DeleteAllExportedSnapshotFiles ( void  )

Definition at line 1565 of file snapmgr.c.

References AllocateDir(), buf, dirent::d_name, ereport, errcode_for_file_access(), errmsg(), FreeDir(), LOG, MAXPGPATH, ReadDirExtended(), SNAPSHOT_EXPORT_DIR, and snprintf.

Referenced by OldSnapshotThresholdActive(), and StartupXLOG().

1566 {
1567  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1568  DIR *s_dir;
1569  struct dirent *s_de;
1570 
1571  /*
1572  * Problems in reading the directory, or unlinking files, are reported at
1573  * LOG level. Since we're running in the startup process, ERROR level
1574  * would prevent database start, and it's not important enough for that.
1575  */
1577 
1578  while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1579  {
1580  if (strcmp(s_de->d_name, ".") == 0 ||
1581  strcmp(s_de->d_name, "..") == 0)
1582  continue;
1583 
1584  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1585 
1586  if (unlink(buf) != 0)
1587  ereport(LOG,
1589  errmsg("could not remove file \"%s\": %m", buf)));
1590  }
1591 
1592  FreeDir(s_dir);
1593 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2664
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:159
Definition: dirent.c:25
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:68
int errcode_for_file_access(void)
Definition: elog.c:633
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2583
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:193
int FreeDir(DIR *dir)
Definition: fd.c:2701

◆ EstimateSnapshotSpace()

Size EstimateSnapshotSpace ( Snapshot  snap)

Definition at line 2074 of file snapmgr.c.

References add_size(), Assert, InvalidSnapshot, mul_size(), SNAPSHOT_MVCC, SnapshotData::snapshot_type, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::takenDuringRecovery, and SnapshotData::xcnt.

Referenced by ExecBitmapHeapEstimate(), index_parallelscan_estimate(), index_parallelscan_initialize(), InitializeParallelDSM(), and table_parallelscan_estimate().

2075 {
2076  Size size;
2077 
2078  Assert(snap != InvalidSnapshot);
2080 
2081  /* We allocate any XID arrays needed in the same palloc block. */
2082  size = add_size(sizeof(SerializedSnapshotData),
2083  mul_size(snap->xcnt, sizeof(TransactionId)));
2084  if (snap->subxcnt > 0 &&
2085  (!snap->suboverflowed || snap->takenDuringRecovery))
2086  size = add_size(size,
2087  mul_size(snap->subxcnt, sizeof(TransactionId)));
2088 
2089  return size;
2090 }
uint32 TransactionId
Definition: c.h:520
bool suboverflowed
Definition: snapshot.h:182
SnapshotType snapshot_type
Definition: snapshot.h:144
#define InvalidSnapshot
Definition: snapshot.h:123
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
#define Assert(condition)
Definition: c.h:745
bool takenDuringRecovery
Definition: snapshot.h:184
size_t Size
Definition: c.h:473
uint32 xcnt
Definition: snapshot.h:169
int32 subxcnt
Definition: snapshot.h:181

◆ ExportSnapshot()

char* ExportSnapshot ( Snapshot  snapshot)

Definition at line 1106 of file snapmgr.c.

References AllocateFile(), appendStringInfo(), appendStringInfoString(), PGPROC::backendId, buf, CopySnapshot(), StringInfoData::data, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, FreeFile(), GetMaxSnapshotSubxidCount(), GetTopTransactionIdIfAny(), i, initStringInfo(), IsSubTransaction(), lappend(), StringInfoData::len, list_length(), PGPROC::lxid, MAXPGPATH, MemoryContextSwitchTo(), MyDatabaseId, MyProc, MyProcPid, pairingheap_add(), palloc(), PG_BINARY_W, SnapshotData::ph_node, pstrdup(), SnapshotData::regd_count, ExportedSnapshot::snapfile, ExportedSnapshot::snapshot, SNAPSHOT_EXPORT_DIR, snprintf, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TopTransactionContext, TransactionIdIsValid, TransactionIdPrecedes(), xactGetCommittedChildren(), XactIsoLevel, XactReadOnly, SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by OldSnapshotThresholdActive(), pg_export_snapshot(), and SnapBuildExportSnapshot().

1107 {
1108  TransactionId topXid;
1109  TransactionId *children;
1110  ExportedSnapshot *esnap;
1111  int nchildren;
1112  int addTopXid;
1114  FILE *f;
1115  int i;
1116  MemoryContext oldcxt;
1117  char path[MAXPGPATH];
1118  char pathtmp[MAXPGPATH];
1119 
1120  /*
1121  * It's tempting to call RequireTransactionBlock here, since it's not very
1122  * useful to export a snapshot that will disappear immediately afterwards.
1123  * However, we haven't got enough information to do that, since we don't
1124  * know if we're at top level or not. For example, we could be inside a
1125  * plpgsql function that is going to fire off other transactions via
1126  * dblink. Rather than disallow perfectly legitimate usages, don't make a
1127  * check.
1128  *
1129  * Also note that we don't make any restriction on the transaction's
1130  * isolation level; however, importers must check the level if they are
1131  * serializable.
1132  */
1133 
1134  /*
1135  * Get our transaction ID if there is one, to include in the snapshot.
1136  */
1137  topXid = GetTopTransactionIdIfAny();
1138 
1139  /*
1140  * We cannot export a snapshot from a subtransaction because there's no
1141  * easy way for importers to verify that the same subtransaction is still
1142  * running.
1143  */
1144  if (IsSubTransaction())
1145  ereport(ERROR,
1146  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1147  errmsg("cannot export a snapshot from a subtransaction")));
1148 
1149  /*
1150  * We do however allow previous committed subtransactions to exist.
1151  * Importers of the snapshot must see them as still running, so get their
1152  * XIDs to add them to the snapshot.
1153  */
1154  nchildren = xactGetCommittedChildren(&children);
1155 
1156  /*
1157  * Generate file path for the snapshot. We start numbering of snapshots
1158  * inside the transaction from 1.
1159  */
1160  snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%08X-%d",
1162 
1163  /*
1164  * Copy the snapshot into TopTransactionContext, add it to the
1165  * exportedSnapshots list, and mark it pseudo-registered. We do this to
1166  * ensure that the snapshot's xmin is honored for the rest of the
1167  * transaction.
1168  */
1169  snapshot = CopySnapshot(snapshot);
1170 
1172  esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
1173  esnap->snapfile = pstrdup(path);
1174  esnap->snapshot = snapshot;
1176  MemoryContextSwitchTo(oldcxt);
1177 
1178  snapshot->regd_count++;
1180 
1181  /*
1182  * Fill buf with a text serialization of the snapshot, plus identification
1183  * data about this transaction. The format expected by ImportSnapshot is
1184  * pretty rigid: each line must be fieldname:value.
1185  */
1186  initStringInfo(&buf);
1187 
1188  appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->backendId, MyProc->lxid);
1189  appendStringInfo(&buf, "pid:%d\n", MyProcPid);
1190  appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1191  appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1192  appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1193 
1194  appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1195  appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1196 
1197  /*
1198  * We must include our own top transaction ID in the top-xid data, since
1199  * by definition we will still be running when the importing transaction
1200  * adopts the snapshot, but GetSnapshotData never includes our own XID in
1201  * the snapshot. (There must, therefore, be enough room to add it.)
1202  *
1203  * However, it could be that our topXid is after the xmax, in which case
1204  * we shouldn't include it because xip[] members are expected to be before
1205  * xmax. (We need not make the same check for subxip[] members, see
1206  * snapshot.h.)
1207  */
1208  addTopXid = (TransactionIdIsValid(topXid) &&
1209  TransactionIdPrecedes(topXid, snapshot->xmax)) ? 1 : 0;
1210  appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1211  for (i = 0; i < snapshot->xcnt; i++)
1212  appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1213  if (addTopXid)
1214  appendStringInfo(&buf, "xip:%u\n", topXid);
1215 
1216  /*
1217  * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1218  * we have to cope with possible overflow.
1219  */
1220  if (snapshot->suboverflowed ||
1221  snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1222  appendStringInfoString(&buf, "sof:1\n");
1223  else
1224  {
1225  appendStringInfoString(&buf, "sof:0\n");
1226  appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1227  for (i = 0; i < snapshot->subxcnt; i++)
1228  appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1229  for (i = 0; i < nchildren; i++)
1230  appendStringInfo(&buf, "sxp:%u\n", children[i]);
1231  }
1232  appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1233 
1234  /*
1235  * Now write the text representation into a file. We first write to a
1236  * ".tmp" filename, and rename to final filename if no error. This
1237  * ensures that no other backend can read an incomplete file
1238  * (ImportSnapshot won't allow it because of its valid-characters check).
1239  */
1240  snprintf(pathtmp, sizeof(pathtmp), "%s.tmp", path);
1241  if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1242  ereport(ERROR,
1244  errmsg("could not create file \"%s\": %m", pathtmp)));
1245 
1246  if (fwrite(buf.data, buf.len, 1, f) != 1)
1247  ereport(ERROR,
1249  errmsg("could not write to file \"%s\": %m", pathtmp)));
1250 
1251  /* no fsync() since file need not survive a system crash */
1252 
1253  if (FreeFile(f))
1254  ereport(ERROR,
1256  errmsg("could not write to file \"%s\": %m", pathtmp)));
1257 
1258  /*
1259  * Now that we have written everything into a .tmp file, rename the file
1260  * to remove the .tmp suffix.
1261  */
1262  if (rename(pathtmp, path) < 0)
1263  ereport(ERROR,
1265  errmsg("could not rename file \"%s\" to \"%s\": %m",
1266  pathtmp, path)));
1267 
1268  /*
1269  * The basename of the file is what we return from pg_export_snapshot().
1270  * It's already in path in a textual format and we know that the path
1271  * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1272  * and pstrdup it so as not to return the address of a local variable.
1273  */
1274  return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1275 }
int xactGetCommittedChildren(TransactionId **ptr)
Definition: xact.c:5477
int MyProcPid
Definition: globals.c:40
MemoryContext TopTransactionContext
Definition: mcxt.c:49
BackendId backendId
Definition: proc.h:144
uint32 TransactionId
Definition: c.h:520
PGPROC * MyProc
Definition: proc.c:67
char * pstrdup(const char *in)
Definition: mcxt.c:1187
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_BINARY_W
Definition: c.h:1214
bool suboverflowed
Definition: snapshot.h:182
uint32 regd_count
Definition: snapshot.h:205
static List * exportedSnapshots
Definition: snapmgr.c:169
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:159
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
#define MAXPGPATH
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
int errcode_for_file_access(void)
Definition: elog.c:633
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2322
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:425
Snapshot snapshot
Definition: snapmgr.c:165
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:168
List * lappend(List *list, void *datum)
Definition: list.c:321
char * snapfile
Definition: snapmgr.c:164
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Oid MyDatabaseId
Definition: globals.c:85
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:606
#define ereport(elevel,...)
Definition: elog.h:144
bool XactReadOnly
Definition: xact.c:78
pairingheap_node ph_node
Definition: snapshot.h:206
bool takenDuringRecovery
Definition: snapshot.h:184
static int list_length(const List *l)
Definition: pg_list.h:149
int XactIsoLevel
Definition: xact.c:75
int FreeFile(FILE *file)
Definition: fd.c:2521
bool IsSubTransaction(void)
Definition: xact.c:4757
uint32 xcnt
Definition: snapshot.h:169
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1938
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define snprintf
Definition: port.h:193
TransactionId * subxip
Definition: snapshot.h:180
int32 subxcnt
Definition: snapshot.h:181
LocalTransactionId lxid
Definition: proc.h:134

◆ FreeSnapshot()

static void FreeSnapshot ( Snapshot  snapshot)
static

Definition at line 662 of file snapmgr.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, pfree(), and SnapshotData::regd_count.

Referenced by AtSubAbort_Snapshot(), PopActiveSnapshot(), and UnregisterSnapshotFromOwner().

663 {
664  Assert(snapshot->regd_count == 0);
665  Assert(snapshot->active_count == 0);
666  Assert(snapshot->copied);
667 
668  pfree(snapshot);
669 }
bool copied
Definition: snapshot.h:185
uint32 regd_count
Definition: snapshot.h:205
void pfree(void *pointer)
Definition: mcxt.c:1057
#define Assert(condition)
Definition: c.h:745
uint32 active_count
Definition: snapshot.h:204

◆ GetActiveSnapshot()

◆ GetCatalogSnapshot()

Snapshot GetCatalogSnapshot ( Oid  relid)

Definition at line 386 of file snapmgr.c.

References GetNonHistoricCatalogSnapshot(), HistoricSnapshot, and HistoricSnapshotActive().

Referenced by OldSnapshotThresholdActive(), process_settings(), systable_beginscan(), systable_beginscan_ordered(), systable_recheck_tuple(), and table_beginscan_catalog().

387 {
388  /*
389  * Return historic snapshot while we're doing logical decoding, so we can
390  * see the appropriate state of the catalog.
391  *
392  * This is the primary reason for needing to reset the system caches after
393  * finishing decoding.
394  */
396  return HistoricSnapshot;
397 
398  return GetNonHistoricCatalogSnapshot(relid);
399 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:105
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:408
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2054

◆ GetLatestSnapshot()

Snapshot GetLatestSnapshot ( void  )

Definition at line 325 of file snapmgr.c.

References Assert, elog, ERROR, FirstSnapshotSet, GetSnapshotData(), GetTransactionSnapshot(), HistoricSnapshotActive(), IsInParallelMode(), and SecondarySnapshot.

Referenced by AlterDomainNotNull(), asyncQueueReadAllNotifications(), ATRewriteTable(), check_default_partition_contents(), currtid_byrelname(), currtid_byreloid(), DefineQueryRewrite(), IndexCheckExclusion(), OldSnapshotThresholdActive(), pgstat_collect_oids(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RI_Initial_Check(), RI_PartitionRemove_Check(), ri_PerformCheck(), validateDomainConstraint(), validateForeignKeyConstraint(), and wait_for_relation_state_change().

326 {
327  /*
328  * We might be able to relax this, but nothing that could otherwise work
329  * needs it.
330  */
331  if (IsInParallelMode())
332  elog(ERROR,
333  "cannot update SecondarySnapshot during a parallel operation");
334 
335  /*
336  * So far there are no cases requiring support for GetLatestSnapshot()
337  * during logical decoding, but it wouldn't be hard to add if required.
338  */
340 
341  /* If first call in transaction, go ahead and set the xact snapshot */
342  if (!FirstSnapshotSet)
343  return GetTransactionSnapshot();
344 
346 
347  return SecondarySnapshot;
348 }
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:250
bool IsInParallelMode(void)
Definition: xact.c:1012
#define ERROR
Definition: elog.h:43
bool FirstSnapshotSet
Definition: snapmgr.c:149
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:96
#define Assert(condition)
Definition: c.h:745
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2064
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2054
#define elog(elevel,...)
Definition: elog.h:214
static Snapshot SecondarySnapshot
Definition: snapmgr.c:103

◆ GetNonHistoricCatalogSnapshot()

Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 408 of file snapmgr.c.

References CatalogSnapshot, GetSnapshotData(), InvalidateCatalogSnapshot(), pairingheap_add(), SnapshotData::ph_node, RelationHasSysCache(), and RelationInvalidatesSnapshotsOnly().

Referenced by GetCatalogSnapshot(), OldSnapshotThresholdActive(), and ScanPgRelation().

409 {
410  /*
411  * If the caller is trying to scan a relation that has no syscache, no
412  * catcache invalidations will be sent when it is updated. For a few key
413  * relations, snapshot invalidations are sent instead. If we're trying to
414  * scan a relation for which neither catcache nor snapshot invalidations
415  * are sent, we must refresh the snapshot every time.
416  */
417  if (CatalogSnapshot &&
419  !RelationHasSysCache(relid))
421 
422  if (CatalogSnapshot == NULL)
423  {
424  /* Get new snapshot. */
426 
427  /*
428  * Make sure the catalog snapshot will be accounted for in decisions
429  * about advancing PGPROC->xmin. We could apply RegisterSnapshot, but
430  * that would result in making a physical copy, which is overkill; and
431  * it would also create a dependency on some resource owner, which we
432  * do not want for reasons explained at the head of this file. Instead
433  * just shove the CatalogSnapshot into the pairing heap manually. This
434  * has to be reversed in InvalidateCatalogSnapshot, of course.
435  *
436  * NB: it had better be impossible for this to throw error, since the
437  * CatalogSnapshot pointer is already valid.
438  */
440  }
441 
442  return CatalogSnapshot;
443 }
SnapshotData CatalogSnapshotData
Definition: snapmgr.c:97
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:1496
static Snapshot CatalogSnapshot
Definition: snapmgr.c:104
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
pairingheap_node ph_node
Definition: snapshot.h:206
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1473
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2064
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ GetOldestSnapshot()

Snapshot GetOldestSnapshot ( void  )

Definition at line 357 of file snapmgr.c.

References ActiveSnapshotElt::as_snap, InvalidXLogRecPtr, SnapshotData::lsn, pairingheap_container, pairingheap_first(), pairingheap_is_empty, and XLogRecPtrIsInvalid.

Referenced by init_toast_snapshot(), and OldSnapshotThresholdActive().

358 {
359  Snapshot OldestRegisteredSnapshot = NULL;
360  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
361 
363  {
364  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
366  RegisteredLSN = OldestRegisteredSnapshot->lsn;
367  }
368 
369  if (OldestActiveSnapshot != NULL)
370  {
372 
373  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
375  }
376 
377  return OldestRegisteredSnapshot;
378 }
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
Snapshot as_snap
Definition: snapmgr.c:128
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr lsn
Definition: snapshot.h:209
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
#define pairingheap_container(type, membername, ptr)
Definition: pairingheap.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:137
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21

◆ GetOldSnapshotFromTimeMapping()

static bool GetOldSnapshotFromTimeMapping ( TimestampTz  ts,
TransactionId xlimitp 
)
static

Definition at line 1707 of file snapmgr.c.

References AlignTimestampToMinuteBoundary(), Assert, OldSnapshotControlData::count_used, OldSnapshotControlData::head_offset, OldSnapshotControlData::head_timestamp, LW_SHARED, LWLockAcquire(), LWLockRelease(), OLD_SNAPSHOT_TIME_MAP_ENTRIES, USECS_PER_MINUTE, and OldSnapshotControlData::xid_by_minute.

Referenced by TransactionIdLimitedForOldSnapshots().

1708 {
1709  bool in_mapping = false;
1710 
1712 
1713  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1714 
1717  {
1718  int offset;
1719 
1720  offset = ((ts - oldSnapshotControl->head_timestamp)
1721  / USECS_PER_MINUTE);
1722  if (offset > oldSnapshotControl->count_used - 1)
1723  offset = oldSnapshotControl->count_used - 1;
1724  offset = (oldSnapshotControl->head_offset + offset)
1726 
1727  *xlimitp = oldSnapshotControl->xid_by_minute[offset];
1728 
1729  in_mapping = true;
1730  }
1731 
1732  LWLockRelease(OldSnapshotTimeMapLock);
1733 
1734  return in_mapping;
1735 }
#define USECS_PER_MINUTE
Definition: timestamp.h:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
#define Assert(condition)
Definition: c.h:745
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: old_snapshot.h:70
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1621
TimestampTz head_timestamp
Definition: old_snapshot.h:68
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32

◆ GetOldSnapshotThresholdTimestamp()

TimestampTz GetOldSnapshotThresholdTimestamp ( void  )

Definition at line 1660 of file snapmgr.c.

References OldSnapshotControlData::mutex_threshold, SpinLockAcquire, SpinLockRelease, and OldSnapshotControlData::threshold_timestamp.

Referenced by TestForOldSnapshot_impl().

1661 {
1662  TimestampTz threshold_timestamp;
1663 
1665  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1667 
1668  return threshold_timestamp;
1669 }
int64 TimestampTz
Definition: timestamp.h:39
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: old_snapshot.h:36
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
#define SpinLockRelease(lock)
Definition: spin.h:64

◆ GetSnapshotCurrentTimestamp()

TimestampTz GetSnapshotCurrentTimestamp ( void  )

Definition at line 1635 of file snapmgr.c.

References OldSnapshotControlData::current_timestamp, GetCurrentTimestamp(), OldSnapshotControlData::mutex_current, now(), SpinLockAcquire, and SpinLockRelease.

Referenced by GetSnapshotDataInitOldSnapshot(), SnapshotTooOldMagicForTest(), and TransactionIdLimitedForOldSnapshots().

1636 {
1638 
1639  /*
1640  * Don't let time move backward; if it hasn't advanced, use the old value.
1641  */
1643  if (now <= oldSnapshotControl->current_timestamp)
1645  else
1648 
1649  return now;
1650 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1578
int64 TimestampTz
Definition: timestamp.h:39
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz current_timestamp
Definition: old_snapshot.h:31
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
#define SpinLockRelease(lock)
Definition: spin.h:64
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1542

◆ GetTransactionSnapshot()

Snapshot GetTransactionSnapshot ( void  )

Definition at line 250 of file snapmgr.c.

References Assert, CopySnapshot(), CurrentSnapshot, elog, ERROR, FirstSnapshotSet, GetSerializableTransactionSnapshot(), GetSnapshotData(), HistoricSnapshot, HistoricSnapshotActive(), InvalidateCatalogSnapshot(), IsInParallelMode(), IsolationIsSerializable, IsolationUsesXactSnapshot, pairingheap_add(), pairingheap_is_empty, SnapshotData::ph_node, and SnapshotData::regd_count.

Referenced by _bt_begin_parallel(), _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), apply_handle_delete(), apply_handle_insert(), apply_handle_update(), bt_check_every_level(), BuildCachedPlan(), CheckTargetForConflictsIn(), cluster(), DefineIndex(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), exec_stmt_call(), execute_sql_string(), fmgr_sql(), get_database_list(), get_subscription_list(), GetLatestSnapshot(), HandleFunctionRequest(), heapam_index_build_range_scan(), initialize_worker_spi(), InitializeParallelDSM(), InitPostgres(), LogicalRepSyncTableStart(), OldSnapshotThresholdActive(), pg_get_constraintdef_worker(), PortalRunMulti(), PortalRunUtility(), PortalStart(), ReindexMultipleInternal(), ReindexRelationConcurrently(), RememberToFreeTupleDescAtEOX(), RevalidateCachedQuery(), ri_PerformCheck(), SPI_cursor_open_internal(), vacuum(), vacuum_rel(), and XidIsConcurrent().

251 {
252  /*
253  * Return historic snapshot if doing logical decoding. We'll never need a
254  * non-historic transaction snapshot in this (sub-)transaction, so there's
255  * no need to be careful to set one up for later calls to
256  * GetTransactionSnapshot().
257  */
259  {
261  return HistoricSnapshot;
262  }
263 
264  /* First call in transaction? */
265  if (!FirstSnapshotSet)
266  {
267  /*
268  * Don't allow catalog snapshot to be older than xact snapshot. Must
269  * do this first to allow the empty-heap Assert to succeed.
270  */
272 
274  Assert(FirstXactSnapshot == NULL);
275 
276  if (IsInParallelMode())
277  elog(ERROR,
278  "cannot take query snapshot during a parallel operation");
279 
280  /*
281  * In transaction-snapshot mode, the first snapshot must live until
282  * end of xact regardless of what the caller does with it, so we must
283  * make a copy of it rather than returning CurrentSnapshotData
284  * directly. Furthermore, if we're running in serializable mode,
285  * predicate.c needs to wrap the snapshot fetch in its own processing.
286  */
288  {
289  /* First, create the snapshot in CurrentSnapshotData */
292  else
294  /* Make a saved copy */
297  /* Mark it as "registered" in FirstXactSnapshot */
300  }
301  else
303 
304  FirstSnapshotSet = true;
305  return CurrentSnapshot;
306  }
307 
309  return CurrentSnapshot;
310 
311  /* Don't allow catalog snapshot to be older than xact snapshot. */
313 
315 
316  return CurrentSnapshot;
317 }
#define IsolationUsesXactSnapshot()
Definition: xact.h:51
static Snapshot HistoricSnapshot
Definition: snapmgr.c:105
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:95
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:156
uint32 regd_count
Definition: snapshot.h:205
static Snapshot CurrentSnapshot
Definition: snapmgr.c:102
bool IsInParallelMode(void)
Definition: xact.c:1012
#define ERROR
Definition: elog.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
bool FirstSnapshotSet
Definition: snapmgr.c:149
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:606
pairingheap_node ph_node
Definition: snapshot.h:206
#define Assert(condition)
Definition: c.h:745
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1608
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2064
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2054
#define IsolationIsSerializable()
Definition: xact.h:52
#define elog(elevel,...)
Definition: elog.h:214
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ HistoricSnapshotActive()

bool HistoricSnapshotActive ( void  )

◆ HistoricSnapshotGetTupleCids()

HTAB* HistoricSnapshotGetTupleCids ( void  )

Definition at line 2060 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

2061 {
2063  return tuplecid_data;
2064 }
static HTAB * tuplecid_data
Definition: snapmgr.c:116
#define Assert(condition)
Definition: c.h:745
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2054

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1377 of file snapmgr.c.

References AllocateFile(), elog, ereport, errcode(), errmsg(), ERROR, FirstSnapshotSet, FreeFile(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetTopTransactionIdIfAny(), i, InvalidTransactionId, IsolationIsSerializable, IsolationUsesXactSnapshot, IsSubTransaction(), MAXPGPATH, MyDatabaseId, OidIsValid, palloc(), parseIntFromText(), parseVxidFromText(), parseXidFromText(), PG_BINARY_R, SetTransactionSnapshot(), SNAPSHOT_EXPORT_DIR, SNAPSHOT_MVCC, SnapshotData::snapshot_type, snprintf, stat, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdIsNormal, VirtualTransactionIdIsValid, XACT_SERIALIZABLE, XactReadOnly, SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by ExecSetVariableStmt(), and OldSnapshotThresholdActive().

1378 {
1379  char path[MAXPGPATH];
1380  FILE *f;
1381  struct stat stat_buf;
1382  char *filebuf;
1383  int xcnt;
1384  int i;
1385  VirtualTransactionId src_vxid;
1386  int src_pid;
1387  Oid src_dbid;
1388  int src_isolevel;
1389  bool src_readonly;
1390  SnapshotData snapshot;
1391 
1392  /*
1393  * Must be at top level of a fresh transaction. Note in particular that
1394  * we check we haven't acquired an XID --- if we have, it's conceivable
1395  * that the snapshot would show it as not running, making for very screwy
1396  * behavior.
1397  */
1398  if (FirstSnapshotSet ||
1400  IsSubTransaction())
1401  ereport(ERROR,
1402  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1403  errmsg("SET TRANSACTION SNAPSHOT must be called before any query")));
1404 
1405  /*
1406  * If we are in read committed mode then the next query would execute with
1407  * a new snapshot thus making this function call quite useless.
1408  */
1410  ereport(ERROR,
1411  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1412  errmsg("a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ")));
1413 
1414  /*
1415  * Verify the identifier: only 0-9, A-F and hyphens are allowed. We do
1416  * this mainly to prevent reading arbitrary files.
1417  */
1418  if (strspn(idstr, "0123456789ABCDEF-") != strlen(idstr))
1419  ereport(ERROR,
1420  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1421  errmsg("invalid snapshot identifier: \"%s\"", idstr)));
1422 
1423  /* OK, read the file */
1424  snprintf(path, MAXPGPATH, SNAPSHOT_EXPORT_DIR "/%s", idstr);
1425 
1426  f = AllocateFile(path, PG_BINARY_R);
1427  if (!f)
1428  ereport(ERROR,
1429  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1430  errmsg("invalid snapshot identifier: \"%s\"", idstr)));
1431 
1432  /* get the size of the file so that we know how much memory we need */
1433  if (fstat(fileno(f), &stat_buf))
1434  elog(ERROR, "could not stat file \"%s\": %m", path);
1435 
1436  /* and read the file into a palloc'd string */
1437  filebuf = (char *) palloc(stat_buf.st_size + 1);
1438  if (fread(filebuf, stat_buf.st_size, 1, f) != 1)
1439  elog(ERROR, "could not read file \"%s\": %m", path);
1440 
1441  filebuf[stat_buf.st_size] = '\0';
1442 
1443  FreeFile(f);
1444 
1445  /*
1446  * Construct a snapshot struct by parsing the file content.
1447  */
1448  memset(&snapshot, 0, sizeof(snapshot));
1449 
1450  parseVxidFromText("vxid:", &filebuf, path, &src_vxid);
1451  src_pid = parseIntFromText("pid:", &filebuf, path);
1452  /* we abuse parseXidFromText a bit here ... */
1453  src_dbid = parseXidFromText("dbid:", &filebuf, path);
1454  src_isolevel = parseIntFromText("iso:", &filebuf, path);
1455  src_readonly = parseIntFromText("ro:", &filebuf, path);
1456 
1457  snapshot.snapshot_type = SNAPSHOT_MVCC;
1458 
1459  snapshot.xmin = parseXidFromText("xmin:", &filebuf, path);
1460  snapshot.xmax = parseXidFromText("xmax:", &filebuf, path);
1461 
1462  snapshot.xcnt = xcnt = parseIntFromText("xcnt:", &filebuf, path);
1463 
1464  /* sanity-check the xid count before palloc */
1465  if (xcnt < 0 || xcnt > GetMaxSnapshotXidCount())
1466  ereport(ERROR,
1467  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1468  errmsg("invalid snapshot data in file \"%s\"", path)));
1469 
1470  snapshot.xip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1471  for (i = 0; i < xcnt; i++)
1472  snapshot.xip[i] = parseXidFromText("xip:", &filebuf, path);
1473 
1474  snapshot.suboverflowed = parseIntFromText("sof:", &filebuf, path);
1475 
1476  if (!snapshot.suboverflowed)
1477  {
1478  snapshot.subxcnt = xcnt = parseIntFromText("sxcnt:", &filebuf, path);
1479 
1480  /* sanity-check the xid count before palloc */
1481  if (xcnt < 0 || xcnt > GetMaxSnapshotSubxidCount())
1482  ereport(ERROR,
1483  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1484  errmsg("invalid snapshot data in file \"%s\"", path)));
1485 
1486  snapshot.subxip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1487  for (i = 0; i < xcnt; i++)
1488  snapshot.subxip[i] = parseXidFromText("sxp:", &filebuf, path);
1489  }
1490  else
1491  {
1492  snapshot.subxcnt = 0;
1493  snapshot.subxip = NULL;
1494  }
1495 
1496  snapshot.takenDuringRecovery = parseIntFromText("rec:", &filebuf, path);
1497 
1498  /*
1499  * Do some additional sanity checking, just to protect ourselves. We
1500  * don't trouble to check the array elements, just the most critical
1501  * fields.
1502  */
1503  if (!VirtualTransactionIdIsValid(src_vxid) ||
1504  !OidIsValid(src_dbid) ||
1505  !TransactionIdIsNormal(snapshot.xmin) ||
1506  !TransactionIdIsNormal(snapshot.xmax))
1507  ereport(ERROR,
1508  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1509  errmsg("invalid snapshot data in file \"%s\"", path)));
1510 
1511  /*
1512  * If we're serializable, the source transaction must be too, otherwise
1513  * predicate.c has problems (SxactGlobalXmin could go backwards). Also, a
1514  * non-read-only transaction can't adopt a snapshot from a read-only
1515  * transaction, as predicate.c handles the cases very differently.
1516  */
1518  {
1519  if (src_isolevel != XACT_SERIALIZABLE)
1520  ereport(ERROR,
1521  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1522  errmsg("a serializable transaction cannot import a snapshot from a non-serializable transaction")));
1523  if (src_readonly && !XactReadOnly)
1524  ereport(ERROR,
1525  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1526  errmsg("a non-read-only serializable transaction cannot import a snapshot from a read-only transaction")));
1527  }
1528 
1529  /*
1530  * We cannot import a snapshot that was taken in a different database,
1531  * because vacuum calculates OldestXmin on a per-database basis; so the
1532  * source transaction's xmin doesn't protect us from data loss. This
1533  * restriction could be removed if the source transaction were to mark its
1534  * xmin as being globally applicable. But that would require some
1535  * additional syntax, since that has to be known when the snapshot is
1536  * initially taken. (See pgsql-hackers discussion of 2011-10-21.)
1537  */
1538  if (src_dbid != MyDatabaseId)
1539  ereport(ERROR,
1540  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1541  errmsg("cannot import a snapshot from a different database")));
1542 
1543  /* OK, install the snapshot */
1544  SetTransactionSnapshot(&snapshot, &src_vxid, src_pid, NULL);
1545 }
static TransactionId parseXidFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1322
uint32 TransactionId
Definition: c.h:520
static int parseIntFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1297
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:511
#define IsolationUsesXactSnapshot()
Definition: xact.h:51
int errcode(int sqlerrcode)
Definition: elog.c:610
bool suboverflowed
Definition: snapshot.h:182
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define PG_BINARY_R
Definition: c.h:1213
#define XACT_SERIALIZABLE
Definition: xact.h:39
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:159
#define ERROR
Definition: elog.h:43
struct stat stat_buf
Definition: pg_standby.c:100
bool FirstSnapshotSet
Definition: snapmgr.c:149
#define MAXPGPATH
static void parseVxidFromText(const char *prefix, char **s, const char *filename, VirtualTransactionId *vxid)
Definition: snapmgr.c:1347
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2322
#define InvalidTransactionId
Definition: transam.h:31
SnapshotType snapshot_type
Definition: snapshot.h:144
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:425
TransactionId * xip
Definition: snapshot.h:168
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
#define stat(a, b)
Definition: win32_port.h:255
Oid MyDatabaseId
Definition: globals.c:85
#define ereport(elevel,...)
Definition: elog.h:144
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1927
bool XactReadOnly
Definition: xact.c:78
bool takenDuringRecovery
Definition: snapshot.h:184
int FreeFile(FILE *file)
Definition: fd.c:2521
bool IsSubTransaction(void)
Definition: xact.c:4757
uint32 xcnt
Definition: snapshot.h:169
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define IsolationIsSerializable()
Definition: xact.h:52
#define elog(elevel,...)
Definition: elog.h:214
int i
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1938
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define snprintf
Definition: port.h:193
TransactionId * subxip
Definition: snapshot.h:180
int32 subxcnt
Definition: snapshot.h:181

◆ InvalidateCatalogSnapshot()

void InvalidateCatalogSnapshot ( void  )

Definition at line 456 of file snapmgr.c.

References pairingheap_remove(), SnapshotData::ph_node, and SnapshotResetXmin().

Referenced by AtEOXact_Snapshot(), CopyFrom(), GetNonHistoricCatalogSnapshot(), GetTransactionSnapshot(), InitPostgres(), InvalidateCatalogSnapshotConditionally(), InvalidateSystemCaches(), LocalExecuteInvalidationMessage(), OldSnapshotThresholdActive(), and SetTransactionSnapshot().

457 {
458  if (CatalogSnapshot)
459  {
461  CatalogSnapshot = NULL;
463  }
464 }
static void SnapshotResetXmin(void)
Definition: snapmgr.c:925
static Snapshot CatalogSnapshot
Definition: snapmgr.c:104
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
pairingheap_node ph_node
Definition: snapshot.h:206
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170

◆ InvalidateCatalogSnapshotConditionally()

void InvalidateCatalogSnapshotConditionally ( void  )

Definition at line 477 of file snapmgr.c.

References InvalidateCatalogSnapshot(), and pairingheap_is_singular.

Referenced by OldSnapshotThresholdActive(), and PostgresMain().

478 {
479  if (CatalogSnapshot &&
480  ActiveSnapshot == NULL &&
483 }
static Snapshot CatalogSnapshot
Definition: snapmgr.c:104
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99

◆ MaintainOldSnapshotTimeMapping()

void MaintainOldSnapshotTimeMapping ( TimestampTz  whenTaken,
TransactionId  xmin 
)

Definition at line 1854 of file snapmgr.c.

References AlignTimestampToMinuteBoundary(), Assert, OldSnapshotControlData::count_used, DEBUG1, elog, OldSnapshotControlData::head_offset, OldSnapshotControlData::head_timestamp, i, OldSnapshotControlData::latest_xmin, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), OldSnapshotControlData::mutex_latest_xmin, OldSnapshotControlData::next_map_update, old_snapshot_threshold, OLD_SNAPSHOT_TIME_MAP_ENTRIES, SpinLockAcquire, SpinLockRelease, TransactionIdFollows(), TransactionIdIsNormal, TransactionIdPrecedes(), USECS_PER_MINUTE, and OldSnapshotControlData::xid_by_minute.

Referenced by GetSnapshotDataInitOldSnapshot(), and OldSnapshotThresholdActive().

1855 {
1856  TimestampTz ts;
1857  TransactionId latest_xmin;
1858  TimestampTz update_ts;
1859  bool map_update_required = false;
1860 
1861  /* Never call this function when old snapshot checking is disabled. */
1863 
1864  ts = AlignTimestampToMinuteBoundary(whenTaken);
1865 
1866  /*
1867  * Keep track of the latest xmin seen by any process. Update mapping with
1868  * a new value when we have crossed a bucket boundary.
1869  */
1871  latest_xmin = oldSnapshotControl->latest_xmin;
1872  update_ts = oldSnapshotControl->next_map_update;
1873  if (ts > update_ts)
1874  {
1876  map_update_required = true;
1877  }
1878  if (TransactionIdFollows(xmin, latest_xmin))
1881 
1882  /* We only needed to update the most recent xmin value. */
1883  if (!map_update_required)
1884  return;
1885 
1886  /* No further tracking needed for 0 (used for testing). */
1887  if (old_snapshot_threshold == 0)
1888  return;
1889 
1890  /*
1891  * We don't want to do something stupid with unusual values, but we don't
1892  * want to litter the log with warnings or break otherwise normal
1893  * processing for this feature; so if something seems unreasonable, just
1894  * log at DEBUG level and return without doing anything.
1895  */
1896  if (whenTaken < 0)
1897  {
1898  elog(DEBUG1,
1899  "MaintainOldSnapshotTimeMapping called with negative whenTaken = %ld",
1900  (long) whenTaken);
1901  return;
1902  }
1903  if (!TransactionIdIsNormal(xmin))
1904  {
1905  elog(DEBUG1,
1906  "MaintainOldSnapshotTimeMapping called with xmin = %lu",
1907  (unsigned long) xmin);
1908  return;
1909  }
1910 
1911  LWLockAcquire(OldSnapshotTimeMapLock, LW_EXCLUSIVE);
1912 
1918 
1919  if (oldSnapshotControl->count_used == 0)
1920  {
1921  /* set up first entry for empty mapping */
1925  oldSnapshotControl->xid_by_minute[0] = xmin;
1926  }
1927  else if (ts < oldSnapshotControl->head_timestamp)
1928  {
1929  /* old ts; log it at DEBUG */
1930  LWLockRelease(OldSnapshotTimeMapLock);
1931  elog(DEBUG1,
1932  "MaintainOldSnapshotTimeMapping called with old whenTaken = %ld",
1933  (long) whenTaken);
1934  return;
1935  }
1936  else if (ts <= (oldSnapshotControl->head_timestamp +
1938  * USECS_PER_MINUTE)))
1939  {
1940  /* existing mapping; advance xid if possible */
1941  int bucket = (oldSnapshotControl->head_offset
1943  / USECS_PER_MINUTE))
1945 
1947  oldSnapshotControl->xid_by_minute[bucket] = xmin;
1948  }
1949  else
1950  {
1951  /* We need a new bucket, but it might not be the very next one. */
1952  int distance_to_new_tail;
1953  int distance_to_current_tail;
1954  int advance;
1955 
1956  /*
1957  * Our goal is for the new "tail" of the mapping, that is, the entry
1958  * which is newest and thus furthest from the "head" entry, to
1959  * correspond to "ts". Since there's one entry per minute, the
1960  * distance between the current head and the new tail is just the
1961  * number of minutes of difference between ts and the current
1962  * head_timestamp.
1963  *
1964  * The distance from the current head to the current tail is one
1965  * less than the number of entries in the mapping, because the
1966  * entry at the head_offset is for 0 minutes after head_timestamp.
1967  *
1968  * The difference between these two values is the number of minutes
1969  * by which we need to advance the mapping, either adding new entries
1970  * or rotating old ones out.
1971  */
1972  distance_to_new_tail =
1974  distance_to_current_tail =
1976  advance = distance_to_new_tail - distance_to_current_tail;
1977  Assert(advance > 0);
1978 
1979  if (advance >= OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1980  {
1981  /* Advance is so far that all old data is junk; start over. */
1984  oldSnapshotControl->xid_by_minute[0] = xmin;
1986  }
1987  else
1988  {
1989  /* Store the new value in one or more buckets. */
1990  int i;
1991 
1992  for (i = 0; i < advance; i++)
1993  {
1995  {
1996  /* Map full and new value replaces old head. */
1997  int old_head = oldSnapshotControl->head_offset;
1998 
1999  if (old_head == (OLD_SNAPSHOT_TIME_MAP_ENTRIES - 1))
2001  else
2002  oldSnapshotControl->head_offset = old_head + 1;
2003  oldSnapshotControl->xid_by_minute[old_head] = xmin;
2005  }
2006  else
2007  {
2008  /* Extend map to unused entry. */
2009  int new_tail = (oldSnapshotControl->head_offset
2012 
2014  oldSnapshotControl->xid_by_minute[new_tail] = xmin;
2015  }
2016  }
2017  }
2018  }
2019 
2020  LWLockRelease(OldSnapshotTimeMapLock);
2021 }
#define DEBUG1
Definition: elog.h:25
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:520
int64 TimestampTz
Definition: timestamp.h:39
#define USECS_PER_MINUTE
Definition: timestamp.h:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz next_map_update
Definition: old_snapshot.h:34
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define SpinLockRelease(lock)
Definition: spin.h:64
TransactionId latest_xmin
Definition: old_snapshot.h:33
#define Assert(condition)
Definition: c.h:745
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: old_snapshot.h:70
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1621
#define elog(elevel,...)
Definition: elog.h:214
int old_snapshot_threshold
Definition: snapmgr.c:78
TimestampTz head_timestamp
Definition: old_snapshot.h:68
int i
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ parseIntFromText()

static int parseIntFromText ( const char *  prefix,
char **  s,
const char *  filename 
)
static

Definition at line 1297 of file snapmgr.c.

References ereport, errcode(), errmsg(), ERROR, and val.

Referenced by ImportSnapshot().

1298 {
1299  char *ptr = *s;
1300  int prefixlen = strlen(prefix);
1301  int val;
1302 
1303  if (strncmp(ptr, prefix, prefixlen) != 0)
1304  ereport(ERROR,
1305  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1306  errmsg("invalid snapshot data in file \"%s\"", filename)));
1307  ptr += prefixlen;
1308  if (sscanf(ptr, "%d", &val) != 1)
1309  ereport(ERROR,
1310  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1311  errmsg("invalid snapshot data in file \"%s\"", filename)));
1312  ptr = strchr(ptr, '\n');
1313  if (!ptr)
1314  ereport(ERROR,
1315  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1316  errmsg("invalid snapshot data in file \"%s\"", filename)));
1317  *s = ptr + 1;
1318  return val;
1319 }
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:824
long val
Definition: informix.c:664

◆ parseVxidFromText()

static void parseVxidFromText ( const char *  prefix,
char **  s,
const char *  filename,
VirtualTransactionId vxid 
)
static

Definition at line 1347 of file snapmgr.c.

References VirtualTransactionId::backendId, ereport, errcode(), errmsg(), ERROR, and VirtualTransactionId::localTransactionId.

Referenced by ImportSnapshot().

1349 {
1350  char *ptr = *s;
1351  int prefixlen = strlen(prefix);
1352 
1353  if (strncmp(ptr, prefix, prefixlen) != 0)
1354  ereport(ERROR,
1355  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1356  errmsg("invalid snapshot data in file \"%s\"", filename)));
1357  ptr += prefixlen;
1358  if (sscanf(ptr, "%d/%u", &vxid->backendId, &vxid->localTransactionId) != 2)
1359  ereport(ERROR,
1360  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1361  errmsg("invalid snapshot data in file \"%s\"", filename)));
1362  ptr = strchr(ptr, '\n');
1363  if (!ptr)
1364  ereport(ERROR,
1365  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1366  errmsg("invalid snapshot data in file \"%s\"", filename)));
1367  *s = ptr + 1;
1368 }
int errcode(int sqlerrcode)
Definition: elog.c:610
LocalTransactionId localTransactionId
Definition: lock.h:65
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
BackendId backendId
Definition: lock.h:64
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ parseXidFromText()

static TransactionId parseXidFromText ( const char *  prefix,
char **  s,
const char *  filename 
)
static

Definition at line 1322 of file snapmgr.c.

References ereport, errcode(), errmsg(), ERROR, and val.

Referenced by ImportSnapshot().

1323 {
1324  char *ptr = *s;
1325  int prefixlen = strlen(prefix);
1327 
1328  if (strncmp(ptr, prefix, prefixlen) != 0)
1329  ereport(ERROR,
1330  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1331  errmsg("invalid snapshot data in file \"%s\"", filename)));
1332  ptr += prefixlen;
1333  if (sscanf(ptr, "%u", &val) != 1)
1334  ereport(ERROR,
1335  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1336  errmsg("invalid snapshot data in file \"%s\"", filename)));
1337  ptr = strchr(ptr, '\n');
1338  if (!ptr)
1339  ereport(ERROR,
1340  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1341  errmsg("invalid snapshot data in file \"%s\"", filename)));
1342  *s = ptr + 1;
1343  return val;
1344 }
uint32 TransactionId
Definition: c.h:520
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:824
long val
Definition: informix.c:664

◆ pg_export_snapshot()

Datum pg_export_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 1282 of file snapmgr.c.

References cstring_to_text(), ExportSnapshot(), GetActiveSnapshot(), and PG_RETURN_TEXT_P.

1283 {
1284  char *snapshotName;
1285 
1286  snapshotName = ExportSnapshot(GetActiveSnapshot());
1287  PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1288 }
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:786
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1106
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
text * cstring_to_text(const char *s)
Definition: varlena.c:188

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 759 of file snapmgr.c.

References SnapshotData::active_count, ActiveSnapshotElt::as_next, ActiveSnapshotElt::as_snap, Assert, FreeSnapshot(), pfree(), SnapshotData::regd_count, and SnapshotResetXmin().

Referenced by _SPI_commit(), _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), apply_handle_delete(), apply_handle_insert(), apply_handle_update(), BuildCachedPlan(), cluster(), DefineIndex(), DoPortalRewind(), EndCopyTo(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), exec_stmt_call(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), fmgr_sql(), HandleFunctionRequest(), index_drop(), initialize_worker_spi(), LogicalRepSyncTableStart(), movedb(), OldSnapshotThresholdActive(), ParallelWorkerMain(), PersistHoldablePortal(), PortalRunMulti(), PortalRunSelect(), PortalRunUtility(), PortalStart(), refresh_matview_datafill(), ReindexMultipleInternal(), ReindexRelationConcurrently(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RememberToFreeTupleDescAtEOX(), RevalidateCachedQuery(), ShutdownSQLFunction(), vacuum(), vacuum_rel(), and wait_for_relation_state_change().

760 {
761  ActiveSnapshotElt *newstack;
762 
763  newstack = ActiveSnapshot->as_next;
764 
766 
768 
769  if (ActiveSnapshot->as_snap->active_count == 0 &&
772 
774  ActiveSnapshot = newstack;
775  if (ActiveSnapshot == NULL)
776  OldestActiveSnapshot = NULL;
777 
779 }
Snapshot as_snap
Definition: snapmgr.c:128
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
static void SnapshotResetXmin(void)
Definition: snapmgr.c:925
uint32 regd_count
Definition: snapshot.h:205
void pfree(void *pointer)
Definition: mcxt.c:1057
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:137
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:130
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134
#define Assert(condition)
Definition: c.h:745
uint32 active_count
Definition: snapshot.h:204

◆ PushActiveSnapshot()

void PushActiveSnapshot ( Snapshot  snap)

Definition at line 680 of file snapmgr.c.

References SnapshotData::active_count, ActiveSnapshot, ActiveSnapshotElt::as_level, ActiveSnapshotElt::as_next, ActiveSnapshotElt::as_snap, Assert, SnapshotData::copied, CopySnapshot(), GetCurrentTransactionNestLevel(), InvalidSnapshot, MemoryContextAlloc(), and TopTransactionContext.

Referenced by _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), apply_handle_delete(), apply_handle_insert(), apply_handle_update(), BuildCachedPlan(), cluster(), DefineIndex(), DoPortalRewind(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), exec_stmt_call(), execute_sql_string(), fmgr_sql(), HandleFunctionRequest(), initialize_worker_spi(), LogicalRepSyncTableStart(), OldSnapshotThresholdActive(), ParallelWorkerMain(), PersistHoldablePortal(), PortalRunSelect(), PortalRunUtility(), PortalStart(), PushCopiedSnapshot(), ReindexMultipleInternal(), ReindexRelationConcurrently(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RememberToFreeTupleDescAtEOX(), RevalidateCachedQuery(), ShutdownSQLFunction(), vacuum(), vacuum_rel(), and wait_for_relation_state_change().

681 {
682  ActiveSnapshotElt *newactive;
683 
684  Assert(snap != InvalidSnapshot);
685 
687 
688  /*
689  * Checking SecondarySnapshot is probably useless here, but it seems
690  * better to be sure.
691  */
692  if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
693  newactive->as_snap = CopySnapshot(snap);
694  else
695  newactive->as_snap = snap;
696 
697  newactive->as_next = ActiveSnapshot;
699 
700  newactive->as_snap->active_count++;
701 
702  ActiveSnapshot = newactive;
703  if (OldestActiveSnapshot == NULL)
705 }
Snapshot as_snap
Definition: snapmgr.c:128
MemoryContext TopTransactionContext
Definition: mcxt.c:49
bool copied
Definition: snapshot.h:185
static Snapshot CurrentSnapshot
Definition: snapmgr.c:102
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:137
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:130
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134
#define InvalidSnapshot
Definition: snapshot.h:123
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:606
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:857
#define Assert(condition)
Definition: c.h:745
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
static Snapshot SecondarySnapshot
Definition: snapmgr.c:103
uint32 active_count
Definition: snapshot.h:204

◆ PushCopiedSnapshot()

void PushCopiedSnapshot ( Snapshot  snapshot)

Definition at line 716 of file snapmgr.c.

References CopySnapshot(), and PushActiveSnapshot().

Referenced by _SPI_execute_plan(), BeginCopy(), ExecCreateTableAs(), ExplainOnePlan(), OldSnapshotThresholdActive(), PortalRunMulti(), and refresh_matview_datafill().

717 {
718  PushActiveSnapshot(CopySnapshot(snapshot));
719 }
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:680
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:606

◆ RegisterSnapshot()

◆ RegisterSnapshotOnOwner()

Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 823 of file snapmgr.c.

References SnapshotData::copied, CopySnapshot(), InvalidSnapshot, pairingheap_add(), SnapshotData::ph_node, SnapshotData::regd_count, ResourceOwnerEnlargeSnapshots(), and ResourceOwnerRememberSnapshot().

Referenced by inv_open(), OldSnapshotThresholdActive(), and RegisterSnapshot().

824 {
825  Snapshot snap;
826 
827  if (snapshot == InvalidSnapshot)
828  return InvalidSnapshot;
829 
830  /* Static snapshot? Create a persistent copy */
831  snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
832 
833  /* and tell resowner.c about it */
835  snap->regd_count++;
836  ResourceOwnerRememberSnapshot(owner, snap);
837 
838  if (snap->regd_count == 1)
840 
841  return snap;
842 }
bool copied
Definition: snapshot.h:185
void ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
Definition: resowner.c:1211
uint32 regd_count
Definition: snapshot.h:205
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
#define InvalidSnapshot
Definition: snapshot.h:123
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:606
pairingheap_node ph_node
Definition: snapshot.h:206
void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1222
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 2157 of file snapmgr.c.

References SnapshotData::active_count, SnapshotData::copied, SnapshotData::curcid, SerializedSnapshotData::curcid, SerializedSnapshotData::lsn, SnapshotData::lsn, MemoryContextAlloc(), SnapshotData::regd_count, SNAPSHOT_MVCC, SnapshotData::snapshot_type, SnapshotData::snapXactCompletionCount, SnapshotData::suboverflowed, SerializedSnapshotData::suboverflowed, SnapshotData::subxcnt, SerializedSnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, SerializedSnapshotData::takenDuringRecovery, TopTransactionContext, SerializedSnapshotData::whenTaken, SnapshotData::whenTaken, SnapshotData::xcnt, SerializedSnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, SerializedSnapshotData::xmax, SnapshotData::xmin, and SerializedSnapshotData::xmin.

Referenced by ExecBitmapHeapInitializeWorker(), index_beginscan_parallel(), ParallelWorkerMain(), and table_beginscan_parallel().

2158 {
2159  SerializedSnapshotData serialized_snapshot;
2160  Size size;
2161  Snapshot snapshot;
2162  TransactionId *serialized_xids;
2163 
2164  memcpy(&serialized_snapshot, start_address,
2165  sizeof(SerializedSnapshotData));
2166  serialized_xids = (TransactionId *)
2167  (start_address + sizeof(SerializedSnapshotData));
2168 
2169  /* We allocate any XID arrays needed in the same palloc block. */
2170  size = sizeof(SnapshotData)
2171  + serialized_snapshot.xcnt * sizeof(TransactionId)
2172  + serialized_snapshot.subxcnt * sizeof(TransactionId);
2173 
2174  /* Copy all required fields */
2176  snapshot->snapshot_type = SNAPSHOT_MVCC;
2177  snapshot->xmin = serialized_snapshot.xmin;
2178  snapshot->xmax = serialized_snapshot.xmax;
2179  snapshot->xip = NULL;
2180  snapshot->xcnt = serialized_snapshot.xcnt;
2181  snapshot->subxip = NULL;
2182  snapshot->subxcnt = serialized_snapshot.subxcnt;
2183  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
2184  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
2185  snapshot->curcid = serialized_snapshot.curcid;
2186  snapshot->whenTaken = serialized_snapshot.whenTaken;
2187  snapshot->lsn = serialized_snapshot.lsn;
2188  snapshot->snapXactCompletionCount = 0;
2189 
2190  /* Copy XIDs, if present. */
2191  if (serialized_snapshot.xcnt > 0)
2192  {
2193  snapshot->xip = (TransactionId *) (snapshot + 1);
2194  memcpy(snapshot->xip, serialized_xids,
2195  serialized_snapshot.xcnt * sizeof(TransactionId));
2196  }
2197 
2198  /* Copy SubXIDs, if present. */
2199  if (serialized_snapshot.subxcnt > 0)
2200  {
2201  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2202  serialized_snapshot.xcnt;
2203  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
2204  serialized_snapshot.subxcnt * sizeof(TransactionId));
2205  }
2206 
2207  /* Set the copied flag so that the caller will set refcounts correctly. */
2208  snapshot->regd_count = 0;
2209  snapshot->active_count = 0;
2210  snapshot->copied = true;
2211 
2212  return snapshot;
2213 }
uint64 snapXactCompletionCount
Definition: snapshot.h:216
MemoryContext TopTransactionContext
Definition: mcxt.c:49
uint32 TransactionId
Definition: c.h:520
bool copied
Definition: snapshot.h:185
XLogRecPtr lsn
Definition: snapshot.h:209
TimestampTz whenTaken
Definition: snapmgr.c:192
bool suboverflowed
Definition: snapshot.h:182
struct SnapshotData * Snapshot
Definition: snapshot.h:121
uint32 regd_count
Definition: snapshot.h:205
struct SnapshotData SnapshotData
SnapshotType snapshot_type
Definition: snapshot.h:144
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
TransactionId * xip
Definition: snapshot.h:168
TransactionId xmax
Definition: snapmgr.c:186
CommandId curcid
Definition: snapshot.h:187
bool takenDuringRecovery
Definition: snapshot.h:184
size_t Size
Definition: c.h:473
uint32 xcnt
Definition: snapshot.h:169
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
TransactionId xmin
Definition: snapmgr.c:185
TimestampTz whenTaken
Definition: snapshot.h:208
TransactionId * subxip
Definition: snapshot.h:180
uint32 active_count
Definition: snapshot.h:204
int32 subxcnt
Definition: snapshot.h:181

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  source_pgproc 
)

Definition at line 2222 of file snapmgr.c.

References InvalidPid, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2223 {
2224  SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
2225 }
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:511
#define InvalidPid
Definition: miscadmin.h:32

◆ SerializeSnapshot()

void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

Definition at line 2098 of file snapmgr.c.

References Assert, SnapshotData::curcid, SerializedSnapshotData::curcid, SerializedSnapshotData::lsn, SnapshotData::lsn, SnapshotData::suboverflowed, SerializedSnapshotData::suboverflowed, SnapshotData::subxcnt, SerializedSnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, SerializedSnapshotData::takenDuringRecovery, SerializedSnapshotData::whenTaken, SnapshotData::whenTaken, SnapshotData::xcnt, SerializedSnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, SerializedSnapshotData::xmax, SnapshotData::xmin, and SerializedSnapshotData::xmin.

Referenced by ExecBitmapHeapInitializeDSM(), index_parallelscan_initialize(), InitializeParallelDSM(), and table_parallelscan_initialize().

2099 {
2100  SerializedSnapshotData serialized_snapshot;
2101 
2102  Assert(snapshot->subxcnt >= 0);
2103 
2104  /* Copy all required fields */
2105  serialized_snapshot.xmin = snapshot->xmin;
2106  serialized_snapshot.xmax = snapshot->xmax;
2107  serialized_snapshot.xcnt = snapshot->xcnt;
2108  serialized_snapshot.subxcnt = snapshot->subxcnt;
2109  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2110  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2111  serialized_snapshot.curcid = snapshot->curcid;
2112  serialized_snapshot.whenTaken = snapshot->whenTaken;
2113  serialized_snapshot.lsn = snapshot->lsn;
2114 
2115  /*
2116  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2117  * taken during recovery - in that case, top-level XIDs are in subxip as
2118  * well, and we mustn't lose them.
2119  */
2120  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
2121  serialized_snapshot.subxcnt = 0;
2122 
2123  /* Copy struct to possibly-unaligned buffer */
2124  memcpy(start_address,
2125  &serialized_snapshot, sizeof(SerializedSnapshotData));
2126 
2127  /* Copy XID array */
2128  if (snapshot->xcnt > 0)
2129  memcpy((TransactionId *) (start_address +
2130  sizeof(SerializedSnapshotData)),
2131  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2132 
2133  /*
2134  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2135  * though, because it's not used anywhere in that case. Except if it's a
2136  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2137  * well in that case, so we mustn't lose them.
2138  */
2139  if (serialized_snapshot.subxcnt > 0)
2140  {
2141  Size subxipoff = sizeof(SerializedSnapshotData) +
2142  snapshot->xcnt * sizeof(TransactionId);
2143 
2144  memcpy((TransactionId *) (start_address + subxipoff),
2145  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2146  }
2147 }
uint32 TransactionId
Definition: c.h:520
XLogRecPtr lsn
Definition: snapshot.h:209
TimestampTz whenTaken
Definition: snapmgr.c:192
bool suboverflowed
Definition: snapshot.h:182
struct SerializedSnapshotData SerializedSnapshotData
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
TransactionId * xip
Definition: snapshot.h:168
TransactionId xmax
Definition: snapmgr.c:186
CommandId curcid
Definition: snapshot.h:187
#define Assert(condition)
Definition: c.h:745
bool takenDuringRecovery
Definition: snapshot.h:184
size_t Size
Definition: c.h:473
uint32 xcnt
Definition: snapshot.h:169
TransactionId xmin
Definition: snapmgr.c:185
TimestampTz whenTaken
Definition: snapshot.h:208
TransactionId * subxip
Definition: snapshot.h:180
int32 subxcnt
Definition: snapshot.h:181

◆ SetOldSnapshotThresholdTimestamp()

void SetOldSnapshotThresholdTimestamp ( TimestampTz  ts,
TransactionId  xlimit 
)

Definition at line 1672 of file snapmgr.c.

References Assert, OldSnapshotControlData::mutex_threshold, SpinLockAcquire, SpinLockRelease, OldSnapshotControlData::threshold_timestamp, OldSnapshotControlData::threshold_xid, and TransactionIdPrecedesOrEquals().

Referenced by heap_prune_satisfies_vacuum(), OldSnapshotThresholdActive(), and vacuum_set_xid_limits().

1673 {
1680 }
#define SpinLockAcquire(lock)
Definition: spin.h:62
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TimestampTz threshold_timestamp
Definition: old_snapshot.h:36
TransactionId threshold_xid
Definition: old_snapshot.h:37
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:745

◆ SetTransactionSnapshot()

static void SetTransactionSnapshot ( Snapshot  sourcesnap,
VirtualTransactionId sourcevxid,
int  sourcepid,
PGPROC sourceproc 
)
static

Definition at line 511 of file snapmgr.c.

References Assert, CopySnapshot(), CurrentSnapshot, ereport, errcode(), errdetail(), errmsg(), ERROR, FirstSnapshotSet, GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotData(), HistoricSnapshotActive(), InvalidateCatalogSnapshot(), IsolationIsSerializable, IsolationUsesXactSnapshot, pairingheap_add(), pairingheap_is_empty, SnapshotData::ph_node, ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), SnapshotData::regd_count, SetSerializableTransactionSnapshot(), SnapshotData::snapXactCompletionCount, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by ImportSnapshot(), and RestoreTransactionSnapshot().

513 {
514  /* Caller should have checked this already */
516 
517  /* Better do this to ensure following Assert succeeds. */
519 
521  Assert(FirstXactSnapshot == NULL);
523 
524  /*
525  * Even though we are not going to use the snapshot it computes, we must
526  * call GetSnapshotData, for two reasons: (1) to be sure that
527  * CurrentSnapshotData's XID arrays have been allocated, and (2) to update
528  * the state for GlobalVis*.
529  */
531 
532  /*
533  * Now copy appropriate fields from the source snapshot.
534  */
535  CurrentSnapshot->xmin = sourcesnap->xmin;
536  CurrentSnapshot->xmax = sourcesnap->xmax;
537  CurrentSnapshot->xcnt = sourcesnap->xcnt;
538  Assert(sourcesnap->xcnt <= GetMaxSnapshotXidCount());
539  memcpy(CurrentSnapshot->xip, sourcesnap->xip,
540  sourcesnap->xcnt * sizeof(TransactionId));
541  CurrentSnapshot->subxcnt = sourcesnap->subxcnt;
542  Assert(sourcesnap->subxcnt <= GetMaxSnapshotSubxidCount());
543  memcpy(CurrentSnapshot->subxip, sourcesnap->subxip,
544  sourcesnap->subxcnt * sizeof(TransactionId));
547  /* NB: curcid should NOT be copied, it's a local matter */
548 
550 
551  /*
552  * Now we have to fix what GetSnapshotData did with MyProc->xmin and
553  * TransactionXmin. There is a race condition: to make sure we are not
554  * causing the global xmin to go backwards, we have to test that the
555  * source transaction is still running, and that has to be done
556  * atomically. So let procarray.c do it.
557  *
558  * Note: in serializable mode, predicate.c will do this a second time. It
559  * doesn't seem worth contorting the logic here to avoid two calls,
560  * especially since it's not clear that predicate.c *must* do this.
561  */
562  if (sourceproc != NULL)
563  {
565  ereport(ERROR,
566  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
567  errmsg("could not import the requested snapshot"),
568  errdetail("The source transaction is not running anymore.")));
569  }
570  else if (!ProcArrayInstallImportedXmin(CurrentSnapshot->xmin, sourcevxid))
571  ereport(ERROR,
572  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
573  errmsg("could not import the requested snapshot"),
574  errdetail("The source process with PID %d is not running anymore.",
575  sourcepid)));
576 
577  /*
578  * In transaction-snapshot mode, the first snapshot must live until end of
579  * xact, so we must make a copy of it. Furthermore, if we're running in
580  * serializable mode, predicate.c needs to do its own processing.
581  */
583  {
586  sourcepid);
587  /* Make a saved copy */
590  /* Mark it as "registered" in FirstXactSnapshot */
593  }
594 
595  FirstSnapshotSet = true;
596 }
uint64 snapXactCompletionCount
Definition: snapshot.h:216
void SetSerializableTransactionSnapshot(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1648
uint32 TransactionId
Definition: c.h:520
#define IsolationUsesXactSnapshot()
Definition: xact.h:51
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
int errcode(int sqlerrcode)
Definition: elog.c:610
bool suboverflowed
Definition: snapshot.h:182
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:95
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:156
uint32 regd_count
Definition: snapshot.h:205
static Snapshot CurrentSnapshot
Definition: snapmgr.c:102
#define ERROR
Definition: elog.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
bool FirstSnapshotSet
Definition: snapmgr.c:149
int errdetail(const char *fmt,...)
Definition: elog.c:957
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
TransactionId * xip
Definition: snapshot.h:168
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:606
#define ereport(elevel,...)
Definition: elog.h:144
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1927
pairingheap_node ph_node
Definition: snapshot.h:206
#define Assert(condition)
Definition: c.h:745
bool takenDuringRecovery
Definition: snapshot.h:184
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2064
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
Definition: procarray.c:2491
uint32 xcnt
Definition: snapshot.h:169
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2054
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define IsolationIsSerializable()
Definition: xact.h:52
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1938
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
Definition: procarray.c:2416
TransactionId * subxip
Definition: snapshot.h:180
int32 subxcnt
Definition: snapshot.h:181

◆ SetupHistoricSnapshot()

void SetupHistoricSnapshot ( Snapshot  historic_snapshot,
HTAB tuplecids 
)

Definition at line 2031 of file snapmgr.c.

References Assert.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

2032 {
2033  Assert(historic_snapshot != NULL);
2034 
2035  /* setup the timetravel snapshot */
2036  HistoricSnapshot = historic_snapshot;
2037 
2038  /* setup (cmin, cmax) lookup hash */
2039  tuplecid_data = tuplecids;
2040 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:105
static HTAB * tuplecid_data
Definition: snapmgr.c:116
#define Assert(condition)
Definition: c.h:745

◆ SnapMgrInit()

void SnapMgrInit ( void  )

Definition at line 213 of file snapmgr.c.

References OldSnapshotControlData::count_used, OldSnapshotControlData::current_timestamp, OldSnapshotControlData::head_offset, OldSnapshotControlData::head_timestamp, InvalidTransactionId, OldSnapshotControlData::latest_xmin, OldSnapshotControlData::mutex_current, OldSnapshotControlData::mutex_latest_xmin, OldSnapshotControlData::mutex_threshold, OldSnapshotControlData::next_map_update, ShmemInitStruct(), SnapMgrShmemSize(), SpinLockInit, OldSnapshotControlData::threshold_timestamp, and OldSnapshotControlData::threshold_xid.

Referenced by CreateSharedMemoryAndSemaphores().

214 {
215  bool found;
216 
217  /*
218  * Create or attach to the OldSnapshotControlData structure.
219  */
221  ShmemInitStruct("OldSnapshotControlData",
222  SnapMgrShmemSize(), &found);
223 
224  if (!found)
225  {
237  }
238 }
#define SpinLockInit(lock)
Definition: spin.h:60
TimestampTz threshold_timestamp
Definition: old_snapshot.h:36
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
TimestampTz next_map_update
Definition: old_snapshot.h:34
TimestampTz current_timestamp
Definition: old_snapshot.h:31
TransactionId threshold_xid
Definition: old_snapshot.h:37
#define InvalidTransactionId
Definition: transam.h:31
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
TransactionId latest_xmin
Definition: old_snapshot.h:33
TimestampTz head_timestamp
Definition: old_snapshot.h:68
Size SnapMgrShmemSize(void)
Definition: snapmgr.c:197

◆ SnapMgrShmemSize()

Size SnapMgrShmemSize ( void  )

Definition at line 197 of file snapmgr.c.

References add_size(), mul_size(), offsetof, old_snapshot_threshold, and OLD_SNAPSHOT_TIME_MAP_ENTRIES.

Referenced by CreateSharedMemoryAndSemaphores(), and SnapMgrInit().

198 {
199  Size size;
200 
201  size = offsetof(OldSnapshotControlData, xid_by_minute);
202  if (old_snapshot_threshold > 0)
203  size = add_size(size, mul_size(sizeof(TransactionId),
205 
206  return size;
207 }
uint32 TransactionId
Definition: c.h:520
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
size_t Size
Definition: c.h:473
int old_snapshot_threshold
Definition: snapmgr.c:78
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
#define offsetof(type, field)
Definition: c.h:668

◆ SnapshotResetXmin()

static void SnapshotResetXmin ( void  )
static

Definition at line 925 of file snapmgr.c.

References InvalidTransactionId, MyProc, pairingheap_container, pairingheap_first(), pairingheap_is_empty, TransactionIdPrecedes(), PGPROC::xmin, and SnapshotData::xmin.

Referenced by AtEOXact_Snapshot(), AtSubAbort_Snapshot(), InvalidateCatalogSnapshot(), PopActiveSnapshot(), and UnregisterSnapshotFromOwner().

926 {
927  Snapshot minSnapshot;
928 
929  if (ActiveSnapshot != NULL)
930  return;
931 
933  {
935  return;
936  }
937 
938  minSnapshot = pairingheap_container(SnapshotData, ph_node,
940 
941  if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin))
942  MyProc->xmin = minSnapshot->xmin;
943 }
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
PGPROC * MyProc
Definition: proc.c:67
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
#define pairingheap_container(type, membername, ptr)
Definition: pairingheap.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
TransactionId xmin
Definition: proc.h:129
#define InvalidTransactionId
Definition: transam.h:31
TransactionId xmin
Definition: snapshot.h:157
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134

◆ SnapshotSetCommandId()

void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 490 of file snapmgr.c.

References SnapshotData::curcid, and FirstSnapshotSet.

Referenced by CommandCounterIncrement(), and OldSnapshotThresholdActive().

491 {
492  if (!FirstSnapshotSet)
493  return;
494 
495  if (CurrentSnapshot)
496  CurrentSnapshot->curcid = curcid;
497  if (SecondarySnapshot)
498  SecondarySnapshot->curcid = curcid;
499  /* Should we do the same with CatalogSnapshot? */
500 }
static Snapshot CurrentSnapshot
Definition: snapmgr.c:102
bool FirstSnapshotSet
Definition: snapmgr.c:149
CommandId curcid
Definition: snapshot.h:187
static Snapshot SecondarySnapshot
Definition: snapmgr.c:103

◆ SnapshotTooOldMagicForTest()

void SnapshotTooOldMagicForTest ( void  )

Definition at line 1689 of file snapmgr.c.

References Assert, GetSnapshotCurrentTimestamp(), OldSnapshotControlData::mutex_threshold, old_snapshot_threshold, SpinLockAcquire, SpinLockRelease, OldSnapshotControlData::threshold_timestamp, and USECS_PER_SEC.

Referenced by heap_page_prune_opt().

1690 {
1692 
1694 
1695  ts -= 5 * USECS_PER_SEC;
1696 
1700 }
#define USECS_PER_SEC
Definition: timestamp.h:94
int64 TimestampTz
Definition: timestamp.h:39
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: old_snapshot.h:36
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1635
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:745
int old_snapshot_threshold
Definition: snapmgr.c:78

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 2047 of file snapmgr.c.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

2048 {
2049  HistoricSnapshot = NULL;
2050  tuplecid_data = NULL;
2051 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:105
static HTAB * tuplecid_data
Definition: snapmgr.c:116

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1604 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom(), and OldSnapshotThresholdActive().

1605 {
1608  return true;
1609 
1610  return false;
1611 }
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99

◆ TransactionIdLimitedForOldSnapshots()

bool TransactionIdLimitedForOldSnapshots ( TransactionId  recentXmin,
Relation  relation,
TransactionId limit_xid,
TimestampTz limit_ts 
)

Definition at line 1751 of file snapmgr.c.

References AlignTimestampToMinuteBoundary(), Assert, GetOldSnapshotFromTimeMapping(), GetSnapshotCurrentTimestamp(), OldSnapshotControlData::latest_xmin, OldSnapshotControlData::mutex_latest_xmin, OldSnapshotControlData::mutex_threshold, MyProc, OldSnapshotControlData::next_map_update, old_snapshot_threshold, OldSnapshotThresholdActive(), RelationAllowsEarlyPruning, SpinLockAcquire, SpinLockRelease, OldSnapshotControlData::threshold_timestamp, OldSnapshotControlData::threshold_xid, TransactionIdFollows(), TransactionIdFollowsOrEquals(), TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), USECS_PER_MINUTE, USECS_PER_SEC, and PGPROC::xmin.

Referenced by heap_page_prune_opt(), heap_prune_satisfies_vacuum(), OldSnapshotThresholdActive(), and vacuum_set_xid_limits().

1755 {
1756  TimestampTz ts;
1757  TransactionId xlimit = recentXmin;
1758  TransactionId latest_xmin;
1759  TimestampTz next_map_update_ts;
1760  TransactionId threshold_timestamp;
1761  TransactionId threshold_xid;
1762 
1763  Assert(TransactionIdIsNormal(recentXmin));
1765  Assert(limit_ts != NULL && limit_xid != NULL);
1766 
1767  if (!RelationAllowsEarlyPruning(relation))
1768  return false;
1769 
1771 
1773  latest_xmin = oldSnapshotControl->latest_xmin;
1774  next_map_update_ts = oldSnapshotControl->next_map_update;
1776 
1777  /*
1778  * Zero threshold always overrides to latest xmin, if valid. Without some
1779  * heuristic it will find its own snapshot too old on, for example, a
1780  * simple UPDATE -- which would make it useless for most testing, but
1781  * there is no principled way to ensure that it doesn't fail in this way.
1782  * Use a five-second delay to try to get useful testing behavior, but this
1783  * may need adjustment.
1784  */
1785  if (old_snapshot_threshold == 0)
1786  {
1787  if (TransactionIdPrecedes(latest_xmin, MyProc->xmin)
1788  && TransactionIdFollows(latest_xmin, xlimit))
1789  xlimit = latest_xmin;
1790 
1791  ts -= 5 * USECS_PER_SEC;
1792  }
1793  else
1794  {
1797 
1798  /* Check for fast exit without LW locking. */
1800  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1801  threshold_xid = oldSnapshotControl->threshold_xid;
1803 
1804  if (ts == threshold_timestamp)
1805  {
1806  /*
1807  * Current timestamp is in same bucket as the last limit that
1808  * was applied. Reuse.
1809  */
1810  xlimit = threshold_xid;
1811  }
1812  else if (ts == next_map_update_ts)
1813  {
1814  /*
1815  * FIXME: This branch is super iffy - but that should probably
1816  * fixed separately.
1817  */
1818  xlimit = latest_xmin;
1819  }
1820  else if (GetOldSnapshotFromTimeMapping(ts, &xlimit))
1821  {
1822  }
1823 
1824  /*
1825  * Failsafe protection against vacuuming work of active transaction.
1826  *
1827  * This is not an assertion because we avoid the spinlock for
1828  * performance, leaving open the possibility that xlimit could advance
1829  * and be more current; but it seems prudent to apply this limit. It
1830  * might make pruning a tiny bit less aggressive than it could be, but
1831  * protects against data loss bugs.
1832  */
1833  if (TransactionIdIsNormal(latest_xmin)
1834  && TransactionIdPrecedes(latest_xmin, xlimit))
1835  xlimit = latest_xmin;
1836  }
1837 
1838  if (TransactionIdIsValid(xlimit) &&
1839  TransactionIdFollowsOrEquals(xlimit, recentXmin))
1840  {
1841  *limit_ts = ts;
1842  *limit_xid = xlimit;
1843 
1844  return true;
1845  }
1846 
1847  return false;
1848 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:520
#define USECS_PER_SEC
Definition: timestamp.h:94
PGPROC * MyProc
Definition: proc.c:67
int64 TimestampTz
Definition: timestamp.h:39
static bool OldSnapshotThresholdActive(void)
Definition: snapmgr.h:102
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define USECS_PER_MINUTE
Definition: timestamp.h:93
static bool GetOldSnapshotFromTimeMapping(TimestampTz ts, TransactionId *xlimitp)
Definition: snapmgr.c:1707
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: old_snapshot.h:36
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1635
TimestampTz next_map_update
Definition: old_snapshot.h:34
TransactionId threshold_xid
Definition: old_snapshot.h:37
TransactionId xmin
Definition: proc.h:129
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define SpinLockRelease(lock)
Definition: spin.h:64
TransactionId latest_xmin
Definition: old_snapshot.h:33
#define Assert(condition)
Definition: c.h:745
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1621
int old_snapshot_threshold
Definition: snapmgr.c:78
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 865 of file snapmgr.c.

References SnapshotData::active_count, Assert, FreeSnapshot(), pairingheap_is_empty, pairingheap_remove(), SnapshotData::ph_node, SnapshotData::regd_count, ResourceOwnerForgetSnapshot(), and SnapshotResetXmin().

Referenced by inv_close(), OldSnapshotThresholdActive(), PortalDrop(), PreCommit_Portals(), and UnregisterSnapshot().

866 {
867  if (snapshot == NULL)
868  return;
869 
870  Assert(snapshot->regd_count > 0);
872 
873  ResourceOwnerForgetSnapshot(owner, snapshot);
874 
875  snapshot->regd_count--;
876  if (snapshot->regd_count == 0)
878 
879  if (snapshot->regd_count == 0 && snapshot->active_count == 0)
880  {
881  FreeSnapshot(snapshot);
883  }
884 }
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
static void SnapshotResetXmin(void)
Definition: snapmgr.c:925
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
uint32 regd_count
Definition: snapshot.h:205
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1231
pairingheap_node ph_node
Definition: snapshot.h:206
#define Assert(condition)
Definition: c.h:745
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170
uint32 active_count
Definition: snapshot.h:204

◆ UpdateActiveSnapshotCommandId()

void UpdateActiveSnapshotCommandId ( void  )

Definition at line 728 of file snapmgr.c.

References SnapshotData::active_count, ActiveSnapshotElt::as_snap, Assert, SnapshotData::curcid, elog, ERROR, GetCurrentCommandId(), IsInParallelMode(), and SnapshotData::regd_count.

Referenced by _SPI_execute_plan(), BeginCopy(), ExecCreateTableAs(), ExplainOnePlan(), fmgr_sql(), OldSnapshotThresholdActive(), PortalRunMulti(), and refresh_matview_datafill().

729 {
730  CommandId save_curcid,
731  curcid;
732 
733  Assert(ActiveSnapshot != NULL);
736 
737  /*
738  * Don't allow modification of the active snapshot during parallel
739  * operation. We share the snapshot to worker backends at the beginning
740  * of parallel operation, so any change to the snapshot can lead to
741  * inconsistencies. We have other defenses against
742  * CommandCounterIncrement, but there are a few places that call this
743  * directly, so we put an additional guard here.
744  */
745  save_curcid = ActiveSnapshot->as_snap->curcid;
746  curcid = GetCurrentCommandId(false);
747  if (IsInParallelMode() && save_curcid != curcid)
748  elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
749  ActiveSnapshot->as_snap->curcid = curcid;
750 }
uint32 CommandId
Definition: c.h:534
Snapshot as_snap
Definition: snapmgr.c:128
uint32 regd_count
Definition: snapshot.h:205
bool IsInParallelMode(void)
Definition: xact.c:1012
#define ERROR
Definition: elog.h:43
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134
CommandId curcid
Definition: snapshot.h:187
#define Assert(condition)
Definition: c.h:745
#define elog(elevel,...)
Definition: elog.h:214
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:761
uint32 active_count
Definition: snapshot.h:204

◆ XactHasExportedSnapshots()

bool XactHasExportedSnapshots ( void  )

Definition at line 1552 of file snapmgr.c.

References NIL.

Referenced by OldSnapshotThresholdActive(), and PrepareTransaction().

1553 {
1554  return (exportedSnapshots != NIL);
1555 }
#define NIL
Definition: pg_list.h:65
static List * exportedSnapshots
Definition: snapmgr.c:169

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 2238 of file snapmgr.c.

References i, SnapshotData::suboverflowed, SubTransGetTopmostTransaction(), SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdPrecedes(), SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by asyncQueueProcessPageEntries(), and HeapTupleSatisfiesMVCC().

2239 {
2240  uint32 i;
2241 
2242  /*
2243  * Make a quick range check to eliminate most XIDs without looking at the
2244  * xip arrays. Note that this is OK even if we convert a subxact XID to
2245  * its parent below, because a subxact with XID < xmin has surely also got
2246  * a parent with XID < xmin, while one with XID >= xmax must belong to a
2247  * parent that was not yet committed at the time of this snapshot.
2248  */
2249 
2250  /* Any xid < xmin is not in-progress */
2251  if (TransactionIdPrecedes(xid, snapshot->xmin))
2252  return false;
2253  /* Any xid >= xmax is in-progress */
2254  if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
2255  return true;
2256 
2257  /*
2258  * Snapshot information is stored slightly differently in snapshots taken
2259  * during recovery.
2260  */
2261  if (!snapshot->takenDuringRecovery)
2262  {
2263  /*
2264  * If the snapshot contains full subxact data, the fastest way to
2265  * check things is just to compare the given XID against both subxact
2266  * XIDs and top-level XIDs. If the snapshot overflowed, we have to
2267  * use pg_subtrans to convert a subxact XID to its parent XID, but
2268  * then we need only look at top-level XIDs not subxacts.
2269  */
2270  if (!snapshot->suboverflowed)
2271  {
2272  /* we have full data, so search subxip */
2273  int32 j;
2274 
2275  for (j = 0; j < snapshot->subxcnt; j++)
2276  {
2277  if (TransactionIdEquals(xid, snapshot->subxip[j]))
2278  return true;
2279  }
2280 
2281  /* not there, fall through to search xip[] */
2282  }
2283  else
2284  {
2285  /*
2286  * Snapshot overflowed, so convert xid to top-level. This is safe
2287  * because we eliminated too-old XIDs above.
2288  */
2289  xid = SubTransGetTopmostTransaction(xid);
2290 
2291  /*
2292  * If xid was indeed a subxact, we might now have an xid < xmin,
2293  * so recheck to avoid an array scan. No point in rechecking
2294  * xmax.
2295  */
2296  if (TransactionIdPrecedes(xid, snapshot->xmin))
2297  return false;
2298  }
2299 
2300  for (i = 0; i < snapshot->xcnt; i++)
2301  {
2302  if (TransactionIdEquals(xid, snapshot->xip[i]))
2303  return true;
2304  }
2305  }
2306  else
2307  {
2308  int32 j;
2309 
2310  /*
2311  * In recovery we store all xids in the subxact array because it is by
2312  * far the bigger array, and we mostly don't know which xids are
2313  * top-level and which are subxacts. The xip array is empty.
2314  *
2315  * We start by searching subtrans, if we overflowed.
2316  */
2317  if (snapshot->suboverflowed)
2318  {
2319  /*
2320  * Snapshot overflowed, so convert xid to top-level. This is safe
2321  * because we eliminated too-old XIDs above.
2322  */
2323  xid = SubTransGetTopmostTransaction(xid);
2324 
2325  /*
2326  * If xid was indeed a subxact, we might now have an xid < xmin,
2327  * so recheck to avoid an array scan. No point in rechecking
2328  * xmax.
2329  */
2330  if (TransactionIdPrecedes(xid, snapshot->xmin))
2331  return false;
2332  }
2333 
2334  /*
2335  * We now have either a top-level xid higher than xmin or an
2336  * indeterminate xid. We don't know whether it's top level or subxact
2337  * but it doesn't matter. If it's present, the xid is visible.
2338  */
2339  for (j = 0; j < snapshot->subxcnt; j++)
2340  {
2341  if (TransactionIdEquals(xid, snapshot->subxip[j]))
2342  return true;
2343  }
2344  }
2345 
2346  return false;
2347 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
bool suboverflowed
Definition: snapshot.h:182
signed int int32
Definition: c.h:362
unsigned int uint32
Definition: c.h:374
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:168
bool takenDuringRecovery
Definition: snapshot.h:184
uint32 xcnt
Definition: snapshot.h:169
int i
TransactionId * subxip
Definition: snapshot.h:180
int32 subxcnt
Definition: snapshot.h:181

◆ xmin_cmp()

static int xmin_cmp ( const pairingheap_node a,
const pairingheap_node b,
void *  arg 
)
static

Definition at line 891 of file snapmgr.c.

References pairingheap_const_container, TransactionIdFollows(), TransactionIdPrecedes(), and SnapshotData::xmin.

892 {
893  const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
894  const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
895 
896  if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
897  return 1;
898  else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
899  return -1;
900  else
901  return 0;
902 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
TransactionId xmin
Definition: snapshot.h:157
#define pairingheap_const_container(type, membername, ptr)
Definition: pairingheap.h:51
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300

Variable Documentation

◆ ActiveSnapshot

ActiveSnapshotElt* ActiveSnapshot = NULL
static

Definition at line 134 of file snapmgr.c.

Referenced by PushActiveSnapshot().

◆ CatalogSnapshot

Snapshot CatalogSnapshot = NULL
static

Definition at line 104 of file snapmgr.c.

Referenced by GetNonHistoricCatalogSnapshot().

◆ CatalogSnapshotData

SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC}

Definition at line 97 of file snapmgr.c.

◆ CurrentSnapshot

Snapshot CurrentSnapshot = NULL
static

Definition at line 102 of file snapmgr.c.

Referenced by GetTransactionSnapshot(), and SetTransactionSnapshot().

◆ CurrentSnapshotData

SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 95 of file snapmgr.c.

◆ exportedSnapshots

List* exportedSnapshots = NIL
static

Definition at line 169 of file snapmgr.c.

◆ FirstSnapshotSet

◆ FirstXactSnapshot

Snapshot FirstXactSnapshot = NULL
static

Definition at line 156 of file snapmgr.c.

◆ HistoricSnapshot

Snapshot HistoricSnapshot = NULL
static

Definition at line 105 of file snapmgr.c.

Referenced by GetCatalogSnapshot(), and GetTransactionSnapshot().

◆ old_snapshot_threshold

◆ OldestActiveSnapshot

ActiveSnapshotElt* OldestActiveSnapshot = NULL
static

Definition at line 137 of file snapmgr.c.

◆ oldSnapshotControl

volatile OldSnapshotControlData* oldSnapshotControl

Definition at line 80 of file snapmgr.c.

Referenced by GetOldSnapshotTimeMapping().

◆ RecentXmin

◆ RegisteredSnapshots

pairingheap RegisteredSnapshots = {&xmin_cmp, NULL, NULL}
static

Definition at line 146 of file snapmgr.c.

◆ SecondarySnapshot

Snapshot SecondarySnapshot = NULL
static

Definition at line 103 of file snapmgr.c.

Referenced by GetLatestSnapshot().

◆ SecondarySnapshotData

SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 96 of file snapmgr.c.

◆ SnapshotAnyData

SnapshotData SnapshotAnyData = {SNAPSHOT_ANY}

Definition at line 99 of file snapmgr.c.

◆ SnapshotSelfData

SnapshotData SnapshotSelfData = {SNAPSHOT_SELF}

Definition at line 98 of file snapmgr.c.

◆ TransactionXmin

◆ tuplecid_data

HTAB* tuplecid_data = NULL
static

Definition at line 116 of file snapmgr.c.

Referenced by HistoricSnapshotGetTupleCids().