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 PushActiveSnapshotWithLevel (Snapshot snap, int snap_level)
 
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()

◆ AlignTimestampToMinuteBoundary()

static TimestampTz AlignTimestampToMinuteBoundary ( TimestampTz  ts)
static

Definition at line 1636 of file snapmgr.c.

References USECS_PER_MINUTE.

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

1637 {
1638  TimestampTz retval = ts + (USECS_PER_MINUTE - 1);
1639 
1640  return retval - (retval % USECS_PER_MINUTE);
1641 }
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 1021 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().

1022 {
1023  /*
1024  * In transaction-snapshot mode we must release our privately-managed
1025  * reference to the transaction snapshot. We must remove it from
1026  * RegisteredSnapshots to keep the check below happy. But we don't bother
1027  * to do FreeSnapshot, for two reasons: the memory will go away with
1028  * TopTransactionContext anyway, and if someone has left the snapshot
1029  * stacked as active, we don't want the code below to be chasing through a
1030  * dangling pointer.
1031  */
1032  if (FirstXactSnapshot != NULL)
1033  {
1037  }
1038  FirstXactSnapshot = NULL;
1039 
1040  /*
1041  * If we exported any snapshots, clean them up.
1042  */
1043  if (exportedSnapshots != NIL)
1044  {
1045  ListCell *lc;
1046 
1047  /*
1048  * Get rid of the files. Unlink failure is only a WARNING because (1)
1049  * it's too late to abort the transaction, and (2) leaving a leaked
1050  * file around has little real consequence anyway.
1051  *
1052  * We also need to remove the snapshots from RegisteredSnapshots to
1053  * prevent a warning below.
1054  *
1055  * As with the FirstXactSnapshot, we don't need to free resources of
1056  * the snapshot itself as it will go away with the memory context.
1057  */
1058  foreach(lc, exportedSnapshots)
1059  {
1060  ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1061 
1062  if (unlink(esnap->snapfile))
1063  elog(WARNING, "could not unlink file \"%s\": %m",
1064  esnap->snapfile);
1065 
1067  &esnap->snapshot->ph_node);
1068  }
1069 
1071  }
1072 
1073  /* Drop catalog snapshot if any */
1075 
1076  /* On commit, complain about leftover snapshots */
1077  if (isCommit)
1078  {
1079  ActiveSnapshotElt *active;
1080 
1082  elog(WARNING, "registered snapshots seem to remain after cleanup");
1083 
1084  /* complain about unpopped active snapshots */
1085  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1086  elog(WARNING, "snapshot %p still active", active);
1087  }
1088 
1089  /*
1090  * And reset our state. We don't need to free the memory explicitly --
1091  * it'll go away with TopTransactionContext.
1092  */
1093  ActiveSnapshot = NULL;
1094  OldestActiveSnapshot = NULL;
1096 
1097  CurrentSnapshot = NULL;
1098  SecondarySnapshot = NULL;
1099 
1100  FirstSnapshotSet = false;
1101 
1102  /*
1103  * During normal commit processing, we call ProcArrayEndTransaction() to
1104  * reset the MyProc->xmin. That call happens prior to the call to
1105  * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1106  */
1107  if (resetXmin)
1109 
1110  Assert(resetXmin || MyProc->xmin == 0);
1111 }
#define NIL
Definition: pg_list.h:65
#define pairingheap_reset(h)
Definition: pairingheap.h:93
PGPROC * MyProc
Definition: proc.c:68
static void SnapshotResetXmin(void)
Definition: snapmgr.c:940
#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:138
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:804
#define lfirst(lc)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:232
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 985 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().

