PostgreSQL Source Code  git master
snapmgr.h File Reference
#include "fmgr.h"
#include "utils/relcache.h"
#include "utils/resowner.h"
#include "utils/snapshot.h"
Include dependency graph for snapmgr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define OLD_SNAPSHOT_PADDING_ENTRIES   10
 
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES   (old_snapshot_threshold + OLD_SNAPSHOT_PADDING_ENTRIES)
 
#define RelationAllowsEarlyPruning(rel)
 
#define EarlyPruningEnabled(rel)   (old_snapshot_threshold >= 0 && RelationAllowsEarlyPruning(rel))
 
#define SnapshotSelf   (&SnapshotSelfData)
 
#define SnapshotAny   (&SnapshotAnyData)
 
#define InitDirtySnapshot(snapshotdata)   ((snapshotdata).snapshot_type = SNAPSHOT_DIRTY)
 
#define InitNonVacuumableSnapshot(snapshotdata, xmin_horizon)
 
#define InitToastSnapshot(snapshotdata, l, w)
 
#define IsMVCCSnapshot(snapshot)
 

Functions

Size SnapMgrShmemSize (void)
 
void SnapMgrInit (void)
 
TimestampTz GetSnapshotCurrentTimestamp (void)
 
TimestampTz GetOldSnapshotThresholdTimestamp (void)
 
Snapshot GetTransactionSnapshot (void)
 
Snapshot GetLatestSnapshot (void)
 
void SnapshotSetCommandId (CommandId curcid)
 
Snapshot GetOldestSnapshot (void)
 
Snapshot GetCatalogSnapshot (Oid relid)
 
Snapshot GetNonHistoricCatalogSnapshot (Oid relid)
 
void InvalidateCatalogSnapshot (void)
 
void InvalidateCatalogSnapshotConditionally (void)
 
void PushActiveSnapshot (Snapshot snapshot)
 
void PushCopiedSnapshot (Snapshot snapshot)
 
void UpdateActiveSnapshotCommandId (void)
 
void PopActiveSnapshot (void)
 
Snapshot GetActiveSnapshot (void)
 
bool ActiveSnapshotSet (void)
 
Snapshot RegisterSnapshot (Snapshot snapshot)
 
void UnregisterSnapshot (Snapshot snapshot)
 
Snapshot RegisterSnapshotOnOwner (Snapshot snapshot, ResourceOwner owner)
 
void UnregisterSnapshotFromOwner (Snapshot snapshot, ResourceOwner owner)
 
void AtSubCommit_Snapshot (int level)
 
void AtSubAbort_Snapshot (int level)
 
void AtEOXact_Snapshot (bool isCommit, bool resetXmin)
 
void ImportSnapshot (const char *idstr)
 
bool XactHasExportedSnapshots (void)
 
void DeleteAllExportedSnapshotFiles (void)
 
bool ThereAreNoPriorRegisteredSnapshots (void)
 
TransactionId TransactionIdLimitedForOldSnapshots (TransactionId recentXmin, Relation relation)
 
void MaintainOldSnapshotTimeMapping (TimestampTz whenTaken, TransactionId xmin)
 
char * ExportSnapshot (Snapshot snapshot)
 
bool XidInMVCCSnapshot (TransactionId xid, Snapshot snapshot)
 
struct HTABHistoricSnapshotGetTupleCids (void)
 
void SetupHistoricSnapshot (Snapshot snapshot_now, struct HTAB *tuplecids)
 
void TeardownHistoricSnapshot (bool is_error)
 
bool HistoricSnapshotActive (void)
 
Size EstimateSnapshotSpace (Snapshot snapshot)
 
void SerializeSnapshot (Snapshot snapshot, char *start_address)
 
Snapshot RestoreSnapshot (char *start_address)
 
void RestoreTransactionSnapshot (Snapshot snapshot, void *master_pgproc)
 

Variables

PGDLLIMPORT int old_snapshot_threshold
 
bool FirstSnapshotSet
 
PGDLLIMPORT TransactionId TransactionXmin
 
PGDLLIMPORT TransactionId RecentXmin
 
PGDLLIMPORT TransactionId RecentGlobalXmin
 
PGDLLIMPORT TransactionId RecentGlobalDataXmin
 
PGDLLIMPORT SnapshotData SnapshotSelfData
 
PGDLLIMPORT SnapshotData SnapshotAnyData
 
PGDLLIMPORT SnapshotData CatalogSnapshotData
 

Macro Definition Documentation

◆ EarlyPruningEnabled

#define EarlyPruningEnabled (   rel)    (old_snapshot_threshold >= 0 && RelationAllowsEarlyPruning(rel))

Definition at line 46 of file snapmgr.h.

Referenced by index_build(), and reindex_index().

◆ InitDirtySnapshot

#define InitDirtySnapshot (   snapshotdata)    ((snapshotdata).snapshot_type = SNAPSHOT_DIRTY)

◆ InitNonVacuumableSnapshot

#define InitNonVacuumableSnapshot (   snapshotdata,
  xmin_horizon 
)
Value:
((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
(snapshotdata).xmin = (xmin_horizon))

Definition at line 84 of file snapmgr.h.

Referenced by get_actual_variable_range().

◆ InitToastSnapshot

#define InitToastSnapshot (   snapshotdata,
  l,
 
)
Value:
((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \
(snapshotdata).lsn = (l), \
(snapshotdata).whenTaken = (w))

Definition at line 92 of file snapmgr.h.

Referenced by init_toast_snapshot().

◆ IsMVCCSnapshot

◆ OLD_SNAPSHOT_PADDING_ENTRIES

#define OLD_SNAPSHOT_PADDING_ENTRIES   10

Definition at line 31 of file snapmgr.h.

◆ OLD_SNAPSHOT_TIME_MAP_ENTRIES

#define OLD_SNAPSHOT_TIME_MAP_ENTRIES   (old_snapshot_threshold + OLD_SNAPSHOT_PADDING_ENTRIES)

◆ RelationAllowsEarlyPruning

#define RelationAllowsEarlyPruning (   rel)
Value:
( \
RelationNeedsWAL(rel) \
&& !IsCatalogRelation(rel) \
)
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:96
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:553
bool RelationHasUnloggedIndex(Relation rel)
Definition: relcache.c:5772

Definition at line 38 of file snapmgr.h.

Referenced by TestForOldSnapshot_impl(), and TransactionIdLimitedForOldSnapshots().

◆ SnapshotAny

◆ SnapshotSelf

Function Documentation

◆ ActiveSnapshotSet()

bool ActiveSnapshotSet ( void  )

Definition at line 853 of file snapmgr.c.

Referenced by _SPI_execute_plan(), BuildCachedPlan(), pg_plan_query(), PortalRunUtility(), postquel_start(), RevalidateCachedQuery(), SPI_commit(), and vacuum().

854 {
855  return ActiveSnapshot != NULL;
856 }
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:190

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1061 of file snapmgr.c.

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

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

1062 {
1063  /*
1064  * In transaction-snapshot mode we must release our privately-managed
1065  * reference to the transaction snapshot. We must remove it from
1066  * RegisteredSnapshots to keep the check below happy. But we don't bother
1067  * to do FreeSnapshot, for two reasons: the memory will go away with
1068  * TopTransactionContext anyway, and if someone has left the snapshot
1069  * stacked as active, we don't want the code below to be chasing through a
1070  * dangling pointer.
1071  */
1072  if (FirstXactSnapshot != NULL)
1073  {
1077  }
1078  FirstXactSnapshot = NULL;
1079 
1080  /*
1081  * If we exported any snapshots, clean them up.
1082  */
1083  if (exportedSnapshots != NIL)
1084  {
1085  ListCell *lc;
1086 
1087  /*
1088  * Get rid of the files. Unlink failure is only a WARNING because (1)
1089  * it's too late to abort the transaction, and (2) leaving a leaked
1090  * file around has little real consequence anyway.
1091  *
1092  * We also need to remove the snapshots from RegisteredSnapshots to
1093  * prevent a warning below.
1094  *
1095  * As with the FirstXactSnapshot, we don't need to free resources of
1096  * the snapshot iself as it will go away with the memory context.
1097  */
1098  foreach(lc, exportedSnapshots)
1099  {
1100  ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1101 
1102  if (unlink(esnap->snapfile))
1103  elog(WARNING, "could not unlink file \"%s\": %m",
1104  esnap->snapfile);
1105 
1107  &esnap->snapshot->ph_node);
1108  }
1109 
1111  }
1112 
1113  /* Drop catalog snapshot if any */
1115 
1116  /* On commit, complain about leftover snapshots */
1117  if (isCommit)
1118  {
1119  ActiveSnapshotElt *active;
1120 
1122  elog(WARNING, "registered snapshots seem to remain after cleanup");
1123 
1124  /* complain about unpopped active snapshots */
1125  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1126  elog(WARNING, "snapshot %p still active", active);
1127  }
1128 
1129  /*
1130  * And reset our state. We don't need to free the memory explicitly --
1131  * it'll go away with TopTransactionContext.
1132  */
1133  ActiveSnapshot = NULL;
1134  OldestActiveSnapshot = NULL;
1136 
1137  CurrentSnapshot = NULL;
1138  SecondarySnapshot = NULL;
1139 
1140  FirstSnapshotSet = false;
1141 
1142  /*
1143  * During normal commit processing, we call ProcArrayEndTransaction() to
1144  * reset the PgXact->xmin. That call happens prior to the call to
1145  * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1146  */
1147  if (resetXmin)
1149 
1150  Assert(resetXmin || MyPgXact->xmin == 0);
1151 }
#define NIL
Definition: pg_list.h:69
#define pairingheap_reset(h)
Definition: pairingheap.h:93
TransactionId xmin
Definition: proc.h:228
static void SnapshotResetXmin(void)
Definition: snapmgr.c:980
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:212
uint32 regd_count
Definition: snapshot.h:180
static Snapshot CurrentSnapshot
Definition: snapmgr.c:151
PGXACT * MyPgXact
Definition: proc.c:69
static List * exportedSnapshots
Definition: snapmgr.c:225
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
bool FirstSnapshotSet
Definition: snapmgr.c:205
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:193
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:186
Snapshot snapshot
Definition: snapmgr.c:221
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:512
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:190
char * snapfile
Definition: snapmgr.c:220
#define WARNING
Definition: elog.h:40
pairingheap_node ph_node
Definition: snapshot.h:181
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:106
#define elog(elevel,...)
Definition: elog.h:226
static Snapshot SecondarySnapshot
Definition: snapmgr.c:152
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170

