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))
 

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)
 
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
 

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

◆ 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:92
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:568
bool RelationHasUnloggedIndex(Relation rel)
Definition: relcache.c:6003

Definition at line 38 of file snapmgr.h.

Referenced by TestForOldSnapshot_impl(), and TransactionIdLimitedForOldSnapshots().

Function Documentation

◆ ActiveSnapshotSet()

bool ActiveSnapshotSet ( void  )

Definition at line 851 of file snapmgr.c.

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

852 {
853  return ActiveSnapshot != NULL;
854 }
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

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

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

◆ AtSubAbort_Snapshot()

void AtSubAbort_Snapshot ( int  level)

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

1024 {
1025  /* Forget the active snapshots set by this subtransaction */
1026  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
1027  {
1029 
1030  next = ActiveSnapshot->as_next;
1031 
1032  /*
1033  * Decrement the snapshot's active count. If it's still registered or
1034  * marked as active by an outer subtransaction, we can't free it yet.
1035  */
1038 
1039  if (ActiveSnapshot->as_snap->active_count == 0 &&
1042 
1043  /* and free the stack element */
1045 
1046  ActiveSnapshot = next;
1047  if (ActiveSnapshot == NULL)
1048  OldestActiveSnapshot = NULL;
1049  }
1050 
1052 }
Snapshot as_snap
Definition: snapmgr.c:182
static int32 next
Definition: blutils.c:210
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:715
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
uint32 regd_count
Definition: snapshot.h:110
void pfree(void *pointer)
Definition: mcxt.c:936
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:191
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:184
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
#define Assert(condition)
Definition: c.h:680
uint32 active_count
Definition: snapshot.h:109

◆ AtSubCommit_Snapshot()

void AtSubCommit_Snapshot ( int  level)

Definition at line 1002 of file snapmgr.c.

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

Referenced by CommitSubTransaction().

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

◆ DeleteAllExportedSnapshotFiles()

void DeleteAllExportedSnapshotFiles ( void  )

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

1617 {
1618  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1619  DIR *s_dir;
1620  struct dirent *s_de;
1621 
1622  /*
1623  * Problems in reading the directory, or unlinking files, are reported at
1624  * LOG level. Since we're running in the startup process, ERROR level
1625  * would prevent database start, and it's not important enough for that.
1626  */
1628 
1629  while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1630  {
1631  if (strcmp(s_de->d_name, ".") == 0 ||
1632  strcmp(s_de->d_name, "..") == 0)
1633  continue;
1634 
1635  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1636 
1637  if (unlink(buf) != 0)
1638  ereport(LOG,
1640  errmsg("could not remove file \"%s\": %m", buf)));
1641  }
1642 
1643  FreeDir(s_dir);
1644 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2677
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:213
Definition: dirent.c:25
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:67
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2596
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2714

◆ EstimateSnapshotSpace()

Size EstimateSnapshotSpace ( Snapshot  snapshot)

Definition at line 2044 of file snapmgr.c.

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

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

2045 {
2046  Size size;
2047 
2048  Assert(snap != InvalidSnapshot);
2049  Assert(snap->satisfies == HeapTupleSatisfiesMVCC);
2050 
2051  /* We allocate any XID arrays needed in the same palloc block. */
2052  size = add_size(sizeof(SerializedSnapshotData),
2053  mul_size(snap->xcnt, sizeof(TransactionId)));
2054  if (snap->subxcnt > 0 &&
2055  (!snap->suboverflowed || snap->takenDuringRecovery))
2056  size = add_size(size,
2057  mul_size(snap->subxcnt, sizeof(TransactionId)));
2058 
2059  return size;
2060 }
uint32 TransactionId
Definition: c.h:455
#define InvalidSnapshot
Definition: snapshot.h:25
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:680
size_t Size
Definition: c.h:414
bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:963

◆ ExportSnapshot()

char* ExportSnapshot ( Snapshot  snapshot)

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

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

◆ GetActiveSnapshot()

◆ GetCatalogSnapshot()

Snapshot GetCatalogSnapshot ( Oid  relid)

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

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

◆ GetLatestSnapshot()

Snapshot GetLatestSnapshot ( void  )

Definition at line 379 of file snapmgr.c.

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

Referenced by AlterDomainNotNull(), asyncQueueReadAllNotifications(), ATRewriteTable(), check_default_allows_bound(), 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().

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

◆ GetNonHistoricCatalogSnapshot()

Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 462 of file snapmgr.c.

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

Referenced by GetCatalogSnapshot(), and ScanPgRelation().

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

◆ GetOldestSnapshot()

Snapshot GetOldestSnapshot ( void  )

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

412 {
413  Snapshot OldestRegisteredSnapshot = NULL;
414  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
415 
417  {
418  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
420  RegisteredLSN = OldestRegisteredSnapshot->lsn;
421  }
422 
423  if (OldestActiveSnapshot != NULL)
424  {
426 
427  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
429  }
430 
431  return OldestRegisteredSnapshot;
432 }
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
Snapshot as_snap
Definition: snapmgr.c:182
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr lsn
Definition: snapshot.h:114
#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:200
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:191
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21

◆ GetOldSnapshotThresholdTimestamp()

TimestampTz GetOldSnapshotThresholdTimestamp ( void  )

Definition at line 1711 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1712 {
1713  TimestampTz threshold_timestamp;
1714 
1716  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1718 
1719  return threshold_timestamp;
1720 }
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 1686 of file snapmgr.c.

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

Referenced by GetSnapshotData(), and TransactionIdLimitedForOldSnapshots().

1687 {
1689 
1690  /*
1691  * Don't let time move backward; if it hasn't advanced, use the old value.
1692  */
1694  if (now <= oldSnapshotControl->current_timestamp)
1696  else
1699 
1700  return now;
1701 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
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:1534

◆ GetTransactionSnapshot()

Snapshot GetTransactionSnapshot ( void  )

Definition at line 304 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 _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), apply_handle_delete(), apply_handle_insert(), apply_handle_update(), BuildCachedPlan(), CheckTargetForConflictsIn(), cluster(), DefineIndex(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), 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().

305 {
306  /*
307  * Return historic snapshot if doing logical decoding. We'll never need a
308  * non-historic transaction snapshot in this (sub-)transaction, so there's
309  * no need to be careful to set one up for later calls to
310  * GetTransactionSnapshot().
311  */
313  {
315  return HistoricSnapshot;
316  }
317 
318  /* First call in transaction? */
319  if (!FirstSnapshotSet)
320  {
321  /*
322  * Don't allow catalog snapshot to be older than xact snapshot. Must
323  * do this first to allow the empty-heap Assert to succeed.
324  */
326 
328  Assert(FirstXactSnapshot == NULL);
329 
330  if (IsInParallelMode())
331  elog(ERROR,
332  "cannot take query snapshot during a parallel operation");
333 
334  /*
335  * In transaction-snapshot mode, the first snapshot must live until
336  * end of xact regardless of what the caller does with it, so we must
337  * make a copy of it rather than returning CurrentSnapshotData
338  * directly. Furthermore, if we're running in serializable mode,
339  * predicate.c needs to wrap the snapshot fetch in its own processing.
340  */
342  {
343  /* First, create the snapshot in CurrentSnapshotData */
346  else
348  /* Make a saved copy */
351  /* Mark it as "registered" in FirstXactSnapshot */
354  }
355  else
357 
358  FirstSnapshotSet = true;
359  return CurrentSnapshot;
360  }
361 
363  return CurrentSnapshot;
364 
365  /* Don't allow catalog snapshot to be older than xact snapshot. */
367 
369 
370  return CurrentSnapshot;
371 }
#define IsolationUsesXactSnapshot()
Definition: xact.h:43
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:144
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:210
uint32 regd_count
Definition: snapshot.h:110
static Snapshot CurrentSnapshot
Definition: snapmgr.c:149
bool IsInParallelMode(void)
Definition: xact.c:906
#define ERROR
Definition: elog.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
bool FirstSnapshotSet
Definition: snapmgr.c:203
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:510
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:660
pairingheap_node ph_node
Definition: snapshot.h:111
#define Assert(condition)
Definition: c.h:680
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1636
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1509
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2024
#define IsolationIsSerializable()
Definition: xact.h:44
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
#define elog
Definition: elog.h:219

◆ HistoricSnapshotActive()

bool HistoricSnapshotActive ( void  )

◆ HistoricSnapshotGetTupleCids()

struct HTAB* HistoricSnapshotGetTupleCids ( void  )

Definition at line 2030 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

2031 {
2033  return tuplecid_data;
2034 }
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define Assert(condition)
Definition: c.h:680
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2024

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

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

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

◆ InvalidateCatalogSnapshot()

void InvalidateCatalogSnapshot ( void  )

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

511 {
512  if (CatalogSnapshot)
513  {
515  CatalogSnapshot = NULL;
517  }
518 }
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
static Snapshot CatalogSnapshot
Definition: snapmgr.c:151
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
pairingheap_node ph_node
Definition: snapshot.h:111
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170

◆ InvalidateCatalogSnapshotConditionally()

void InvalidateCatalogSnapshotConditionally ( void  )

Definition at line 531 of file snapmgr.c.

References InvalidateCatalogSnapshot(), and pairingheap_is_singular.

Referenced by PostgresMain().

532 {
533  if (CatalogSnapshot &&
534  ActiveSnapshot == NULL &&
537 }
static Snapshot CatalogSnapshot
Definition: snapmgr.c:151
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:510
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99

◆ MaintainOldSnapshotTimeMapping()

void MaintainOldSnapshotTimeMapping ( TimestampTz  whenTaken,
TransactionId  xmin 
)

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

1849 {
1850  TimestampTz ts;
1851  TransactionId latest_xmin;
1852  TimestampTz update_ts;
1853  bool map_update_required = false;
1854 
1855  /* Never call this function when old snapshot checking is disabled. */
1857 
1858  ts = AlignTimestampToMinuteBoundary(whenTaken);
1859 
1860  /*
1861  * Keep track of the latest xmin seen by any process. Update mapping with
1862  * a new value when we have crossed a bucket boundary.
1863  */
1865  latest_xmin = oldSnapshotControl->latest_xmin;
1866  update_ts = oldSnapshotControl->next_map_update;
1867  if (ts > update_ts)
1868  {
1870  map_update_required = true;
1871  }
1872  if (TransactionIdFollows(xmin, latest_xmin))
1875 
1876  /* We only needed to update the most recent xmin value. */
1877  if (!map_update_required)
1878  return;
1879 
1880  /* No further tracking needed for 0 (used for testing). */
1881  if (old_snapshot_threshold == 0)
1882  return;
1883 
1884  /*
1885  * We don't want to do something stupid with unusual values, but we don't
1886  * want to litter the log with warnings or break otherwise normal
1887  * processing for this feature; so if something seems unreasonable, just
1888  * log at DEBUG level and return without doing anything.
1889  */
1890  if (whenTaken < 0)
1891  {
1892  elog(DEBUG1,
1893  "MaintainOldSnapshotTimeMapping called with negative whenTaken = %ld",
1894  (long) whenTaken);
1895  return;
1896  }
1897  if (!TransactionIdIsNormal(xmin))
1898  {
1899  elog(DEBUG1,
1900  "MaintainOldSnapshotTimeMapping called with xmin = %lu",
1901  (unsigned long) xmin);
1902  return;
1903  }
1904 
1905  LWLockAcquire(OldSnapshotTimeMapLock, LW_EXCLUSIVE);
1906 
1912 
1913  if (oldSnapshotControl->count_used == 0)
1914  {
1915  /* set up first entry for empty mapping */
1919  oldSnapshotControl->xid_by_minute[0] = xmin;
1920  }
1921  else if (ts < oldSnapshotControl->head_timestamp)
1922  {
1923  /* old ts; log it at DEBUG */
1924  LWLockRelease(OldSnapshotTimeMapLock);
1925  elog(DEBUG1,
1926  "MaintainOldSnapshotTimeMapping called with old whenTaken = %ld",
1927  (long) whenTaken);
1928  return;
1929  }
1930  else if (ts <= (oldSnapshotControl->head_timestamp +
1932  * USECS_PER_MINUTE)))
1933  {
1934  /* existing mapping; advance xid if possible */
1935  int bucket = (oldSnapshotControl->head_offset
1937  / USECS_PER_MINUTE))
1939 
1941  oldSnapshotControl->xid_by_minute[bucket] = xmin;
1942  }
1943  else
1944  {
1945  /* We need a new bucket, but it might not be the very next one. */
1946  int advance = ((ts - oldSnapshotControl->head_timestamp)
1947  / USECS_PER_MINUTE);
1948 
1950 
1951  if (advance >= OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1952  {
1953  /* Advance is so far that all old data is junk; start over. */
1956  oldSnapshotControl->xid_by_minute[0] = xmin;
1957  }
1958  else
1959  {
1960  /* Store the new value in one or more buckets. */
1961  int i;
1962 
1963  for (i = 0; i < advance; i++)
1964  {
1966  {
1967  /* Map full and new value replaces old head. */
1968  int old_head = oldSnapshotControl->head_offset;
1969 
1970  if (old_head == (OLD_SNAPSHOT_TIME_MAP_ENTRIES - 1))
1972  else
1973  oldSnapshotControl->head_offset = old_head + 1;
1974  oldSnapshotControl->xid_by_minute[old_head] = xmin;
1975  }
1976  else
1977  {
1978  /* Extend map to unused entry. */
1979  int new_tail = (oldSnapshotControl->head_offset
1982 
1984  oldSnapshotControl->xid_by_minute[new_tail] = xmin;
1985  }
1986  }
1987  }
1988  }
1989 
1990  LWLockRelease(OldSnapshotTimeMapLock);
1991 }
#define DEBUG1
Definition: elog.h:25
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:455
int64 TimestampTz
Definition: timestamp.h:39
#define USECS_PER_MINUTE
Definition: timestamp.h:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
#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:680
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: snapmgr.c:126
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1672
int old_snapshot_threshold
Definition: snapmgr.c:75
TimestampTz head_timestamp
Definition: snapmgr.c:124
int i
#define elog
Definition: elog.h:219
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 812 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(), 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(), vacuum(), vacuum_rel(), and wait_for_relation_state_change().

813 {
814  ActiveSnapshotElt *newstack;
815 
816  newstack = ActiveSnapshot->as_next;
817 
819 
821 
822  if (ActiveSnapshot->as_snap->active_count == 0 &&
825 
827  ActiveSnapshot = newstack;
828  if (ActiveSnapshot == NULL)
829  OldestActiveSnapshot = NULL;
830 
832 }
Snapshot as_snap
Definition: snapmgr.c:182
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:715
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
uint32 regd_count
Definition: snapshot.h:110
void pfree(void *pointer)
Definition: mcxt.c:936
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:191
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:184
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
#define Assert(condition)
Definition: c.h:680
uint32 active_count
Definition: snapshot.h:109

◆ PushActiveSnapshot()

void PushActiveSnapshot ( Snapshot  snapshot)

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

734 {
735  ActiveSnapshotElt *newactive;
736 
737  Assert(snap != InvalidSnapshot);
738 
740 
741  /*
742  * Checking SecondarySnapshot is probably useless here, but it seems
743  * better to be sure.
744  */
745  if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
746  newactive->as_snap = CopySnapshot(snap);
747  else
748  newactive->as_snap = snap;
749 
750  newactive->as_next = ActiveSnapshot;
752 
753  newactive->as_snap->active_count++;
754 
755  ActiveSnapshot = newactive;
756  if (OldestActiveSnapshot == NULL)
758 }
Snapshot as_snap
Definition: snapmgr.c:182
MemoryContext TopTransactionContext
Definition: mcxt.c:48
bool copied
Definition: snapshot.h:96
static Snapshot CurrentSnapshot
Definition: snapmgr.c:149
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:191
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:184
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
#define InvalidSnapshot
Definition: snapshot.h:25
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:660
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:754
#define Assert(condition)
Definition: c.h:680
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
static Snapshot SecondarySnapshot
Definition: snapmgr.c:150
uint32 active_count
Definition: snapshot.h:109

◆ PushCopiedSnapshot()

void PushCopiedSnapshot ( Snapshot  snapshot)

Definition at line 769 of file snapmgr.c.

References CopySnapshot(), and PushActiveSnapshot().

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

770 {
771  PushActiveSnapshot(CopySnapshot(snapshot));
772 }
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:733
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:660

◆ RegisterSnapshot()

◆ RegisterSnapshotOnOwner()

Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

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

877 {
878  Snapshot snap;
879 
880  if (snapshot == InvalidSnapshot)
881  return InvalidSnapshot;
882 
883  /* Static snapshot? Create a persistent copy */
884  snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
885 
886  /* and tell resowner.c about it */
888  snap->regd_count++;
889  ResourceOwnerRememberSnapshot(owner, snap);
890 
891  if (snap->regd_count == 1)
893 
894  return snap;
895 }
bool copied
Definition: snapshot.h:96
void ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
Definition: resowner.c:1129
uint32 regd_count
Definition: snapshot.h:110
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
#define InvalidSnapshot
Definition: snapshot.h:25
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:660
pairingheap_node ph_node
Definition: snapshot.h:111
void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1140
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 2127 of file snapmgr.c.

References SnapshotData::active_count, SnapshotData::copied, SnapshotData::curcid, SerializedSnapshotData::curcid, HeapTupleSatisfiesMVCC(), SnapshotData::lsn, SerializedSnapshotData::lsn, MemoryContextAlloc(), SnapshotData::regd_count, SnapshotData::satisfies, 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().

2128 {
2129  SerializedSnapshotData serialized_snapshot;
2130  Size size;
2131  Snapshot snapshot;
2132  TransactionId *serialized_xids;
2133 
2134  memcpy(&serialized_snapshot, start_address,
2135  sizeof(SerializedSnapshotData));
2136  serialized_xids = (TransactionId *)
2137  (start_address + sizeof(SerializedSnapshotData));
2138 
2139  /* We allocate any XID arrays needed in the same palloc block. */
2140  size = sizeof(SnapshotData)
2141  + serialized_snapshot.xcnt * sizeof(TransactionId)
2142  + serialized_snapshot.subxcnt * sizeof(TransactionId);
2143 
2144  /* Copy all required fields */
2146  snapshot->satisfies = HeapTupleSatisfiesMVCC;
2147  snapshot->xmin = serialized_snapshot.xmin;
2148  snapshot->xmax = serialized_snapshot.xmax;
2149  snapshot->xip = NULL;
2150  snapshot->xcnt = serialized_snapshot.xcnt;
2151  snapshot->subxip = NULL;
2152  snapshot->subxcnt = serialized_snapshot.subxcnt;
2153  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
2154  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
2155  snapshot->curcid = serialized_snapshot.curcid;
2156  snapshot->whenTaken = serialized_snapshot.whenTaken;
2157  snapshot->lsn = serialized_snapshot.lsn;
2158 
2159  /* Copy XIDs, if present. */
2160  if (serialized_snapshot.xcnt > 0)
2161  {
2162  snapshot->xip = (TransactionId *) (snapshot + 1);
2163  memcpy(snapshot->xip, serialized_xids,
2164  serialized_snapshot.xcnt * sizeof(TransactionId));
2165  }
2166 
2167  /* Copy SubXIDs, if present. */
2168  if (serialized_snapshot.subxcnt > 0)
2169  {
2170  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2171  serialized_snapshot.xcnt;
2172  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
2173  serialized_snapshot.subxcnt * sizeof(TransactionId));
2174  }
2175 
2176  /* Set the copied flag so that the caller will set refcounts correctly. */
2177  snapshot->regd_count = 0;
2178  snapshot->active_count = 0;
2179  snapshot->copied = true;
2180 
2181  return snapshot;
2182 }
SnapshotSatisfiesFunc satisfies
Definition: snapshot.h:55
MemoryContext TopTransactionContext
Definition: mcxt.c:48
uint32 TransactionId
Definition: c.h:455
bool copied
Definition: snapshot.h:96
XLogRecPtr lsn
Definition: snapshot.h:114
TimestampTz whenTaken
Definition: snapmgr.c:246
bool suboverflowed
Definition: snapshot.h:93
struct SnapshotData * Snapshot
Definition: snapshot.h:23
uint32 regd_count
Definition: snapshot.h:110
struct SnapshotData SnapshotData
TransactionId xmax
Definition: snapshot.h:69
TransactionId xmin
Definition: snapshot.h:68
TransactionId * xip
Definition: snapshot.h:79
TransactionId xmax
Definition: snapmgr.c:240
CommandId curcid
Definition: snapshot.h:98
bool takenDuringRecovery
Definition: snapshot.h:95
size_t Size
Definition: c.h:414
uint32 xcnt
Definition: snapshot.h:80
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
TransactionId xmin
Definition: snapmgr.c:239
TimestampTz whenTaken
Definition: snapshot.h:113
bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:963
TransactionId * subxip
Definition: snapshot.h:91
uint32 active_count
Definition: snapshot.h:109
int32 subxcnt
Definition: snapshot.h:92

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  master_pgproc 
)

Definition at line 2191 of file snapmgr.c.

References InvalidPid, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2192 {
2193  SetTransactionSnapshot(snapshot, NULL, InvalidPid, master_pgproc);
2194 }
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:565
#define InvalidPid
Definition: miscadmin.h:31

◆ SerializeSnapshot()

void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

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

2069 {
2070  SerializedSnapshotData serialized_snapshot;
2071 
2072  Assert(snapshot->subxcnt >= 0);
2073 
2074  /* Copy all required fields */
2075  serialized_snapshot.xmin = snapshot->xmin;
2076  serialized_snapshot.xmax = snapshot->xmax;
2077  serialized_snapshot.xcnt = snapshot->xcnt;
2078  serialized_snapshot.subxcnt = snapshot->subxcnt;
2079  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2080  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2081  serialized_snapshot.curcid = snapshot->curcid;
2082  serialized_snapshot.whenTaken = snapshot->whenTaken;
2083  serialized_snapshot.lsn = snapshot->lsn;
2084 
2085  /*
2086  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2087  * taken during recovery - in that case, top-level XIDs are in subxip as
2088  * well, and we mustn't lose them.
2089  */
2090  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
2091  serialized_snapshot.subxcnt = 0;
2092 
2093  /* Copy struct to possibly-unaligned buffer */
2094  memcpy(start_address,
2095  &serialized_snapshot, sizeof(SerializedSnapshotData));
2096 
2097  /* Copy XID array */
2098  if (snapshot->xcnt > 0)
2099  memcpy((TransactionId *) (start_address +
2100  sizeof(SerializedSnapshotData)),
2101  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2102 
2103  /*
2104  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2105  * though, because it's not used anywhere in that case. Except if it's a
2106  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2107  * well in that case, so we mustn't lose them.
2108  */
2109  if (serialized_snapshot.subxcnt > 0)
2110  {
2111  Size subxipoff = sizeof(SerializedSnapshotData) +
2112  snapshot->xcnt * sizeof(TransactionId);
2113 
2114  memcpy((TransactionId *) (start_address + subxipoff),
2115  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2116  }
2117 }
uint32 TransactionId
Definition: c.h:455
XLogRecPtr lsn
Definition: snapshot.h:114
TimestampTz whenTaken
Definition: snapmgr.c:246
bool suboverflowed
Definition: snapshot.h:93
struct SerializedSnapshotData SerializedSnapshotData
TransactionId xmax
Definition: snapshot.h:69
TransactionId xmin
Definition: snapshot.h:68
TransactionId * xip
Definition: snapshot.h:79
TransactionId xmax
Definition: snapmgr.c:240
CommandId curcid
Definition: snapshot.h:98
#define Assert(condition)
Definition: c.h:680
bool takenDuringRecovery
Definition: snapshot.h:95
size_t Size
Definition: c.h:414
uint32 xcnt
Definition: snapshot.h:80
TransactionId xmin
Definition: snapmgr.c:239
TimestampTz whenTaken
Definition: snapshot.h:113
TransactionId * subxip
Definition: snapshot.h:91
int32 subxcnt
Definition: snapshot.h:92

◆ SetupHistoricSnapshot()

void SetupHistoricSnapshot ( Snapshot  snapshot_now,
struct HTAB tuplecids 
)

Definition at line 2001 of file snapmgr.c.

References Assert.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

2002 {
2003  Assert(historic_snapshot != NULL);
2004 
2005  /* setup the timetravel snapshot */
2006  HistoricSnapshot = historic_snapshot;
2007 
2008  /* setup (cmin, cmax) lookup hash */
2009  tuplecid_data = tuplecids;
2010 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define Assert(condition)
Definition: c.h:680

◆ SnapMgrInit()

void SnapMgrInit ( void  )

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

268 {
269  bool found;
270 
271  /*
272  * Create or attach to the OldSnapshotControlData structure.
273  */
275  ShmemInitStruct("OldSnapshotControlData",
276  SnapMgrShmemSize(), &found);
277 
278  if (!found)
279  {
291  }
292 }
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:251

◆ SnapMgrShmemSize()

Size SnapMgrShmemSize ( void  )

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

252 {
253  Size size;
254 
255  size = offsetof(OldSnapshotControlData, xid_by_minute);
256  if (old_snapshot_threshold > 0)
257  size = add_size(size, mul_size(sizeof(TransactionId),
259 
260  return size;
261 }
uint32 TransactionId
Definition: c.h:455
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:414
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:603

◆ SnapshotSetCommandId()

void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 544 of file snapmgr.c.

References SnapshotData::curcid, and FirstSnapshotSet.

Referenced by CommandCounterIncrement().

545 {
546  if (!FirstSnapshotSet)
547  return;
548 
549  if (CurrentSnapshot)
550  CurrentSnapshot->curcid = curcid;
551  if (SecondarySnapshot)
552  SecondarySnapshot->curcid = curcid;
553  /* Should we do the same with CatalogSnapshot? */
554 }
static Snapshot CurrentSnapshot
Definition: snapmgr.c:149
bool FirstSnapshotSet
Definition: snapmgr.c:203
CommandId curcid
Definition: snapshot.h:98
static Snapshot SecondarySnapshot
Definition: snapmgr.c:150

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 2017 of file snapmgr.c.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

2018 {
2019  HistoricSnapshot = NULL;
2020  tuplecid_data = NULL;
2021 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
static HTAB * tuplecid_data
Definition: snapmgr.c:170

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1655 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom().

1656 {
1659  return true;
1660 
1661  return false;
1662 }
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99

◆ TransactionIdLimitedForOldSnapshots()

TransactionId TransactionIdLimitedForOldSnapshots ( TransactionId  recentXmin,
Relation  relation 
)

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

1743 {
1744  if (TransactionIdIsNormal(recentXmin)
1745  && old_snapshot_threshold >= 0
1746  && RelationAllowsEarlyPruning(relation))
1747  {
1749  TransactionId xlimit = recentXmin;
1750  TransactionId latest_xmin;
1751  TimestampTz update_ts;
1752  bool same_ts_as_threshold = false;
1753 
1755  latest_xmin = oldSnapshotControl->latest_xmin;
1756  update_ts = oldSnapshotControl->next_map_update;
1758 
1759  /*
1760  * Zero threshold always overrides to latest xmin, if valid. Without
1761  * some heuristic it will find its own snapshot too old on, for
1762  * example, a simple UPDATE -- which would make it useless for most
1763  * testing, but there is no principled way to ensure that it doesn't
1764  * fail in this way. Use a five-second delay to try to get useful
1765  * testing behavior, but this may need adjustment.
1766  */
1767  if (old_snapshot_threshold == 0)
1768  {
1769  if (TransactionIdPrecedes(latest_xmin, MyPgXact->xmin)
1770  && TransactionIdFollows(latest_xmin, xlimit))
1771  xlimit = latest_xmin;
1772 
1773  ts -= 5 * USECS_PER_SEC;
1775 
1776  return xlimit;
1777  }
1778 
1781 
1782  /* Check for fast exit without LW locking. */
1785  {
1787  same_ts_as_threshold = true;
1788  }
1790 
1791  if (!same_ts_as_threshold)
1792  {
1793  if (ts == update_ts)
1794  {
1795  xlimit = latest_xmin;
1796  if (NormalTransactionIdFollows(xlimit, recentXmin))
1798  }
1799  else
1800  {
1801  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1802 
1805  {
1806  int offset;
1807 
1808  offset = ((ts - oldSnapshotControl->head_timestamp)
1809  / USECS_PER_MINUTE);
1810  if (offset > oldSnapshotControl->count_used - 1)
1811  offset = oldSnapshotControl->count_used - 1;
1812  offset = (oldSnapshotControl->head_offset + offset)
1814  xlimit = oldSnapshotControl->xid_by_minute[offset];
1815 
1816  if (NormalTransactionIdFollows(xlimit, recentXmin))
1818  }
1819 
1820  LWLockRelease(OldSnapshotTimeMapLock);
1821  }
1822  }
1823 
1824  /*
1825  * Failsafe protection against vacuuming work of active transaction.
1826  *
1827  * This is not an assertion because we avoid the spinlock for
1828  * performance, leaving open the possibility that xlimit could advance
1829  * and be more current; but it seems prudent to apply this limit. It
1830  * might make pruning a tiny bit less aggressive than it could be, but
1831  * protects against data loss bugs.
1832  */
1833  if (TransactionIdIsNormal(latest_xmin)
1834  && TransactionIdPrecedes(latest_xmin, xlimit))
1835  xlimit = latest_xmin;
1836 
1837  if (NormalTransactionIdFollows(xlimit, recentXmin))
1838  return xlimit;
1839  }
1840 
1841  return recentXmin;
1842 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:455
#define USECS_PER_SEC
Definition: timestamp.h:94
TransactionId xmin
Definition: proc.h:225
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:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: snapmgr.c:92
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1686
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:1723
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:1118
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1672
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 918 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(), and UnregisterSnapshot().

919 {
920  if (snapshot == NULL)
921  return;
922 
923  Assert(snapshot->regd_count > 0);
925 
926  ResourceOwnerForgetSnapshot(owner, snapshot);
927 
928  snapshot->regd_count--;
929  if (snapshot->regd_count == 0)
931 
932  if (snapshot->regd_count == 0 && snapshot->active_count == 0)
933  {
934  FreeSnapshot(snapshot);
936  }
937 }
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:715
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
uint32 regd_count
Definition: snapshot.h:110
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1149
pairingheap_node ph_node
Definition: snapshot.h:111
#define Assert(condition)
Definition: c.h:680
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170
uint32 active_count
Definition: snapshot.h:109

◆ UpdateActiveSnapshotCommandId()

void UpdateActiveSnapshotCommandId ( void  )

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

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

◆ XactHasExportedSnapshots()

bool XactHasExportedSnapshots ( void  )

Definition at line 1603 of file snapmgr.c.

References NIL.

Referenced by PrepareTransaction().

1604 {
1605  return (exportedSnapshots != NIL);
1606 }
#define NIL
Definition: pg_list.h:69
static List * exportedSnapshots
Definition: snapmgr.c:223

Variable Documentation

◆ FirstSnapshotSet

◆ old_snapshot_threshold

◆ RecentGlobalDataXmin

PGDLLIMPORT TransactionId RecentGlobalDataXmin

Definition at line 167 of file snapmgr.c.

Referenced by GetSnapshotData(), and heap_page_prune_opt().

◆ RecentGlobalXmin

◆ RecentXmin

◆ TransactionXmin