986 {
987  /* Forget the active snapshots set by this subtransaction */
988  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
989  {
991 
992  next = ActiveSnapshot->as_next;
993 
994  /*
995  * Decrement the snapshot's active count. If it's still registered or
996  * marked as active by an outer subtransaction, we can't free it yet.
997  */
1000 
1001  if (ActiveSnapshot->as_snap->active_count == 0 &&
1004 
1005  /* and free the stack element */
1007 
1008  ActiveSnapshot = next;
1009  if (ActiveSnapshot == NULL)
1010  OldestActiveSnapshot = NULL;
1011  }
1012 
1014 }
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:940
uint32 regd_count
Definition: snapshot.h:205
void pfree(void *pointer)
Definition: mcxt.c:1169
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:804
uint32 active_count
Definition: snapshot.h:204

◆ AtSubCommit_Snapshot()

void AtSubCommit_Snapshot ( int  level)

Definition at line 964 of file snapmgr.c.

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

Referenced by CommitSubTransaction(), and OldSnapshotThresholdActive().

965 {
966  ActiveSnapshotElt *active;
967 
968  /*
969  * Relabel the active snapshots set in this subtransaction as though they
970  * are owned by the parent subxact.
971  */
972  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
973  {
974  if (active->as_level < level)
975  break;
976  active->as_level = level - 1;
977  }
978 }
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(), PushActiveSnapshotWithLevel(), 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:53
uint32 TransactionId
Definition: c.h:587
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:804
bool takenDuringRecovery
Definition: snapshot.h:184
size_t Size
Definition: c.h:540
uint32 xcnt
Definition: snapshot.h:169
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
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 1580 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().

1581 {
1582  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1583  DIR *s_dir;
1584  struct dirent *s_de;
1585 
1586  /*
1587  * Problems in reading the directory, or unlinking files, are reported at
1588  * LOG level. Since we're running in the startup process, ERROR level
1589  * would prevent database start, and it's not important enough for that.
1590  */
1592 
1593  while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1594  {
1595  if (strcmp(s_de->d_name, ".") == 0 ||
1596  strcmp(s_de->d_name, "..") == 0)
1597  continue;
1598 
1599  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1600 
1601  if (unlink(buf) != 0)
1602  ereport(LOG,
1604  errmsg("could not remove file \"%s\": %m", buf)));
1605  }
1606 
1607  FreeDir(s_dir);
1608 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2802
#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:721
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2721
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2839

◆ EstimateSnapshotSpace()

Size EstimateSnapshotSpace ( Snapshot  snap)

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

2094 {
2095  Size size;
2096 
2097  Assert(snap != InvalidSnapshot);
2099 
2100  /* We allocate any XID arrays needed in the same palloc block. */
2101  size = add_size(sizeof(SerializedSnapshotData),
2102  mul_size(snap->xcnt, sizeof(TransactionId)));
2103  if (snap->subxcnt > 0 &&
2104  (!snap->suboverflowed || snap->takenDuringRecovery))
2105  size = add_size(size,
2106  mul_size(snap->subxcnt, sizeof(TransactionId)));
2107 
2108  return size;
2109 }
uint32 TransactionId
Definition: c.h:587
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:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
#define Assert(condition)
Definition: c.h:804
bool takenDuringRecovery
Definition: snapshot.h:184
size_t Size
Definition: c.h:540
uint32 xcnt
Definition: snapshot.h:169
int32 subxcnt
Definition: snapshot.h:181

◆ ExportSnapshot()

char* ExportSnapshot ( Snapshot  snapshot)

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

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

◆ 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:1169
#define Assert(condition)
Definition: c.h:804
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:2073

◆ 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_internal(), DefineQueryRewrite(), IndexCheckExclusion(), OldSnapshotThresholdActive(), pgstat_collect_oids(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RI_Initial_Check(), RI_PartitionRemove_Check(), ri_PerformCheck(), validateDomainConstraint(), and validateForeignKeyConstraint().

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:1013
#define ERROR
Definition: elog.h:46
bool FirstSnapshotSet
Definition: snapmgr.c:149
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:96
#define Assert(condition)
Definition: c.h:804
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2206
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2073
#define elog(elevel,...)
Definition: elog.h:232
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:1507
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:1484
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2206
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 1722 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().

1723 {
1724  bool in_mapping = false;
1725 
1727 
1728  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1729 
1732  {
1733  int offset;
1734 
1735  offset = ((ts - oldSnapshotControl->head_timestamp)
1736  / USECS_PER_MINUTE);
1737  if (offset > oldSnapshotControl->count_used - 1)
1738  offset = oldSnapshotControl->count_used - 1;
1739  offset = (oldSnapshotControl->head_offset + offset)
1741 
1742  *xlimitp = oldSnapshotControl->xid_by_minute[offset];
1743 
1744  in_mapping = true;
1745  }
1746 
1747  LWLockRelease(OldSnapshotTimeMapLock);
1748 
1749  return in_mapping;
1750 }
#define USECS_PER_MINUTE
Definition: timestamp.h:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
#define Assert(condition)
Definition: c.h:804
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: old_snapshot.h:70
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1636
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 1675 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1676 {
1677  TimestampTz threshold_timestamp;
1678 
1680  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1682 
1683  return threshold_timestamp;
1684 }
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 1650 of file snapmgr.c.

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

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

1651 {
1653 
1654  /*
1655  * Don't let time move backward; if it hasn't advanced, use the old value.
1656  */
1658  if (now <= oldSnapshotControl->current_timestamp)
1660  else
1663 
1664  return now;
1665 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
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:1544

◆ 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(), begin_replication_step(), bt_check_every_level(), BuildCachedPlan(), CheckTargetForConflictsIn(), cluster(), DefineIndex(), EnsurePortalSnapshotExists(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), execute_sql_string(), ExecuteCallStmt(), 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(), verify_heapam(), 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:1013
#define ERROR
Definition: elog.h:46
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:804
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1680
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2206
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2073
#define IsolationIsSerializable()
Definition: xact.h:52
#define elog(elevel,...)
Definition: elog.h:232
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ HistoricSnapshotActive()

bool HistoricSnapshotActive ( void  )

◆ HistoricSnapshotGetTupleCids()

HTAB* HistoricSnapshotGetTupleCids ( void  )

Definition at line 2079 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

2080 {
2082  return tuplecid_data;
2083 }
static HTAB * tuplecid_data
Definition: snapmgr.c:116
#define Assert(condition)
Definition: c.h:804
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2073

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1392 of file snapmgr.c.

References AllocateFile(), elog, ereport, errcode(), errmsg(), ERROR, FirstSnapshotSet, FreeFile(), fstat, 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::st_size, 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().

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

457 {
458  if (CatalogSnapshot)
459  {
461  CatalogSnapshot = NULL;
463  }
464 }
static void SnapshotResetXmin(void)
Definition: snapmgr.c:940
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 1873 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().

1874 {
1875  TimestampTz ts;
1876  TransactionId latest_xmin;
1877  TimestampTz update_ts;
1878  bool map_update_required = false;
1879 
1880  /* Never call this function when old snapshot checking is disabled. */
1882 
1883  ts = AlignTimestampToMinuteBoundary(whenTaken);
1884 
1885  /*
1886  * Keep track of the latest xmin seen by any process. Update mapping with
1887  * a new value when we have crossed a bucket boundary.
1888  */
1890  latest_xmin = oldSnapshotControl->latest_xmin;
1891  update_ts = oldSnapshotControl->next_map_update;
1892  if (ts > update_ts)
1893  {
1895  map_update_required = true;
1896  }
1897  if (TransactionIdFollows(xmin, latest_xmin))
1900 
1901  /* We only needed to update the most recent xmin value. */
1902  if (!map_update_required)
1903  return;
1904 
1905  /* No further tracking needed for 0 (used for testing). */
1906  if (old_snapshot_threshold == 0)
1907  return;
1908 
1909  /*
1910  * We don't want to do something stupid with unusual values, but we don't
1911  * want to litter the log with warnings or break otherwise normal
1912  * processing for this feature; so if something seems unreasonable, just
1913  * log at DEBUG level and return without doing anything.
1914  */
1915  if (whenTaken < 0)
1916  {
1917  elog(DEBUG1,
1918  "MaintainOldSnapshotTimeMapping called with negative whenTaken = %ld",
1919  (long) whenTaken);
1920  return;
1921  }
1922  if (!TransactionIdIsNormal(xmin))
1923  {
1924  elog(DEBUG1,
1925  "MaintainOldSnapshotTimeMapping called with xmin = %lu",
1926  (unsigned long) xmin);
1927  return;
1928  }
1929 
1930  LWLockAcquire(OldSnapshotTimeMapLock, LW_EXCLUSIVE);
1931 
1937 
1938  if (oldSnapshotControl->count_used == 0)
1939  {
1940  /* set up first entry for empty mapping */
1944  oldSnapshotControl->xid_by_minute[0] = xmin;
1945  }
1946  else if (ts < oldSnapshotControl->head_timestamp)
1947  {
1948  /* old ts; log it at DEBUG */
1949  LWLockRelease(OldSnapshotTimeMapLock);
1950  elog(DEBUG1,
1951  "MaintainOldSnapshotTimeMapping called with old whenTaken = %ld",
1952  (long) whenTaken);
1953  return;
1954  }
1955  else if (ts <= (oldSnapshotControl->head_timestamp +
1957  * USECS_PER_MINUTE)))
1958  {
1959  /* existing mapping; advance xid if possible */
1960  int bucket = (oldSnapshotControl->head_offset
1962  / USECS_PER_MINUTE))
1964 
1966  oldSnapshotControl->xid_by_minute[bucket] = xmin;
1967  }
1968  else
1969  {
1970  /* We need a new bucket, but it might not be the very next one. */
1971  int distance_to_new_tail;
1972  int distance_to_current_tail;
1973  int advance;
1974 
1975  /*
1976  * Our goal is for the new "tail" of the mapping, that is, the entry
1977  * which is newest and thus furthest from the "head" entry, to
1978  * correspond to "ts". Since there's one entry per minute, the
1979  * distance between the current head and the new tail is just the
1980  * number of minutes of difference between ts and the current
1981  * head_timestamp.
1982  *
1983  * The distance from the current head to the current tail is one less
1984  * than the number of entries in the mapping, because the entry at the
1985  * head_offset is for 0 minutes after head_timestamp.
1986  *
1987  * The difference between these two values is the number of minutes by
1988  * which we need to advance the mapping, either adding new entries or
1989  * rotating old ones out.
1990  */
1991  distance_to_new_tail =
1993  distance_to_current_tail =
1995  advance = distance_to_new_tail - distance_to_current_tail;
1996  Assert(advance > 0);
1997 
1998  if (advance >= OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1999  {
2000  /* Advance is so far that all old data is junk; start over. */
2003  oldSnapshotControl->xid_by_minute[0] = xmin;
2005  }
2006  else
2007  {
2008  /* Store the new value in one or more buckets. */
2009  int i;
2010 
2011  for (i = 0; i < advance; i++)
2012  {
2014  {
2015  /* Map full and new value replaces old head. */
2016  int old_head = oldSnapshotControl->head_offset;
2017 
2018  if (old_head == (OLD_SNAPSHOT_TIME_MAP_ENTRIES - 1))
2020  else
2021  oldSnapshotControl->head_offset = old_head + 1;
2022  oldSnapshotControl->xid_by_minute[old_head] = xmin;
2024  }
2025  else
2026  {
2027  /* Extend map to unused entry. */
2028  int new_tail = (oldSnapshotControl->head_offset
2031 
2033  oldSnapshotControl->xid_by_minute[new_tail] = xmin;
2034  }
2035  }
2036  }
2037  }
2038 
2039  LWLockRelease(OldSnapshotTimeMapLock);
2040 }
#define DEBUG1
Definition: elog.h:25
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:587
int64 TimestampTz
Definition: timestamp.h:39
#define USECS_PER_MINUTE
Definition: timestamp.h:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#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:804
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: old_snapshot.h:70
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1636
#define elog(elevel,...)
Definition: elog.h:232
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 1312 of file snapmgr.c.

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

Referenced by ImportSnapshot().

1313 {
1314  char *ptr = *s;
1315  int prefixlen = strlen(prefix);
1316  int val;
1317 
1318  if (strncmp(ptr, prefix, prefixlen) != 0)
1319  ereport(ERROR,
1320  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1321  errmsg("invalid snapshot data in file \"%s\"", filename)));
1322  ptr += prefixlen;
1323  if (sscanf(ptr, "%d", &val) != 1)
1324  ereport(ERROR,
1325  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1326  errmsg("invalid snapshot data in file \"%s\"", filename)));
1327  ptr = strchr(ptr, '\n');
1328  if (!ptr)
1329  ereport(ERROR,
1330  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1331  errmsg("invalid snapshot data in file \"%s\"", filename)));
1332  *s = ptr + 1;
1333  return val;
1334 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
static char * filename
Definition: pg_dumpall.c:92
int errmsg(const char *fmt,...)
Definition: elog.c:909
long val
Definition: informix.c:664

◆ parseVxidFromText()

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

Definition at line 1362 of file snapmgr.c.

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

Referenced by ImportSnapshot().

1364 {
1365  char *ptr = *s;
1366  int prefixlen = strlen(prefix);
1367 
1368  if (strncmp(ptr, prefix, prefixlen) != 0)
1369  ereport(ERROR,
1370  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1371  errmsg("invalid snapshot data in file \"%s\"", filename)));
1372  ptr += prefixlen;
1373  if (sscanf(ptr, "%d/%u", &vxid->backendId, &vxid->localTransactionId) != 2)
1374  ereport(ERROR,
1375  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1376  errmsg("invalid snapshot data in file \"%s\"", filename)));
1377  ptr = strchr(ptr, '\n');
1378  if (!ptr)
1379  ereport(ERROR,
1380  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1381  errmsg("invalid snapshot data in file \"%s\"", filename)));
1382  *s = ptr + 1;
1383 }
int errcode(int sqlerrcode)
Definition: elog.c:698
LocalTransactionId localTransactionId
Definition: lock.h:67
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
BackendId backendId
Definition: lock.h:66
static char * filename
Definition: pg_dumpall.c:92
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ parseXidFromText()

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