◆ AtSubAbort_Snapshot()

void AtSubAbort_Snapshot ( int  level)

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

1026 {
1027  /* Forget the active snapshots set by this subtransaction */
1028  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
1029  {
1031 
1032  next = ActiveSnapshot->as_next;
1033 
1034  /*
1035  * Decrement the snapshot's active count. If it's still registered or
1036  * marked as active by an outer subtransaction, we can't free it yet.
1037  */
1040 
1041  if (ActiveSnapshot->as_snap->active_count == 0 &&
1044 
1045  /* and free the stack element */
1047 
1048  ActiveSnapshot = next;
1049  if (ActiveSnapshot == NULL)
1050  OldestActiveSnapshot = NULL;
1051  }
1052 
1054 }
Snapshot as_snap
Definition: snapmgr.c:184
static int32 next
Definition: blutils.c:211
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:717
static void SnapshotResetXmin(void)
Definition: snapmgr.c:980
uint32 regd_count
Definition: snapshot.h:180
void pfree(void *pointer)
Definition: mcxt.c:1031
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:193
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:186
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:190
#define Assert(condition)
Definition: c.h:732
uint32 active_count
Definition: snapshot.h:179

◆ AtSubCommit_Snapshot()

void AtSubCommit_Snapshot ( int  level)

Definition at line 1004 of file snapmgr.c.

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

Referenced by CommitSubTransaction().

1005 {
1006  ActiveSnapshotElt *active;
1007 
1008  /*
1009  * Relabel the active snapshots set in this subtransaction as though they
1010  * are owned by the parent subxact.
1011  */
1012  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1013  {
1014  if (active->as_level < level)
1015  break;
1016  active->as_level = level - 1;
1017  }
1018 }
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:186
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:190

◆ DeleteAllExportedSnapshotFiles()

void DeleteAllExportedSnapshotFiles ( void  )

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

1621 {
1622  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1623  DIR *s_dir;
1624  struct dirent *s_de;
1625 
1626  /*
1627  * Problems in reading the directory, or unlinking files, are reported at
1628  * LOG level. Since we're running in the startup process, ERROR level
1629  * would prevent database start, and it's not important enough for that.
1630  */
1632 
1633  while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1634  {
1635  if (strcmp(s_de->d_name, ".") == 0 ||
1636  strcmp(s_de->d_name, "..") == 0)
1637  continue;
1638 
1639  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1640 
1641  if (unlink(buf) != 0)
1642  ereport(LOG,
1644  errmsg("could not remove file \"%s\": %m", buf)));
1645  }
1646 
1647  FreeDir(s_dir);
1648 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2527
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:215
Definition: dirent.c:25
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:67
int errcode_for_file_access(void)
Definition: elog.c:593
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2446
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:784
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2564

◆ EstimateSnapshotSpace()

Size EstimateSnapshotSpace ( Snapshot  snapshot)

Definition at line 2048 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(), heap_parallelscan_estimate(), index_parallelscan_estimate(), index_parallelscan_initialize(), and InitializeParallelDSM().

2049 {
2050  Size size;
2051 
2052  Assert(snap != InvalidSnapshot);
2053  Assert(snap->snapshot_type == SNAPSHOT_MVCC);
2054 
2055  /* We allocate any XID arrays needed in the same palloc block. */
2056  size = add_size(sizeof(SerializedSnapshotData),
2057  mul_size(snap->xcnt, sizeof(TransactionId)));
2058  if (snap->subxcnt > 0 &&
2059  (!snap->suboverflowed || snap->takenDuringRecovery))
2060  size = add_size(size,
2061  mul_size(snap->subxcnt, sizeof(TransactionId)));
2062 
2063  return size;
2064 }
uint32 TransactionId
Definition: c.h:507
#define InvalidSnapshot
Definition: snapshot.h:104
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define Assert(condition)
Definition: c.h:732
size_t Size
Definition: c.h:466

◆ ExportSnapshot()

char* ExportSnapshot ( Snapshot  snapshot)

Definition at line 1161 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 pg_export_snapshot(), and SnapBuildExportSnapshot().

1162 {
1163  TransactionId topXid;
1164  TransactionId *children;
1165  ExportedSnapshot *esnap;
1166  int nchildren;
1167  int addTopXid;
1169  FILE *f;
1170  int i;
1171  MemoryContext oldcxt;
1172  char path[MAXPGPATH];
1173  char pathtmp[MAXPGPATH];
1174 
1175  /*
1176  * It's tempting to call RequireTransactionBlock here, since it's not very
1177  * useful to export a snapshot that will disappear immediately afterwards.
1178  * However, we haven't got enough information to do that, since we don't
1179  * know if we're at top level or not. For example, we could be inside a
1180  * plpgsql function that is going to fire off other transactions via
1181  * dblink. Rather than disallow perfectly legitimate usages, don't make a
1182  * check.
1183  *
1184  * Also note that we don't make any restriction on the transaction's
1185  * isolation level; however, importers must check the level if they are
1186  * serializable.
1187  */
1188 
1189  /*
1190  * Get our transaction ID if there is one, to include in the snapshot.
1191  */
1192  topXid = GetTopTransactionIdIfAny();
1193 
1194  /*
1195  * We cannot export a snapshot from a subtransaction because there's no
1196  * easy way for importers to verify that the same subtransaction is still
1197  * running.
1198  */
1199  if (IsSubTransaction())
1200  ereport(ERROR,
1201  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1202  errmsg("cannot export a snapshot from a subtransaction")));
1203 
1204  /*
1205  * We do however allow previous committed subtransactions to exist.
1206  * Importers of the snapshot must see them as still running, so get their
1207  * XIDs to add them to the snapshot.
1208  */
1209  nchildren = xactGetCommittedChildren(&children);
1210 
1211  /*
1212  * Generate file path for the snapshot. We start numbering of snapshots
1213  * inside the transaction from 1.
1214  */
1215  snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%08X-%d",
1217 
1218  /*
1219  * Copy the snapshot into TopTransactionContext, add it to the
1220  * exportedSnapshots list, and mark it pseudo-registered. We do this to
1221  * ensure that the snapshot's xmin is honored for the rest of the
1222  * transaction.
1223  */
1224  snapshot = CopySnapshot(snapshot);
1225 
1227  esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
1228  esnap->snapfile = pstrdup(path);
1229  esnap->snapshot = snapshot;
1231  MemoryContextSwitchTo(oldcxt);
1232 
1233  snapshot->regd_count++;
1235 
1236  /*
1237  * Fill buf with a text serialization of the snapshot, plus identification
1238  * data about this transaction. The format expected by ImportSnapshot is
1239  * pretty rigid: each line must be fieldname:value.
1240  */
1241  initStringInfo(&buf);
1242 
1243  appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->backendId, MyProc->lxid);
1244  appendStringInfo(&buf, "pid:%d\n", MyProcPid);
1245  appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1246  appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1247  appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1248 
1249  appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1250  appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1251 
1252  /*
1253  * We must include our own top transaction ID in the top-xid data, since
1254  * by definition we will still be running when the importing transaction
1255  * adopts the snapshot, but GetSnapshotData never includes our own XID in
1256  * the snapshot. (There must, therefore, be enough room to add it.)
1257  *
1258  * However, it could be that our topXid is after the xmax, in which case
1259  * we shouldn't include it because xip[] members are expected to be before
1260  * xmax. (We need not make the same check for subxip[] members, see
1261  * snapshot.h.)
1262  */
1263  addTopXid = (TransactionIdIsValid(topXid) &&
1264  TransactionIdPrecedes(topXid, snapshot->xmax)) ? 1 : 0;
1265  appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1266  for (i = 0; i < snapshot->xcnt; i++)
1267  appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1268  if (addTopXid)
1269  appendStringInfo(&buf, "xip:%u\n", topXid);
1270 
1271  /*
1272  * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1273  * we have to cope with possible overflow.
1274  */
1275  if (snapshot->suboverflowed ||
1276  snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1277  appendStringInfoString(&buf, "sof:1\n");
1278  else
1279  {
1280  appendStringInfoString(&buf, "sof:0\n");
1281  appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1282  for (i = 0; i < snapshot->subxcnt; i++)
1283  appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1284  for (i = 0; i < nchildren; i++)
1285  appendStringInfo(&buf, "sxp:%u\n", children[i]);
1286  }
1287  appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1288 
1289  /*
1290  * Now write the text representation into a file. We first write to a
1291  * ".tmp" filename, and rename to final filename if no error. This
1292  * ensures that no other backend can read an incomplete file
1293  * (ImportSnapshot won't allow it because of its valid-characters check).
1294  */
1295  snprintf(pathtmp, sizeof(pathtmp), "%s.tmp", path);
1296  if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1297  ereport(ERROR,
1299  errmsg("could not create file \"%s\": %m", pathtmp)));
1300 
1301  if (fwrite(buf.data, buf.len, 1, f) != 1)
1302  ereport(ERROR,
1304  errmsg("could not write to file \"%s\": %m", pathtmp)));
1305 
1306  /* no fsync() since file need not survive a system crash */
1307 
1308  if (FreeFile(f))
1309  ereport(ERROR,
1311  errmsg("could not write to file \"%s\": %m", pathtmp)));
1312 
1313  /*
1314  * Now that we have written everything into a .tmp file, rename the file
1315  * to remove the .tmp suffix.
1316  */
1317  if (rename(pathtmp, path) < 0)
1318  ereport(ERROR,
1320  errmsg("could not rename file \"%s\" to \"%s\": %m",
1321  pathtmp, path)));
1322 
1323  /*
1324  * The basename of the file is what we return from pg_export_snapshot().
1325  * It's already in path in a textual format and we know that the path
1326  * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1327  * and pstrdup it so as not to return the address of a local variable.
1328  */
1329  return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1330 }
int xactGetCommittedChildren(TransactionId **ptr)
Definition: xact.c:5252
int MyProcPid
Definition: globals.c:40
MemoryContext TopTransactionContext
Definition: mcxt.c:49
BackendId backendId
Definition: proc.h:113
uint32 TransactionId
Definition: c.h:507
PGPROC * MyProc
Definition: proc.c:68
char * pstrdup(const char *in)
Definition: mcxt.c:1161
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_BINARY_W
Definition: c.h:1174
bool suboverflowed
Definition: snapshot.h:163
uint32 regd_count
Definition: snapshot.h:180
static List * exportedSnapshots
Definition: snapmgr.c:225
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:215
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ERROR
Definition: elog.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
#define MAXPGPATH
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:67
int errcode_for_file_access(void)
Definition: elog.c:593
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2185
TransactionId xmax
Definition: snapshot.h:139
TransactionId xmin
Definition: snapshot.h:138
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:387
#define ereport(elevel, rest)
Definition: elog.h:141
Snapshot snapshot
Definition: snapmgr.c:221
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:149
List * lappend(List *list, void *datum)
Definition: list.c:128
char * snapfile
Definition: snapmgr.c:220
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
Oid MyDatabaseId
Definition: globals.c:85
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
bool XactReadOnly
Definition: xact.c:78
pairingheap_node ph_node
Definition: snapshot.h:181
bool takenDuringRecovery
Definition: snapshot.h:165
static int list_length(const List *l)
Definition: pg_list.h:89
int XactIsoLevel
Definition: xact.c:75
int FreeFile(FILE *file)
Definition: fd.c:2384
bool IsSubTransaction(void)
Definition: xact.c:4530
uint32 xcnt
Definition: snapshot.h:150
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1477
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define snprintf
Definition: port.h:192
TransactionId * subxip
Definition: snapshot.h:161
int32 subxcnt
Definition: snapshot.h:162
LocalTransactionId lxid
Definition: proc.h:106