Definition at line 1337 of file snapmgr.c.

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

Referenced by ImportSnapshot().

1338 {
1339  char *ptr = *s;
1340  int prefixlen = strlen(prefix);
1342 
1343  if (strncmp(ptr, prefix, prefixlen) != 0)
1344  ereport(ERROR,
1345  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1346  errmsg("invalid snapshot data in file \"%s\"", filename)));
1347  ptr += prefixlen;
1348  if (sscanf(ptr, "%u", &val) != 1)
1349  ereport(ERROR,
1350  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1351  errmsg("invalid snapshot data in file \"%s\"", filename)));
1352  ptr = strchr(ptr, '\n');
1353  if (!ptr)
1354  ereport(ERROR,
1355  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1356  errmsg("invalid snapshot data in file \"%s\"", filename)));
1357  *s = ptr + 1;
1358  return val;
1359 }
uint32 TransactionId
Definition: c.h:587
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
static char * filename
Definition: pg_dumpall.c:92
int errmsg(const char *fmt,...)
Definition: elog.c:909
long val
Definition: informix.c:664

◆ pg_export_snapshot()

Datum pg_export_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 1297 of file snapmgr.c.

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

1298 {
1299  char *snapshotName;
1300 
1301  snapshotName = ExportSnapshot(GetActiveSnapshot());
1302  PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1303 }
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:801
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1121
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:189

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 774 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_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), ATExecDetachPartition(), BuildCachedPlan(), cluster(), DefineIndex(), DoPortalRewind(), end_replication_step(), EndCopyTo(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), ExecCreateTableAs(), execute_sql_string(), ExecuteCallStmt(), ExplainOnePlan(), fmgr_sql(), ForgetPortalSnapshots(), 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(), and vacuum_rel().

775 {
776  ActiveSnapshotElt *newstack;
777 
778  newstack = ActiveSnapshot->as_next;
779 
781 
783 
784  if (ActiveSnapshot->as_snap->active_count == 0 &&
787 
789  ActiveSnapshot = newstack;
790  if (ActiveSnapshot == NULL)
791  OldestActiveSnapshot = NULL;
792 
794 }
Snapshot as_snap
Definition: snapmgr.c:128
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
static void SnapshotResetXmin(void)
Definition: snapmgr.c:940
uint32 regd_count
Definition: snapshot.h:205
void pfree(void *pointer)
Definition: mcxt.c:1169
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:804
uint32 active_count
Definition: snapshot.h:204

◆ PushActiveSnapshot()

◆ PushActiveSnapshotWithLevel()

void PushActiveSnapshotWithLevel ( Snapshot  snap,
int  snap_level 
)

Definition at line 694 of file snapmgr.c.

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

Referenced by EnsurePortalSnapshotExists(), OldSnapshotThresholdActive(), PortalRunUtility(), and PushActiveSnapshot().

695 {
696  ActiveSnapshotElt *newactive;
697 
698  Assert(snap != InvalidSnapshot);
699  Assert(ActiveSnapshot == NULL || snap_level >= ActiveSnapshot->as_level);
700 
702 
703  /*
704  * Checking SecondarySnapshot is probably useless here, but it seems
705  * better to be sure.
706  */
707  if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
708  newactive->as_snap = CopySnapshot(snap);
709  else
710  newactive->as_snap = snap;
711 
712  newactive->as_next = ActiveSnapshot;
713  newactive->as_level = snap_level;
714 
715  newactive->as_snap->active_count++;
716 
717  ActiveSnapshot = newactive;
718  if (OldestActiveSnapshot == NULL)
720 }
Snapshot as_snap
Definition: snapmgr.c:128
MemoryContext TopTransactionContext
Definition: mcxt.c:53
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
#define Assert(condition)
Definition: c.h:804
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
static Snapshot SecondarySnapshot
Definition: snapmgr.c:103
uint32 active_count
Definition: snapshot.h:204

◆ PushCopiedSnapshot()

void PushCopiedSnapshot ( Snapshot  snapshot)

Definition at line 731 of file snapmgr.c.

References CopySnapshot(), and PushActiveSnapshot().

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

732 {
733  PushActiveSnapshot(CopySnapshot(snapshot));
734 }
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 838 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().

839 {
840  Snapshot snap;
841 
842  if (snapshot == InvalidSnapshot)
843  return InvalidSnapshot;
844 
845  /* Static snapshot? Create a persistent copy */
846  snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
847 
848  /* and tell resowner.c about it */
850  snap->regd_count++;
851  ResourceOwnerRememberSnapshot(owner, snap);
852 
853  if (snap->regd_count == 1)
855 
856  return snap;
857 }
bool copied
Definition: snapshot.h:185
void ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
Definition: resowner.c:1240
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:1251
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

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

2177 {
2178  SerializedSnapshotData serialized_snapshot;
2179  Size size;
2180  Snapshot snapshot;
2181  TransactionId *serialized_xids;
2182 
2183  memcpy(&serialized_snapshot, start_address,
2184  sizeof(SerializedSnapshotData));
2185  serialized_xids = (TransactionId *)
2186  (start_address + sizeof(SerializedSnapshotData));
2187 
2188  /* We allocate any XID arrays needed in the same palloc block. */
2189  size = sizeof(SnapshotData)
2190  + serialized_snapshot.xcnt * sizeof(TransactionId)
2191  + serialized_snapshot.subxcnt * sizeof(TransactionId);
2192 
2193  /* Copy all required fields */
2195  snapshot->snapshot_type = SNAPSHOT_MVCC;
2196  snapshot->xmin = serialized_snapshot.xmin;
2197  snapshot->xmax = serialized_snapshot.xmax;
2198  snapshot->xip = NULL;
2199  snapshot->xcnt = serialized_snapshot.xcnt;
2200  snapshot->subxip = NULL;
2201  snapshot->subxcnt = serialized_snapshot.subxcnt;
2202  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
2203  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
2204  snapshot->curcid = serialized_snapshot.curcid;
2205  snapshot->whenTaken = serialized_snapshot.whenTaken;
2206  snapshot->lsn = serialized_snapshot.lsn;
2207  snapshot->snapXactCompletionCount = 0;
2208 
2209  /* Copy XIDs, if present. */
2210  if (serialized_snapshot.xcnt > 0)
2211  {
2212  snapshot->xip = (TransactionId *) (snapshot + 1);
2213  memcpy(snapshot->xip, serialized_xids,
2214  serialized_snapshot.xcnt * sizeof(TransactionId));
2215  }
2216 
2217  /* Copy SubXIDs, if present. */
2218  if (serialized_snapshot.subxcnt > 0)
2219  {
2220  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2221  serialized_snapshot.xcnt;
2222  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
2223  serialized_snapshot.subxcnt * sizeof(TransactionId));
2224  }
2225 
2226  /* Set the copied flag so that the caller will set refcounts correctly. */
2227  snapshot->regd_count = 0;
2228  snapshot->active_count = 0;
2229  snapshot->copied = true;
2230 
2231  return snapshot;
2232 }
uint64 snapXactCompletionCount
Definition: snapshot.h:216
MemoryContext TopTransactionContext
Definition: mcxt.c:53
uint32 TransactionId
Definition: c.h:587
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:540
uint32 xcnt
Definition: snapshot.h:169
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
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 2241 of file snapmgr.c.