◆ GetActiveSnapshot()

◆ GetCatalogSnapshot()

Snapshot GetCatalogSnapshot ( Oid  relid)

Definition at line 442 of file snapmgr.c.

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

Referenced by heap_beginscan_catalog(), process_settings(), ScanPgRelation(), systable_beginscan(), systable_beginscan_ordered(), and systable_recheck_tuple().

443 {
444  /*
445  * Return historic snapshot while we're doing logical decoding, so we can
446  * see the appropriate state of the catalog.
447  *
448  * This is the primary reason for needing to reset the system caches after
449  * finishing decoding.
450  */
452  return HistoricSnapshot;
453 
454  return GetNonHistoricCatalogSnapshot(relid);
455 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:154
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:464
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2028

◆ GetLatestSnapshot()

Snapshot GetLatestSnapshot ( void  )

Definition at line 381 of file snapmgr.c.

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

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

382 {
383  /*
384  * We might be able to relax this, but nothing that could otherwise work
385  * needs it.
386  */
387  if (IsInParallelMode())
388  elog(ERROR,
389  "cannot update SecondarySnapshot during a parallel operation");
390 
391  /*
392  * So far there are no cases requiring support for GetLatestSnapshot()
393  * during logical decoding, but it wouldn't be hard to add if required.
394  */
396 
397  /* If first call in transaction, go ahead and set the xact snapshot */
398  if (!FirstSnapshotSet)
399  return GetTransactionSnapshot();
400 
402 
403  return SecondarySnapshot;
404 }
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:306
bool IsInParallelMode(void)
Definition: xact.c:910
#define ERROR
Definition: elog.h:43
bool FirstSnapshotSet
Definition: snapmgr.c:205
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:145
#define Assert(condition)
Definition: c.h:732
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1519
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2028
#define elog(elevel,...)
Definition: elog.h:226
static Snapshot SecondarySnapshot
Definition: snapmgr.c:152

◆ GetNonHistoricCatalogSnapshot()

Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 464 of file snapmgr.c.

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

Referenced by GetCatalogSnapshot(), and ScanPgRelation().

465 {
466  /*
467  * If the caller is trying to scan a relation that has no syscache, no
468  * catcache invalidations will be sent when it is updated. For a few key
469  * relations, snapshot invalidations are sent instead. If we're trying to
470  * scan a relation for which neither catcache nor snapshot invalidations
471  * are sent, we must refresh the snapshot every time.
472  */
473  if (CatalogSnapshot &&
475  !RelationHasSysCache(relid))
477 
478  if (CatalogSnapshot == NULL)
479  {
480  /* Get new snapshot. */
482 
483  /*
484  * Make sure the catalog snapshot will be accounted for in decisions
485  * about advancing PGXACT->xmin. We could apply RegisterSnapshot, but
486  * that would result in making a physical copy, which is overkill; and
487  * it would also create a dependency on some resource owner, which we
488  * do not want for reasons explained at the head of this file. Instead
489  * just shove the CatalogSnapshot into the pairing heap manually. This
490  * has to be reversed in InvalidateCatalogSnapshot, of course.
491  *
492  * NB: it had better be impossible for this to throw error, since the
493  * CatalogSnapshot pointer is already valid.
494  */
496  }
497 
498  return CatalogSnapshot;
499 }
SnapshotData CatalogSnapshotData
Definition: snapmgr.c:146
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:1492
static Snapshot CatalogSnapshot
Definition: snapmgr.c:153
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:512
pairingheap_node ph_node
Definition: snapshot.h:181
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1469
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1519
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ GetOldestSnapshot()

Snapshot GetOldestSnapshot ( void  )

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

414 {
415  Snapshot OldestRegisteredSnapshot = NULL;
416  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
417 
419  {
420  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
422  RegisteredLSN = OldestRegisteredSnapshot->lsn;
423  }
424 
425  if (OldestActiveSnapshot != NULL)
426  {
428 
429  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
431  }
432 
433  return OldestRegisteredSnapshot;
434 }
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
Snapshot as_snap
Definition: snapmgr.c:184
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr lsn
Definition: snapshot.h:184
#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:202
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:193
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21

◆ GetOldSnapshotThresholdTimestamp()

TimestampTz GetOldSnapshotThresholdTimestamp ( void  )

Definition at line 1715 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1716 {
1717  TimestampTz threshold_timestamp;
1718 
1720  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1722 
1723  return threshold_timestamp;
1724 }
int64 TimestampTz
Definition: timestamp.h:39
slock_t mutex_threshold
Definition: snapmgr.c:91
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: snapmgr.c:92
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64

◆ GetSnapshotCurrentTimestamp()

TimestampTz GetSnapshotCurrentTimestamp ( void  )

Definition at line 1690 of file snapmgr.c.

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

Referenced by GetSnapshotData(), and TransactionIdLimitedForOldSnapshots().

1691 {
1693 
1694  /*
1695  * Don't let time move backward; if it hasn't advanced, use the old value.
1696  */
1698  if (now <= oldSnapshotControl->current_timestamp)
1700  else
1703 
1704  return now;
1705 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1592
int64 TimestampTz
Definition: timestamp.h:39
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz current_timestamp
Definition: snapmgr.c:87
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64
slock_t mutex_current
Definition: snapmgr.c:86
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1556

◆ GetTransactionSnapshot()

Snapshot GetTransactionSnapshot ( void  )

Definition at line 306 of file snapmgr.c.

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

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

307 {
308  /*
309  * Return historic snapshot if doing logical decoding. We'll never need a
310  * non-historic transaction snapshot in this (sub-)transaction, so there's
311  * no need to be careful to set one up for later calls to
312  * GetTransactionSnapshot().
313  */
315  {
317  return HistoricSnapshot;
318  }
319 
320  /* First call in transaction? */
321  if (!FirstSnapshotSet)
322  {
323  /*
324  * Don't allow catalog snapshot to be older than xact snapshot. Must
325  * do this first to allow the empty-heap Assert to succeed.
326  */
328 
330  Assert(FirstXactSnapshot == NULL);
331 
332  if (IsInParallelMode())
333  elog(ERROR,
334  "cannot take query snapshot during a parallel operation");
335 
336  /*
337  * In transaction-snapshot mode, the first snapshot must live until
338  * end of xact regardless of what the caller does with it, so we must
339  * make a copy of it rather than returning CurrentSnapshotData
340  * directly. Furthermore, if we're running in serializable mode,
341  * predicate.c needs to wrap the snapshot fetch in its own processing.
342  */
344  {
345  /* First, create the snapshot in CurrentSnapshotData */
348  else
350  /* Make a saved copy */
353  /* Mark it as "registered" in FirstXactSnapshot */
356  }
357  else
359 
360  FirstSnapshotSet = true;
361  return CurrentSnapshot;
362  }
363 
365  return CurrentSnapshot;
366 
367  /* Don't allow catalog snapshot to be older than xact snapshot. */
369 
371 
372  return CurrentSnapshot;
373 }
#define IsolationUsesXactSnapshot()
Definition: xact.h:50
static Snapshot HistoricSnapshot
Definition: snapmgr.c:154
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:144
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:212
uint32 regd_count
Definition: snapshot.h:180
static Snapshot CurrentSnapshot
Definition: snapmgr.c:151
bool IsInParallelMode(void)
Definition: xact.c:910
#define ERROR
Definition: elog.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
bool FirstSnapshotSet
Definition: snapmgr.c:205
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:512
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
pairingheap_node ph_node
Definition: snapshot.h:181
#define Assert(condition)
Definition: c.h:732
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1590
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1519
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2028
#define IsolationIsSerializable()
Definition: xact.h:51
#define elog(elevel,...)
Definition: elog.h:226
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ HistoricSnapshotActive()

bool HistoricSnapshotActive ( void  )

◆ HistoricSnapshotGetTupleCids()

struct HTAB* HistoricSnapshotGetTupleCids ( void  )

Definition at line 2034 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

2035 {
2037  return tuplecid_data;
2038 }
static HTAB * tuplecid_data
Definition: snapmgr.c:172
#define Assert(condition)
Definition: c.h:732
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2028

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1432 of file snapmgr.c.

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

Referenced by ExecSetVariableStmt().

1433 {
1434  char path[MAXPGPATH];
1435  FILE *f;
1436  struct stat stat_buf;
1437  char *filebuf;
1438  int xcnt;
1439  int i;
1440  VirtualTransactionId src_vxid;
1441  int src_pid;
1442  Oid src_dbid;
1443  int src_isolevel;
1444  bool src_readonly;
1445  SnapshotData snapshot;
1446 
1447  /*
1448  * Must be at top level of a fresh transaction. Note in particular that
1449  * we check we haven't acquired an XID --- if we have, it's conceivable
1450  * that the snapshot would show it as not running, making for very screwy
1451  * behavior.
1452  */
1453  if (FirstSnapshotSet ||
1455  IsSubTransaction())
1456  ereport(ERROR,
1457  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1458  errmsg("SET TRANSACTION SNAPSHOT must be called before any query")));
1459 
1460  /*
1461  * If we are in read committed mode then the next query would execute with
1462  * a new snapshot thus making this function call quite useless.
1463  */
1465  ereport(ERROR,
1466  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1467  errmsg("a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ")));
1468 
1469  /*
1470  * Verify the identifier: only 0-9, A-F and hyphens are allowed. We do
1471  * this mainly to prevent reading arbitrary files.
1472  */
1473  if (strspn(idstr, "0123456789ABCDEF-") != strlen(idstr))
1474  ereport(ERROR,
1475  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1476  errmsg("invalid snapshot identifier: \"%s\"", idstr)));
1477 
1478  /* OK, read the file */
1479  snprintf(path, MAXPGPATH, SNAPSHOT_EXPORT_DIR "/%s", idstr);
1480 
1481  f = AllocateFile(path, PG_BINARY_R);
1482  if (!f)
1483  ereport(ERROR,
1484  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1485  errmsg("invalid snapshot identifier: \"%s\"", idstr)));
1486 
1487  /* get the size of the file so that we know how much memory we need */
1488  if (fstat(fileno(f), &stat_buf))
1489  elog(ERROR, "could not stat file \"%s\": %m", path);
1490 
1491  /* and read the file into a palloc'd string */
1492  filebuf = (char *) palloc(stat_buf.st_size + 1);
1493  if (fread(filebuf, stat_buf.st_size, 1, f) != 1)
1494  elog(ERROR, "could not read file \"%s\": %m", path);
1495 
1496  filebuf[stat_buf.st_size] = '\0';
1497 
1498  FreeFile(f);
1499 
1500  /*
1501  * Construct a snapshot struct by parsing the file content.
1502  */
1503  memset(&snapshot, 0, sizeof(snapshot));
1504 
1505  parseVxidFromText("vxid:", &filebuf, path, &src_vxid);
1506  src_pid = parseIntFromText("pid:", &filebuf, path);
1507  /* we abuse parseXidFromText a bit here ... */
1508  src_dbid = parseXidFromText("dbid:", &filebuf, path);
1509  src_isolevel = parseIntFromText("iso:", &filebuf, path);
1510  src_readonly = parseIntFromText("ro:", &filebuf, path);
1511 
1512  snapshot.snapshot_type = SNAPSHOT_MVCC;
1513 
1514  snapshot.xmin = parseXidFromText("xmin:", &filebuf, path);
1515  snapshot.xmax = parseXidFromText("xmax:", &filebuf, path);
1516 
1517  snapshot.xcnt = xcnt = parseIntFromText("xcnt:", &filebuf, path);
1518 
1519  /* sanity-check the xid count before palloc */
1520  if (xcnt < 0 || xcnt > GetMaxSnapshotXidCount())
1521  ereport(ERROR,
1522  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1523  errmsg("invalid snapshot data in file \"%s\"", path)));
1524 
1525  snapshot.xip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1526  for (i = 0; i < xcnt; i++)
1527  snapshot.xip[i] = parseXidFromText("xip:", &filebuf, path);
1528 
1529  snapshot.suboverflowed = parseIntFromText("sof:", &filebuf, path);
1530 
1531  if (!snapshot.suboverflowed)
1532  {
1533  snapshot.subxcnt = xcnt = parseIntFromText("sxcnt:", &filebuf, path);
1534 
1535  /* sanity-check the xid count before palloc */
1536  if (xcnt < 0 || xcnt > GetMaxSnapshotSubxidCount())
1537  ereport(ERROR,
1538  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1539  errmsg("invalid snapshot data in file \"%s\"", path)));
1540 
1541  snapshot.subxip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1542  for (i = 0; i < xcnt; i++)
1543  snapshot.subxip[i] = parseXidFromText("sxp:", &filebuf, path);
1544  }
1545  else
1546  {
1547  snapshot.subxcnt = 0;
1548  snapshot.subxip = NULL;
1549  }
1550 
1551  snapshot.takenDuringRecovery = parseIntFromText("rec:", &filebuf, path);
1552 
1553  /*
1554  * Do some additional sanity checking, just to protect ourselves. We
1555  * don't trouble to check the array elements, just the most critical
1556  * fields.
1557  */
1558  if (!VirtualTransactionIdIsValid(src_vxid) ||
1559  !OidIsValid(src_dbid) ||
1560  !TransactionIdIsNormal(snapshot.xmin) ||
1561  !TransactionIdIsNormal(snapshot.xmax))
1562  ereport(ERROR,
1563  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1564  errmsg("invalid snapshot data in file \"%s\"", path)));
1565 
1566  /*
1567  * If we're serializable, the source transaction must be too, otherwise
1568  * predicate.c has problems (SxactGlobalXmin could go backwards). Also, a
1569  * non-read-only transaction can't adopt a snapshot from a read-only
1570  * transaction, as predicate.c handles the cases very differently.
1571  */
1573  {
1574  if (src_isolevel != XACT_SERIALIZABLE)
1575  ereport(ERROR,
1576  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1577  errmsg("a serializable transaction cannot import a snapshot from a non-serializable transaction")));
1578  if (src_readonly && !XactReadOnly)
1579  ereport(ERROR,
1580  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1581  errmsg("a non-read-only serializable transaction cannot import a snapshot from a read-only transaction")));
1582  }
1583 
1584  /*
1585  * We cannot import a snapshot that was taken in a different database,
1586  * because vacuum calculates OldestXmin on a per-database basis; so the
1587  * source transaction's xmin doesn't protect us from data loss. This
1588  * restriction could be removed if the source transaction were to mark its
1589  * xmin as being globally applicable. But that would require some
1590  * additional syntax, since that has to be known when the snapshot is
1591  * initially taken. (See pgsql-hackers discussion of 2011-10-21.)
1592  */
1593  if (src_dbid != MyDatabaseId)
1594  ereport(ERROR,
1595  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1596  errmsg("cannot import a snapshot from a different database")));
1597 
1598  /* OK, install the snapshot */
1599  SetTransactionSnapshot(&snapshot, &src_vxid, src_pid, NULL);
1600 }
static TransactionId parseXidFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1377
uint32 TransactionId
Definition: c.h:507
static int parseIntFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1352
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:567
#define IsolationUsesXactSnapshot()
Definition: xact.h:50
int errcode(int sqlerrcode)
Definition: elog.c:570
bool suboverflowed
Definition: snapshot.h:163
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define PG_BINARY_R
Definition: c.h:1173
#define XACT_SERIALIZABLE
Definition: xact.h:38
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:215
#define ERROR
Definition: elog.h:43
struct stat stat_buf
Definition: pg_standby.c:102
bool FirstSnapshotSet
Definition: snapmgr.c:205
#define MAXPGPATH
static void parseVxidFromText(const char *prefix, char **s, const char *filename, VirtualTransactionId *vxid)
Definition: snapmgr.c:1402
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2185
#define InvalidTransactionId
Definition: transam.h:31
SnapshotType snapshot_type
Definition: snapshot.h:125
TransactionId xmax
Definition: snapshot.h:139
TransactionId xmin
Definition: snapshot.h:138
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:387
#define ereport(elevel, rest)
Definition: elog.h:141
TransactionId * xip
Definition: snapshot.h:149
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
#define stat(a, b)
Definition: win32_port.h:264
Oid MyDatabaseId
Definition: globals.c:85
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1466
bool XactReadOnly
Definition: xact.c:78
bool takenDuringRecovery
Definition: snapshot.h:165
int FreeFile(FILE *file)
Definition: fd.c:2384
bool IsSubTransaction(void)
Definition: xact.c:4530
uint32 xcnt
Definition: snapshot.h:150
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define IsolationIsSerializable()
Definition: xact.h:51
#define elog(elevel,...)
Definition: elog.h:226
int i
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1477
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define snprintf
Definition: port.h:192
TransactionId * subxip
Definition: snapshot.h:161
int32 subxcnt
Definition: snapshot.h:162

◆ InvalidateCatalogSnapshot()

void InvalidateCatalogSnapshot ( void  )

Definition at line 512 of file snapmgr.c.

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

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

513 {
514  if (CatalogSnapshot)
515  {
517  CatalogSnapshot = NULL;
519  }
520 }
static void SnapshotResetXmin(void)
Definition: snapmgr.c:980
static Snapshot CatalogSnapshot
Definition: snapmgr.c:153
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
pairingheap_node ph_node
Definition: snapshot.h:181
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170

◆ InvalidateCatalogSnapshotConditionally()

void InvalidateCatalogSnapshotConditionally ( void  )

Definition at line 533 of file snapmgr.c.

References InvalidateCatalogSnapshot(), and pairingheap_is_singular.

Referenced by PostgresMain().

534 {
535  if (CatalogSnapshot &&
536  ActiveSnapshot == NULL &&
539 }
static Snapshot CatalogSnapshot
Definition: snapmgr.c:153
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:512
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:190
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99

◆ MaintainOldSnapshotTimeMapping()

void MaintainOldSnapshotTimeMapping ( TimestampTz  whenTaken,
TransactionId  xmin 
)

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

1853 {
1854  TimestampTz ts;
1855  TransactionId latest_xmin;
1856  TimestampTz update_ts;
1857  bool map_update_required = false;
1858 
1859  /* Never call this function when old snapshot checking is disabled. */
1861 
1862  ts = AlignTimestampToMinuteBoundary(whenTaken);
1863 
1864  /*
1865  * Keep track of the latest xmin seen by any process. Update mapping with
1866  * a new value when we have crossed a bucket boundary.
1867  */
1869  latest_xmin = oldSnapshotControl->latest_xmin;
1870  update_ts = oldSnapshotControl->next_map_update;
1871  if (ts > update_ts)
1872  {
1874  map_update_required = true;
1875  }
1876  if (TransactionIdFollows(xmin, latest_xmin))
1879 
1880  /* We only needed to update the most recent xmin value. */
1881  if (!map_update_required)
1882  return;
1883 
1884  /* No further tracking needed for 0 (used for testing). */
1885  if (old_snapshot_threshold == 0)
1886  return;
1887 
1888  /*
1889  * We don't want to do something stupid with unusual values, but we don't
1890  * want to litter the log with warnings or break otherwise normal
1891  * processing for this feature; so if something seems unreasonable, just
1892  * log at DEBUG level and return without doing anything.
1893  */
1894  if (whenTaken < 0)
1895  {
1896  elog(DEBUG1,
1897  "MaintainOldSnapshotTimeMapping called with negative whenTaken = %ld",
1898  (long) whenTaken);
1899  return;
1900  }
1901  if (!TransactionIdIsNormal(xmin))
1902  {
1903  elog(DEBUG1,
1904  "MaintainOldSnapshotTimeMapping called with xmin = %lu",
1905  (unsigned long) xmin);
1906  return;
1907  }
1908 
1909  LWLockAcquire(OldSnapshotTimeMapLock, LW_EXCLUSIVE);
1910 
1916 
1917  if (oldSnapshotControl->count_used == 0)
1918  {
1919  /* set up first entry for empty mapping */
1923  oldSnapshotControl->xid_by_minute[0] = xmin;
1924  }
1925  else if (ts < oldSnapshotControl->head_timestamp)
1926  {
1927  /* old ts; log it at DEBUG */
1928  LWLockRelease(OldSnapshotTimeMapLock);
1929  elog(DEBUG1,
1930  "MaintainOldSnapshotTimeMapping called with old whenTaken = %ld",
1931  (long) whenTaken);
1932  return;
1933  }
1934  else if (ts <= (oldSnapshotControl->head_timestamp +
1936  * USECS_PER_MINUTE)))
1937  {
1938  /* existing mapping; advance xid if possible */
1939  int bucket = (oldSnapshotControl->head_offset
1941  / USECS_PER_MINUTE))
1943 
1945  oldSnapshotControl->xid_by_minute[bucket] = xmin;
1946  }
1947  else
1948  {
1949  /* We need a new bucket, but it might not be the very next one. */
1950  int advance = ((ts - oldSnapshotControl->head_timestamp)
1951  / USECS_PER_MINUTE);
1952 
1954 
1955  if (advance >= OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1956  {
1957  /* Advance is so far that all old data is junk; start over. */
1960  oldSnapshotControl->xid_by_minute[0] = xmin;
1961  }
1962  else
1963  {
1964  /* Store the new value in one or more buckets. */
1965  int i;
1966 
1967  for (i = 0; i < advance; i++)
1968  {
1970  {
1971  /* Map full and new value replaces old head. */
1972  int old_head = oldSnapshotControl->head_offset;
1973 
1974  if (old_head == (OLD_SNAPSHOT_TIME_MAP_ENTRIES - 1))
1976  else
1977  oldSnapshotControl->head_offset = old_head + 1;
1978  oldSnapshotControl->xid_by_minute[old_head] = xmin;
1979  }
1980  else
1981  {
1982  /* Extend map to unused entry. */
1983  int new_tail = (oldSnapshotControl->head_offset
1986 
1988  oldSnapshotControl->xid_by_minute[new_tail] = xmin;
1989  }
1990  }
1991  }
1992  }
1993 
1994  LWLockRelease(OldSnapshotTimeMapLock);
1995 }
#define DEBUG1
Definition: elog.h:25
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:507
int64 TimestampTz
Definition: timestamp.h:39
#define USECS_PER_MINUTE
Definition: timestamp.h:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define SpinLockAcquire(lock)
Definition: spin.h:62
slock_t mutex_latest_xmin
Definition: snapmgr.c:88
TimestampTz next_map_update
Definition: snapmgr.c:90
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define SpinLockRelease(lock)
Definition: spin.h:64
TransactionId latest_xmin
Definition: snapmgr.c:89
#define Assert(condition)
Definition: c.h:732
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: snapmgr.c:126
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1676
#define elog(elevel,...)
Definition: elog.h:226
int old_snapshot_threshold
Definition: snapmgr.c:75
TimestampTz head_timestamp
Definition: snapmgr.c:124
int i
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 814 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(), apply_handle_delete(), apply_handle_insert(), apply_handle_update(), BuildCachedPlan(), cluster(), DefineIndex(), DoPortalRewind(), EndCopyTo(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), exec_stmt_call(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), fmgr_sql(), HandleFunctionRequest(), index_drop(), initialize_worker_spi(), LogicalRepSyncTableStart(), movedb(), ParallelWorkerMain(), PersistHoldablePortal(), PortalRunMulti(), PortalRunSelect(), PortalRunUtility(), PortalStart(), refresh_matview_datafill(), ReindexMultipleTables(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RevalidateCachedQuery(), ShutdownSQLFunction(), SPI_commit(), vacuum(), vacuum_rel(), and wait_for_relation_state_change().

815 {
816  ActiveSnapshotElt *newstack;
817 
818  newstack = ActiveSnapshot->as_next;
819 
821 
823 
824  if (ActiveSnapshot->as_snap->active_count == 0 &&
827 
829  ActiveSnapshot = newstack;
830  if (ActiveSnapshot == NULL)
831  OldestActiveSnapshot = NULL;
832 
834 }
Snapshot as_snap
Definition: snapmgr.c:184
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:717
static void SnapshotResetXmin(void)
Definition: snapmgr.c:980
uint32 regd_count
Definition: snapshot.h:180
void pfree(void *pointer)
Definition: mcxt.c:1031
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:193
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:186
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:190
#define Assert(condition)
Definition: c.h:732
uint32 active_count
Definition: snapshot.h:179

◆ PushActiveSnapshot()

void PushActiveSnapshot ( Snapshot  snapshot)

Definition at line 735 of file snapmgr.c.

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

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

736 {
737  ActiveSnapshotElt *newactive;
738 
739  Assert(snap != InvalidSnapshot);
740 
742 
743  /*
744  * Checking SecondarySnapshot is probably useless here, but it seems
745  * better to be sure.
746  */
747  if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
748  newactive->as_snap = CopySnapshot(snap);
749  else
750  newactive->as_snap = snap;
751 
752  newactive->as_next = ActiveSnapshot;
754 
755  newactive->as_snap->active_count++;
756 
757  ActiveSnapshot = newactive;
758  if (OldestActiveSnapshot == NULL)
760 }
Snapshot as_snap
Definition: snapmgr.c:184
MemoryContext TopTransactionContext
Definition: mcxt.c:49
bool copied
Definition: snapshot.h:166
static Snapshot CurrentSnapshot
Definition: snapmgr.c:151
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:193
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:186
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:190
#define InvalidSnapshot
Definition: snapshot.h:104
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:758
#define Assert(condition)
Definition: c.h:732
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
static Snapshot SecondarySnapshot
Definition: snapmgr.c:152
uint32 active_count
Definition: snapshot.h:179

◆ PushCopiedSnapshot()

void PushCopiedSnapshot ( Snapshot  snapshot)

Definition at line 771 of file snapmgr.c.

References CopySnapshot(), and PushActiveSnapshot().

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

772 {
773  PushActiveSnapshot(CopySnapshot(snapshot));
774 }
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:735
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:662

◆ RegisterSnapshot()

◆ RegisterSnapshotOnOwner()

Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 878 of file snapmgr.c.

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

Referenced by inv_open(), and RegisterSnapshot().

879 {
880  Snapshot snap;
881 
882  if (snapshot == InvalidSnapshot)
883  return InvalidSnapshot;
884 
885  /* Static snapshot? Create a persistent copy */
886  snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
887 
888  /* and tell resowner.c about it */
890  snap->regd_count++;
891  ResourceOwnerRememberSnapshot(owner, snap);
892 
893  if (snap->regd_count == 1)
895 
896  return snap;
897 }
bool copied
Definition: snapshot.h:166
void ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
Definition: resowner.c:1186
uint32 regd_count
Definition: snapshot.h:180
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
#define InvalidSnapshot
Definition: snapshot.h:104
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
pairingheap_node ph_node
Definition: snapshot.h:181
void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1197
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 2131 of file snapmgr.c.

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

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

2132 {
2133  SerializedSnapshotData serialized_snapshot;
2134  Size size;
2135  Snapshot snapshot;
2136  TransactionId *serialized_xids;
2137 
2138  memcpy(&serialized_snapshot, start_address,
2139  sizeof(SerializedSnapshotData));
2140  serialized_xids = (TransactionId *)
2141  (start_address + sizeof(SerializedSnapshotData));
2142 
2143  /* We allocate any XID arrays needed in the same palloc block. */
2144  size = sizeof(SnapshotData)
2145  + serialized_snapshot.xcnt * sizeof(TransactionId)
2146  + serialized_snapshot.subxcnt * sizeof(TransactionId);
2147 
2148  /* Copy all required fields */
2150  snapshot->snapshot_type = SNAPSHOT_MVCC;
2151  snapshot->xmin = serialized_snapshot.xmin;
2152  snapshot->xmax = serialized_snapshot.xmax;
2153  snapshot->xip = NULL;
2154  snapshot->xcnt = serialized_snapshot.xcnt;
2155  snapshot->subxip = NULL;
2156  snapshot->subxcnt = serialized_snapshot.subxcnt;
2157  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
2158  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
2159  snapshot->curcid = serialized_snapshot.curcid;
2160  snapshot->whenTaken = serialized_snapshot.whenTaken;
2161  snapshot->lsn = serialized_snapshot.lsn;
2162 
2163  /* Copy XIDs, if present. */
2164  if (serialized_snapshot.xcnt > 0)
2165  {
2166  snapshot->xip = (TransactionId *) (snapshot + 1);
2167  memcpy(snapshot->xip, serialized_xids,
2168  serialized_snapshot.xcnt * sizeof(TransactionId));
2169  }
2170 
2171  /* Copy SubXIDs, if present. */
2172  if (serialized_snapshot.subxcnt > 0)
2173  {
2174  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2175  serialized_snapshot.xcnt;
2176  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
2177  serialized_snapshot.subxcnt * sizeof(TransactionId));
2178  }
2179 
2180  /* Set the copied flag so that the caller will set refcounts correctly. */
2181  snapshot->regd_count = 0;
2182  snapshot->active_count = 0;
2183  snapshot->copied = true;
2184 
2185  return snapshot;
2186 }
MemoryContext TopTransactionContext
Definition: mcxt.c:49
uint32 TransactionId
Definition: c.h:507
bool copied
Definition: snapshot.h:166
XLogRecPtr lsn
Definition: snapshot.h:184
TimestampTz whenTaken
Definition: snapmgr.c:248
bool suboverflowed
Definition: snapshot.h:163
struct SnapshotData * Snapshot
Definition: snapshot.h:102
uint32 regd_count
Definition: snapshot.h:180
struct SnapshotData SnapshotData
SnapshotType snapshot_type
Definition: snapshot.h:125
TransactionId xmax
Definition: snapshot.h:139
TransactionId xmin
Definition: snapshot.h:138
TransactionId * xip
Definition: snapshot.h:149
TransactionId xmax
Definition: snapmgr.c:242
CommandId curcid
Definition: snapshot.h:168
bool takenDuringRecovery
Definition: snapshot.h:165
size_t Size
Definition: c.h:466
uint32 xcnt
Definition: snapshot.h:150
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
TransactionId xmin
Definition: snapmgr.c:241
TimestampTz whenTaken
Definition: snapshot.h:183
TransactionId * subxip
Definition: snapshot.h:161
uint32 active_count
Definition: snapshot.h:179
int32 subxcnt
Definition: snapshot.h:162

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  master_pgproc 
)

Definition at line 2195 of file snapmgr.c.

References InvalidPid, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2196 {
2197  SetTransactionSnapshot(snapshot, NULL, InvalidPid, master_pgproc);
2198 }
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:567
#define InvalidPid
Definition: miscadmin.h:32

◆ SerializeSnapshot()

void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

Definition at line 2072 of file snapmgr.c.

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

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

2073 {
2074  SerializedSnapshotData serialized_snapshot;
2075 
2076  Assert(snapshot->subxcnt >= 0);
2077 
2078  /* Copy all required fields */
2079  serialized_snapshot.xmin = snapshot->xmin;
2080  serialized_snapshot.xmax = snapshot->xmax;
2081  serialized_snapshot.xcnt = snapshot->xcnt;
2082  serialized_snapshot.subxcnt = snapshot->subxcnt;
2083  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2084  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2085  serialized_snapshot.curcid = snapshot->curcid;
2086  serialized_snapshot.whenTaken = snapshot->whenTaken;
2087  serialized_snapshot.lsn = snapshot->lsn;
2088 
2089  /*
2090  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2091  * taken during recovery - in that case, top-level XIDs are in subxip as
2092  * well, and we mustn't lose them.
2093  */
2094  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
2095  serialized_snapshot.subxcnt = 0;
2096 
2097  /* Copy struct to possibly-unaligned buffer */
2098  memcpy(start_address,
2099  &serialized_snapshot, sizeof(SerializedSnapshotData));
2100 
2101  /* Copy XID array */
2102  if (snapshot->xcnt > 0)
2103  memcpy((TransactionId *) (start_address +
2104  sizeof(SerializedSnapshotData)),
2105  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2106 
2107  /*
2108  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2109  * though, because it's not used anywhere in that case. Except if it's a
2110  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2111  * well in that case, so we mustn't lose them.
2112  */
2113  if (serialized_snapshot.subxcnt > 0)
2114  {
2115  Size subxipoff = sizeof(SerializedSnapshotData) +
2116  snapshot->xcnt * sizeof(TransactionId);
2117 
2118  memcpy((TransactionId *) (start_address + subxipoff),
2119  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2120  }
2121 }
uint32 TransactionId
Definition: c.h:507
XLogRecPtr lsn
Definition: snapshot.h:184
TimestampTz whenTaken
Definition: snapmgr.c:248
bool suboverflowed
Definition: snapshot.h:163
struct SerializedSnapshotData SerializedSnapshotData
TransactionId xmax
Definition: snapshot.h:139
TransactionId xmin
Definition: snapshot.h:138
TransactionId * xip
Definition: snapshot.h:149
TransactionId xmax
Definition: snapmgr.c:242
CommandId curcid
Definition: snapshot.h:168
#define Assert(condition)
Definition: c.h:732
bool takenDuringRecovery
Definition: snapshot.h:165
size_t Size
Definition: c.h:466
uint32 xcnt
Definition: snapshot.h:150
TransactionId xmin
Definition: snapmgr.c:241
TimestampTz whenTaken
Definition: snapshot.h:183
TransactionId * subxip
Definition: snapshot.h:161
int32 subxcnt
Definition: snapshot.h:162

◆ SetupHistoricSnapshot()

void SetupHistoricSnapshot ( Snapshot  snapshot_now,
struct HTAB tuplecids 
)

Definition at line 2005 of file snapmgr.c.

References Assert.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

2006 {
2007  Assert(historic_snapshot != NULL);
2008 
2009  /* setup the timetravel snapshot */
2010  HistoricSnapshot = historic_snapshot;
2011 
2012  /* setup (cmin, cmax) lookup hash */
2013  tuplecid_data = tuplecids;
2014 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:154
static HTAB * tuplecid_data
Definition: snapmgr.c:172
#define Assert(condition)
Definition: c.h:732

◆ SnapMgrInit()

void SnapMgrInit ( void  )

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

270 {
271  bool found;
272 
273  /*
274  * Create or attach to the OldSnapshotControlData structure.
275  */
277  ShmemInitStruct("OldSnapshotControlData",
278  SnapMgrShmemSize(), &found);
279 
280  if (!found)
281  {
293  }
294 }
slock_t mutex_threshold
Definition: snapmgr.c:91
#define SpinLockInit(lock)
Definition: spin.h:60
TimestampTz threshold_timestamp
Definition: snapmgr.c:92
slock_t mutex_latest_xmin
Definition: snapmgr.c:88
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
TimestampTz next_map_update
Definition: snapmgr.c:90
TimestampTz current_timestamp
Definition: snapmgr.c:87
TransactionId threshold_xid
Definition: snapmgr.c:93
#define InvalidTransactionId
Definition: transam.h:31
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
TransactionId latest_xmin
Definition: snapmgr.c:89
slock_t mutex_current
Definition: snapmgr.c:86
TimestampTz head_timestamp
Definition: snapmgr.c:124
Size SnapMgrShmemSize(void)
Definition: snapmgr.c:253

◆ SnapMgrShmemSize()

Size SnapMgrShmemSize ( void  )

Definition at line 253 of file snapmgr.c.

References add_size(), mul_size(), offsetof, old_snapshot_threshold, OLD_SNAPSHOT_TIME_MAP_ENTRIES, and OldSnapshotControlData::xid_by_minute.

Referenced by CreateSharedMemoryAndSemaphores(), and SnapMgrInit().

254 {
255  Size size;
256 
257  size = offsetof(OldSnapshotControlData, xid_by_minute);
258  if (old_snapshot_threshold > 0)
259  size = add_size(size, mul_size(sizeof(TransactionId),
261 
262  return size;
263 }
uint32 TransactionId
Definition: c.h:507
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:466
int old_snapshot_threshold
Definition: snapmgr.c:75
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
#define offsetof(type, field)
Definition: c.h:655

◆ SnapshotSetCommandId()

void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 546 of file snapmgr.c.

References SnapshotData::curcid, and FirstSnapshotSet.

Referenced by CommandCounterIncrement().

547 {
548  if (!FirstSnapshotSet)
549  return;
550 
551  if (CurrentSnapshot)
552  CurrentSnapshot->curcid = curcid;
553  if (SecondarySnapshot)
554  SecondarySnapshot->curcid = curcid;
555  /* Should we do the same with CatalogSnapshot? */
556 }
static Snapshot CurrentSnapshot
Definition: snapmgr.c:151
bool FirstSnapshotSet
Definition: snapmgr.c:205
CommandId curcid
Definition: snapshot.h:168
static Snapshot SecondarySnapshot
Definition: snapmgr.c:152

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 2021 of file snapmgr.c.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

2022 {
2023  HistoricSnapshot = NULL;
2024  tuplecid_data = NULL;
2025 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:154
static HTAB * tuplecid_data
Definition: snapmgr.c:172

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1659 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom().

1660 {
1663  return true;
1664 
1665  return false;
1666 }
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99

◆ TransactionIdLimitedForOldSnapshots()

TransactionId TransactionIdLimitedForOldSnapshots ( TransactionId  recentXmin,
Relation  relation 
)

Definition at line 1745 of file snapmgr.c.

References AlignTimestampToMinuteBoundary(), OldSnapshotControlData::count_used, GetSnapshotCurrentTimestamp(), OldSnapshotControlData::head_offset, OldSnapshotControlData::head_timestamp, OldSnapshotControlData::latest_xmin, LW_SHARED, LWLockAcquire(), LWLockRelease(), OldSnapshotControlData::mutex_latest_xmin, OldSnapshotControlData::mutex_threshold, MyPgXact, OldSnapshotControlData::next_map_update, NormalTransactionIdFollows, old_snapshot_threshold, OLD_SNAPSHOT_TIME_MAP_ENTRIES, RelationAllowsEarlyPruning, SetOldSnapshotThresholdTimestamp(), SpinLockAcquire, SpinLockRelease, OldSnapshotControlData::threshold_timestamp, OldSnapshotControlData::threshold_xid, TransactionIdFollows(), TransactionIdIsNormal, TransactionIdPrecedes(), USECS_PER_MINUTE, USECS_PER_SEC, OldSnapshotControlData::xid_by_minute, and PGXACT::xmin.

Referenced by heap_page_prune_opt(), and vacuum_set_xid_limits().

1747 {
1748  if (TransactionIdIsNormal(recentXmin)
1749  && old_snapshot_threshold >= 0
1750  && RelationAllowsEarlyPruning(relation))
1751  {
1753  TransactionId xlimit = recentXmin;
1754  TransactionId latest_xmin;
1755  TimestampTz update_ts;
1756  bool same_ts_as_threshold = false;
1757 
1759  latest_xmin = oldSnapshotControl->latest_xmin;
1760  update_ts = oldSnapshotControl->next_map_update;
1762 
1763  /*
1764  * Zero threshold always overrides to latest xmin, if valid. Without
1765  * some heuristic it will find its own snapshot too old on, for
1766  * example, a simple UPDATE -- which would make it useless for most
1767  * testing, but there is no principled way to ensure that it doesn't
1768  * fail in this way. Use a five-second delay to try to get useful
1769  * testing behavior, but this may need adjustment.
1770  */
1771  if (old_snapshot_threshold == 0)
1772  {
1773  if (TransactionIdPrecedes(latest_xmin, MyPgXact->xmin)
1774  && TransactionIdFollows(latest_xmin, xlimit))
1775  xlimit = latest_xmin;
1776 
1777  ts -= 5 * USECS_PER_SEC;
1779 
1780  return xlimit;
1781  }
1782 
1785 
1786  /* Check for fast exit without LW locking. */
1789  {
1791  same_ts_as_threshold = true;
1792  }
1794 
1795  if (!same_ts_as_threshold)
1796  {
1797  if (ts == update_ts)
1798  {
1799  xlimit = latest_xmin;
1800  if (NormalTransactionIdFollows(xlimit, recentXmin))
1802  }
1803  else
1804  {
1805  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1806 
1809  {
1810  int offset;
1811 
1812  offset = ((ts - oldSnapshotControl->head_timestamp)
1813  / USECS_PER_MINUTE);
1814  if (offset > oldSnapshotControl->count_used - 1)
1815  offset = oldSnapshotControl->count_used - 1;
1816  offset = (oldSnapshotControl->head_offset + offset)
1818  xlimit = oldSnapshotControl->xid_by_minute[offset];
1819 
1820  if (NormalTransactionIdFollows(xlimit, recentXmin))
1822  }
1823 
1824  LWLockRelease(OldSnapshotTimeMapLock);
1825  }
1826  }
1827 
1828  /*
1829  * Failsafe protection against vacuuming work of active transaction.
1830  *
1831  * This is not an assertion because we avoid the spinlock for
1832  * performance, leaving open the possibility that xlimit could advance
1833  * and be more current; but it seems prudent to apply this limit. It
1834  * might make pruning a tiny bit less aggressive than it could be, but
1835  * protects against data loss bugs.
1836  */
1837  if (TransactionIdIsNormal(latest_xmin)
1838  && TransactionIdPrecedes(latest_xmin, xlimit))
1839  xlimit = latest_xmin;
1840 
1841  if (NormalTransactionIdFollows(xlimit, recentXmin))
1842  return xlimit;
1843  }
1844 
1845  return recentXmin;
1846 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:507
#define USECS_PER_SEC
Definition: timestamp.h:94
TransactionId xmin
Definition: proc.h:228
int64 TimestampTz
Definition: timestamp.h:39
slock_t mutex_threshold
Definition: snapmgr.c:91
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38
#define USECS_PER_MINUTE
Definition: timestamp.h:93
PGXACT * MyPgXact
Definition: proc.c:69
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: snapmgr.c:92
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1690
slock_t mutex_latest_xmin
Definition: snapmgr.c:88
TimestampTz next_map_update
Definition: snapmgr.c:90
TransactionId threshold_xid
Definition: snapmgr.c:93
static void SetOldSnapshotThresholdTimestamp(TimestampTz ts, TransactionId xlimit)
Definition: snapmgr.c:1727
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define SpinLockRelease(lock)
Definition: spin.h:64
TransactionId latest_xmin
Definition: snapmgr.c:89
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: snapmgr.c:126
#define NormalTransactionIdFollows(id1, id2)
Definition: transam.h:67
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1676
int old_snapshot_threshold
Definition: snapmgr.c:75
TimestampTz head_timestamp
Definition: snapmgr.c:124
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 920 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(), PortalDrop(), PreCommit_Portals(), and UnregisterSnapshot().

921 {
922  if (snapshot == NULL)
923  return;
924 
925  Assert(snapshot->regd_count > 0);
927 
928  ResourceOwnerForgetSnapshot(owner, snapshot);
929 
930  snapshot->regd_count--;
931  if (snapshot->regd_count == 0)
933 
934  if (snapshot->regd_count == 0 && snapshot->active_count == 0)
935  {
936  FreeSnapshot(snapshot);
938  }
939 }
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:717
static void SnapshotResetXmin(void)
Definition: snapmgr.c:980
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
uint32 regd_count
Definition: snapshot.h:180
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:202
void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1206
pairingheap_node ph_node
Definition: snapshot.h:181
#define Assert(condition)
Definition: c.h:732
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170
uint32 active_count
Definition: snapshot.h:179

◆ UpdateActiveSnapshotCommandId()

void UpdateActiveSnapshotCommandId ( void  )

Definition at line 783 of file snapmgr.c.

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

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

784 {
785  CommandId save_curcid,
786  curcid;
787 
788  Assert(ActiveSnapshot != NULL);
791 
792  /*
793  * Don't allow modification of the active snapshot during parallel
794  * operation. We share the snapshot to worker backends at the beginning
795  * of parallel operation, so any change to the snapshot can lead to
796  * inconsistencies. We have other defenses against
797  * CommandCounterIncrement, but there are a few places that call this
798  * directly, so we put an additional guard here.
799  */
800  save_curcid = ActiveSnapshot->as_snap->curcid;
801  curcid = GetCurrentCommandId(false);
802  if (IsInParallelMode() && save_curcid != curcid)
803  elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
804  ActiveSnapshot->as_snap->curcid = curcid;
805 }
uint32 CommandId
Definition: c.h:521
Snapshot as_snap
Definition: snapmgr.c:184
uint32 regd_count
Definition: snapshot.h:180
bool IsInParallelMode(void)
Definition: xact.c:910
#define ERROR
Definition: elog.h:43
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:190
CommandId curcid
Definition: snapshot.h:168
#define Assert(condition)
Definition: c.h:732
#define elog(elevel,...)
Definition: elog.h:226
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:662
uint32 active_count
Definition: snapshot.h:179

◆ XactHasExportedSnapshots()

bool XactHasExportedSnapshots ( void  )

Definition at line 1607 of file snapmgr.c.

References NIL.

Referenced by PrepareTransaction().

1608 {
1609  return (exportedSnapshots != NIL);
1610 }
#define NIL
Definition: pg_list.h:69
static List * exportedSnapshots
Definition: snapmgr.c:225

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 2211 of file snapmgr.c.

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

Referenced by asyncQueueProcessPageEntries(), and HeapTupleSatisfiesMVCC().

2212 {
2213  uint32 i;
2214 
2215  /*
2216  * Make a quick range check to eliminate most XIDs without looking at the
2217  * xip arrays. Note that this is OK even if we convert a subxact XID to
2218  * its parent below, because a subxact with XID < xmin has surely also got
2219  * a parent with XID < xmin, while one with XID >= xmax must belong to a
2220  * parent that was not yet committed at the time of this snapshot.
2221  */
2222 
2223  /* Any xid < xmin is not in-progress */
2224  if (TransactionIdPrecedes(xid, snapshot->xmin))
2225  return false;
2226  /* Any xid >= xmax is in-progress */
2227  if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
2228  return true;
2229 
2230  /*
2231  * Snapshot information is stored slightly differently in snapshots taken
2232  * during recovery.
2233  */
2234  if (!snapshot->takenDuringRecovery)
2235  {
2236  /*
2237  * If the snapshot contains full subxact data, the fastest way to
2238  * check things is just to compare the given XID against both subxact
2239  * XIDs and top-level XIDs. If the snapshot overflowed, we have to
2240  * use pg_subtrans to convert a subxact XID to its parent XID, but
2241  * then we need only look at top-level XIDs not subxacts.
2242  */
2243  if (!snapshot->suboverflowed)
2244  {
2245  /* we have full data, so search subxip */
2246  int32 j;
2247 
2248  for (j = 0; j < snapshot->subxcnt; j++)
2249  {
2250  if (TransactionIdEquals(xid, snapshot->subxip[j]))
2251  return true;
2252  }
2253 
2254  /* not there, fall through to search xip[] */
2255  }
2256  else
2257  {
2258  /*
2259  * Snapshot overflowed, so convert xid to top-level. This is safe
2260  * because we eliminated too-old XIDs above.
2261  */
2262  xid = SubTransGetTopmostTransaction(xid);
2263 
2264  /*
2265  * If xid was indeed a subxact, we might now have an xid < xmin,
2266  * so recheck to avoid an array scan. No point in rechecking
2267  * xmax.
2268  */
2269  if (TransactionIdPrecedes(xid, snapshot->xmin))
2270  return false;
2271  }
2272 
2273  for (i = 0; i < snapshot->xcnt; i++)
2274  {
2275  if (TransactionIdEquals(xid, snapshot->xip[i]))
2276  return true;
2277  }
2278  }
2279  else
2280  {
2281  int32 j;
2282 
2283  /*
2284  * In recovery we store all xids in the subxact array because it is by
2285  * far the bigger array, and we mostly don't know which xids are
2286  * top-level and which are subxacts. The xip array is empty.
2287  *
2288  * We start by searching subtrans, if we overflowed.
2289  */
2290  if (snapshot->suboverflowed)
2291  {
2292  /*
2293  * Snapshot overflowed, so convert xid to top-level. This is safe
2294  * because we eliminated too-old XIDs above.
2295  */
2296  xid = SubTransGetTopmostTransaction(xid);
2297 
2298  /*
2299  * If xid was indeed a subxact, we might now have an xid < xmin,
2300  * so recheck to avoid an array scan. No point in rechecking
2301  * xmax.
2302  */
2303  if (TransactionIdPrecedes(xid, snapshot->xmin))
2304  return false;
2305  }
2306 
2307  /*
2308  * We now have either a top-level xid higher than xmin or an
2309  * indeterminate xid. We don't know whether it's top level or subxact
2310  * but it doesn't matter. If it's present, the xid is visible.
2311  */
2312  for (j = 0; j < snapshot->subxcnt; j++)
2313  {
2314  if (TransactionIdEquals(xid, snapshot->subxip[j]))
2315  return true;
2316  }
2317  }
2318 
2319  return false;
2320 }
#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:163
signed int int32
Definition: c.h:346
unsigned int uint32
Definition: c.h:358
TransactionId xmax
Definition: snapshot.h:139
TransactionId xmin
Definition: snapshot.h:138
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:149
bool takenDuringRecovery
Definition: snapshot.h:165
uint32 xcnt
Definition: snapshot.h:150
int i
TransactionId * subxip
Definition: snapshot.h:161
int32 subxcnt
Definition: snapshot.h:162

Variable Documentation

◆ CatalogSnapshotData

PGDLLIMPORT SnapshotData CatalogSnapshotData

Definition at line 146 of file snapmgr.c.

◆ FirstSnapshotSet

◆ old_snapshot_threshold

◆ RecentGlobalDataXmin

PGDLLIMPORT TransactionId RecentGlobalDataXmin

Definition at line 169 of file snapmgr.c.

Referenced by GetSnapshotData(), and heap_page_prune_opt().

◆ RecentGlobalXmin

◆ RecentXmin

◆ SnapshotAnyData

PGDLLIMPORT SnapshotData SnapshotAnyData

Definition at line 148 of file snapmgr.c.

◆ SnapshotSelfData

PGDLLIMPORT SnapshotData SnapshotSelfData

Definition at line 147 of file snapmgr.c.

◆ TransactionXmin