References InvalidPid, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2242 {
2243  SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
2244 }
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 2117 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().

2118 {
2119  SerializedSnapshotData serialized_snapshot;
2120 
2121  Assert(snapshot->subxcnt >= 0);
2122 
2123  /* Copy all required fields */
2124  serialized_snapshot.xmin = snapshot->xmin;
2125  serialized_snapshot.xmax = snapshot->xmax;
2126  serialized_snapshot.xcnt = snapshot->xcnt;
2127  serialized_snapshot.subxcnt = snapshot->subxcnt;
2128  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2129  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2130  serialized_snapshot.curcid = snapshot->curcid;
2131  serialized_snapshot.whenTaken = snapshot->whenTaken;
2132  serialized_snapshot.lsn = snapshot->lsn;
2133 
2134  /*
2135  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2136  * taken during recovery - in that case, top-level XIDs are in subxip as
2137  * well, and we mustn't lose them.
2138  */
2139  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
2140  serialized_snapshot.subxcnt = 0;
2141 
2142  /* Copy struct to possibly-unaligned buffer */
2143  memcpy(start_address,
2144  &serialized_snapshot, sizeof(SerializedSnapshotData));
2145 
2146  /* Copy XID array */
2147  if (snapshot->xcnt > 0)
2148  memcpy((TransactionId *) (start_address +
2149  sizeof(SerializedSnapshotData)),
2150  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2151 
2152  /*
2153  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2154  * though, because it's not used anywhere in that case. Except if it's a
2155  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2156  * well in that case, so we mustn't lose them.
2157  */
2158  if (serialized_snapshot.subxcnt > 0)
2159  {
2160  Size subxipoff = sizeof(SerializedSnapshotData) +
2161  snapshot->xcnt * sizeof(TransactionId);
2162 
2163  memcpy((TransactionId *) (start_address + subxipoff),
2164  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2165  }
2166 }
uint32 TransactionId
Definition: c.h:587
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:804
bool takenDuringRecovery
Definition: snapshot.h:184
size_t Size
Definition: c.h:540
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 1687 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().

1688 {
1695 }
#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:804

◆ 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:1720
uint32 TransactionId
Definition: c.h:587
#define IsolationUsesXactSnapshot()
Definition: xact.h:51
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
int errcode(int sqlerrcode)
Definition: elog.c:698
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:46
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
bool FirstSnapshotSet
Definition: snapmgr.c:149
int errdetail(const char *fmt,...)
Definition: elog.c:1042
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:157
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:2069
pairingheap_node ph_node
Definition: snapshot.h:206
#define Assert(condition)
Definition: c.h:804
bool takenDuringRecovery
Definition: snapshot.h:184
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2206
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
Definition: procarray.c:2644
uint32 xcnt
Definition: snapshot.h:169
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2073
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define IsolationIsSerializable()
Definition: xact.h:52
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:2080
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
Definition: procarray.c:2569
TransactionId * subxip
Definition: snapshot.h:180
int32 subxcnt
Definition: snapshot.h:181

◆ SetupHistoricSnapshot()

void SetupHistoricSnapshot ( Snapshot  historic_snapshot,
HTAB tuplecids 
)

Definition at line 2050 of file snapmgr.c.

References Assert.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

2051 {
2052  Assert(historic_snapshot != NULL);
2053 
2054  /* setup the timetravel snapshot */
2055  HistoricSnapshot = historic_snapshot;
2056 
2057  /* setup (cmin, cmax) lookup hash */
2058  tuplecid_data = tuplecids;
2059 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:105
static HTAB * tuplecid_data
Definition: snapmgr.c:116
#define Assert(condition)
Definition: c.h:804

◆ 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:396
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 CalculateShmemSize(), 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:587
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
size_t Size
Definition: c.h:540
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:727

◆ SnapshotResetXmin()

static void SnapshotResetXmin ( void  )
static

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

941 {
942  Snapshot minSnapshot;
943 
944  if (ActiveSnapshot != NULL)
945  return;
946 
948  {
950  return;
951  }
952 
953  minSnapshot = pairingheap_container(SnapshotData, ph_node,
955 
956  if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin))
957  MyProc->xmin = minSnapshot->xmin;
958 }
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
PGPROC * MyProc
Definition: proc.c:68
#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:138
#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 1704 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().

1705 {
1707 
1709 
1710  ts -= 5 * USECS_PER_SEC;
1711 
1715 }
#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:1650
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:804
int old_snapshot_threshold
Definition: snapmgr.c:78

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 2066 of file snapmgr.c.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

2067 {
2068  HistoricSnapshot = NULL;
2069  tuplecid_data = NULL;
2070 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:105
static HTAB * tuplecid_data
Definition: snapmgr.c:116

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1619 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom(), and OldSnapshotThresholdActive().

1620 {
1623  return true;
1624 
1625  return false;
1626 }
#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 1766 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, RelationNeedsWAL, 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().

1770 {
1771  TimestampTz ts;
1772  TransactionId xlimit = recentXmin;
1773  TransactionId latest_xmin;
1774  TimestampTz next_map_update_ts;
1775  TransactionId threshold_timestamp;
1776  TransactionId threshold_xid;
1777 
1778  Assert(TransactionIdIsNormal(recentXmin));
1780  Assert(limit_ts != NULL && limit_xid != NULL);
1781 
1782  /*
1783  * TestForOldSnapshot() assumes early pruning advances the page LSN, so we
1784  * can't prune early when skipping WAL.
1785  */
1786  if (!RelationAllowsEarlyPruning(relation) || !RelationNeedsWAL(relation))
1787  return false;
1788 
1790 
1792  latest_xmin = oldSnapshotControl->latest_xmin;
1793  next_map_update_ts = oldSnapshotControl->next_map_update;
1795 
1796  /*
1797  * Zero threshold always overrides to latest xmin, if valid. Without some
1798  * heuristic it will find its own snapshot too old on, for example, a
1799  * simple UPDATE -- which would make it useless for most testing, but
1800  * there is no principled way to ensure that it doesn't fail in this way.
1801  * Use a five-second delay to try to get useful testing behavior, but this
1802  * may need adjustment.
1803  */
1804  if (old_snapshot_threshold == 0)
1805  {
1806  if (TransactionIdPrecedes(latest_xmin, MyProc->xmin)
1807  && TransactionIdFollows(latest_xmin, xlimit))
1808  xlimit = latest_xmin;
1809 
1810  ts -= 5 * USECS_PER_SEC;
1811  }
1812  else
1813  {
1816 
1817  /* Check for fast exit without LW locking. */
1819  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1820  threshold_xid = oldSnapshotControl->threshold_xid;
1822 
1823  if (ts == threshold_timestamp)
1824  {
1825  /*
1826  * Current timestamp is in same bucket as the last limit that was
1827  * applied. Reuse.
1828  */
1829  xlimit = threshold_xid;
1830  }
1831  else if (ts == next_map_update_ts)
1832  {
1833  /*
1834  * FIXME: This branch is super iffy - but that should probably
1835  * fixed separately.
1836  */
1837  xlimit = latest_xmin;
1838  }
1839  else if (GetOldSnapshotFromTimeMapping(ts, &xlimit))
1840  {
1841  }
1842 
1843  /*
1844  * Failsafe protection against vacuuming work of active transaction.
1845  *
1846  * This is not an assertion because we avoid the spinlock for
1847  * performance, leaving open the possibility that xlimit could advance
1848  * and be more current; but it seems prudent to apply this limit. It
1849  * might make pruning a tiny bit less aggressive than it could be, but
1850  * protects against data loss bugs.
1851  */
1852  if (TransactionIdIsNormal(latest_xmin)
1853  && TransactionIdPrecedes(latest_xmin, xlimit))
1854  xlimit = latest_xmin;
1855  }
1856 
1857  if (TransactionIdIsValid(xlimit) &&
1858  TransactionIdFollowsOrEquals(xlimit, recentXmin))
1859  {
1860  *limit_ts = ts;
1861  *limit_xid = xlimit;
1862 
1863  return true;
1864  }
1865 
1866  return false;
1867 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:587
#define USECS_PER_SEC
Definition: timestamp.h:94
PGPROC * MyProc
Definition: proc.c:68
int64 TimestampTz
Definition: timestamp.h:39
static bool OldSnapshotThresholdActive(void)
Definition: snapmgr.h:101
#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:1722
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: old_snapshot.h:36
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1650
TimestampTz next_map_update
Definition: old_snapshot.h:34
TransactionId threshold_xid
Definition: old_snapshot.h:37
TransactionId xmin
Definition: proc.h:138
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:804
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1636
#define RelationNeedsWAL(relation)
Definition: rel.h:601
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 880 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().

881 {
882  if (snapshot == NULL)
883  return;
884 
885  Assert(snapshot->regd_count > 0);
887 
888  ResourceOwnerForgetSnapshot(owner, snapshot);
889 
890  snapshot->regd_count--;
891  if (snapshot->regd_count == 0)
893 
894  if (snapshot->regd_count == 0 && snapshot->active_count == 0)
895  {
896  FreeSnapshot(snapshot);
898  }
899 }
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
static void SnapshotResetXmin(void)
Definition: snapmgr.c:940
#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:1260
pairingheap_node ph_node
Definition: snapshot.h:206
#define Assert(condition)
Definition: c.h:804
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 743 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(), BeginCopyTo(), ExecCreateTableAs(), ExplainOnePlan(), fmgr_sql(), OldSnapshotThresholdActive(), PortalRunMulti(), and refresh_matview_datafill().

744 {
745  CommandId save_curcid,
746  curcid;
747 
748  Assert(ActiveSnapshot != NULL);
751 
752  /*
753  * Don't allow modification of the active snapshot during parallel
754  * operation. We share the snapshot to worker backends at the beginning
755  * of parallel operation, so any change to the snapshot can lead to
756  * inconsistencies. We have other defenses against
757  * CommandCounterIncrement, but there are a few places that call this
758  * directly, so we put an additional guard here.
759  */
760  save_curcid = ActiveSnapshot->as_snap->curcid;
761  curcid = GetCurrentCommandId(false);
762  if (IsInParallelMode() && save_curcid != curcid)
763  elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
764  ActiveSnapshot->as_snap->curcid = curcid;
765 }
uint32 CommandId
Definition: c.h:601
Snapshot as_snap
Definition: snapmgr.c:128
uint32 regd_count
Definition: snapshot.h:205
bool IsInParallelMode(void)
Definition: xact.c:1013
#define ERROR
Definition: elog.h:46
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134
CommandId curcid
Definition: snapshot.h:187
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:762
uint32 active_count
Definition: snapshot.h:204

◆ XactHasExportedSnapshots()

bool XactHasExportedSnapshots ( void  )

Definition at line 1567 of file snapmgr.c.

References NIL.

Referenced by OldSnapshotThresholdActive(), and PrepareTransaction().

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

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 2257 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(), find_inheritance_children_extended(), HeapTupleSatisfiesMVCC(), and RelationGetPartitionDesc().

2258 {
2259  uint32 i;
2260 
2261  /*
2262  * Make a quick range check to eliminate most XIDs without looking at the
2263  * xip arrays. Note that this is OK even if we convert a subxact XID to
2264  * its parent below, because a subxact with XID < xmin has surely also got
2265  * a parent with XID < xmin, while one with XID >= xmax must belong to a
2266  * parent that was not yet committed at the time of this snapshot.
2267  */
2268 
2269  /* Any xid < xmin is not in-progress */
2270  if (TransactionIdPrecedes(xid, snapshot->xmin))
2271  return false;
2272  /* Any xid >= xmax is in-progress */
2273  if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
2274  return true;
2275 
2276  /*
2277  * Snapshot information is stored slightly differently in snapshots taken
2278  * during recovery.
2279  */
2280  if (!snapshot->takenDuringRecovery)
2281  {
2282  /*
2283  * If the snapshot contains full subxact data, the fastest way to
2284  * check things is just to compare the given XID against both subxact
2285  * XIDs and top-level XIDs. If the snapshot overflowed, we have to
2286  * use pg_subtrans to convert a subxact XID to its parent XID, but
2287  * then we need only look at top-level XIDs not subxacts.
2288  */
2289  if (!snapshot->suboverflowed)
2290  {
2291  /* we have full data, so search subxip */
2292  int32 j;
2293 
2294  for (j = 0; j < snapshot->subxcnt; j++)
2295  {
2296  if (TransactionIdEquals(xid, snapshot->subxip[j]))
2297  return true;
2298  }
2299 
2300  /* not there, fall through to search xip[] */
2301  }
2302  else
2303  {
2304  /*
2305  * Snapshot overflowed, so convert xid to top-level. This is safe
2306  * because we eliminated too-old XIDs above.
2307  */
2308  xid = SubTransGetTopmostTransaction(xid);
2309 
2310  /*
2311  * If xid was indeed a subxact, we might now have an xid < xmin,
2312  * so recheck to avoid an array scan. No point in rechecking
2313  * xmax.
2314  */
2315  if (TransactionIdPrecedes(xid, snapshot->xmin))
2316  return false;
2317  }
2318 
2319  for (i = 0; i < snapshot->xcnt; i++)
2320  {
2321  if (TransactionIdEquals(xid, snapshot->xip[i]))
2322  return true;
2323  }
2324  }
2325  else
2326  {
2327  int32 j;
2328 
2329  /*
2330  * In recovery we store all xids in the subxact array because it is by
2331  * far the bigger array, and we mostly don't know which xids are
2332  * top-level and which are subxacts. The xip array is empty.
2333  *
2334  * We start by searching subtrans, if we overflowed.
2335  */
2336  if (snapshot->suboverflowed)
2337  {
2338  /*
2339  * Snapshot overflowed, so convert xid to top-level. This is safe
2340  * because we eliminated too-old XIDs above.
2341  */
2342  xid = SubTransGetTopmostTransaction(xid);
2343 
2344  /*
2345  * If xid was indeed a subxact, we might now have an xid < xmin,
2346  * so recheck to avoid an array scan. No point in rechecking
2347  * xmax.
2348  */
2349  if (TransactionIdPrecedes(xid, snapshot->xmin))
2350  return false;
2351  }
2352 
2353  /*
2354  * We now have either a top-level xid higher than xmin or an
2355  * indeterminate xid. We don't know whether it's top level or subxact
2356  * but it doesn't matter. If it's present, the xid is visible.
2357  */
2358  for (j = 0; j < snapshot->subxcnt; j++)
2359  {
2360  if (TransactionIdEquals(xid, snapshot->subxip[j]))
2361  return true;
2362  }
2363  }
2364 
2365  return false;
2366 }
#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:429
unsigned int uint32
Definition: c.h:441
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 906 of file snapmgr.c.

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

907 {
908  const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
909  const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
910 
911  if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
912  return 1;
913  else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
914  return -1;
915  else
916  return 0;
917 }
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 PushActiveSnapshotWithLevel().

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