PostgreSQL Source Code  git master
snapmgr.h File Reference
#include "access/transam.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, vistestp)
 
#define InitToastSnapshot(snapshotdata, l, w)
 
#define IsMVCCSnapshot(snapshot)
 

Typedefs

typedef struct GlobalVisState GlobalVisState
 

Functions

Size SnapMgrShmemSize (void)
 
void SnapMgrInit (void)
 
TimestampTz GetSnapshotCurrentTimestamp (void)
 
TimestampTz GetOldSnapshotThresholdTimestamp (void)
 
void SnapshotTooOldMagicForTest (void)
 
static bool OldSnapshotThresholdActive (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)
 
void WaitForOlderSnapshots (TransactionId limitXmin, bool progress)
 
bool ThereAreNoPriorRegisteredSnapshots (void)
 
bool TransactionIdLimitedForOldSnapshots (TransactionId recentXmin, Relation relation, TransactionId *limit_xid, TimestampTz *limit_ts)
 
void SetOldSnapshotThresholdTimestamp (TimestampTz ts, TransactionId xlimit)
 
void MaintainOldSnapshotTimeMapping (TimestampTz whenTaken, TransactionId xmin)
 
char * ExportSnapshot (Snapshot snapshot)
 
GlobalVisStateGlobalVisTestFor (Relation rel)
 
bool GlobalVisTestIsRemovableXid (GlobalVisState *state, TransactionId xid)
 
bool GlobalVisTestIsRemovableFullXid (GlobalVisState *state, FullTransactionId fxid)
 
FullTransactionId GlobalVisTestNonRemovableFullHorizon (GlobalVisState *state)
 
TransactionId GlobalVisTestNonRemovableHorizon (GlobalVisState *state)
 
bool GlobalVisCheckRemovableXid (Relation rel, TransactionId xid)
 
bool GlobalVisCheckRemovableFullXid (Relation rel, FullTransactionId fxid)
 
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 *source_pgproc)
 

Variables

PGDLLIMPORT int old_snapshot_threshold
 
bool FirstSnapshotSet
 
PGDLLIMPORT TransactionId TransactionXmin
 
PGDLLIMPORT TransactionId RecentXmin
 
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 44 of file snapmgr.h.

Referenced by index_build(), and reindex_index().

◆ InitDirtySnapshot

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

◆ InitNonVacuumableSnapshot

#define InitNonVacuumableSnapshot (   snapshotdata,
  vistestp 
)
Value:
((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
(snapshotdata).vistest = (vistestp))

Definition at line 82 of file snapmgr.h.

Referenced by get_actual_variable_endpoint(), and heap_index_delete_tuples().

◆ InitToastSnapshot

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

Definition at line 90 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

◆ RelationAllowsEarlyPruning

#define RelationAllowsEarlyPruning (   rel)
Value:
( \
RelationIsPermanent(rel) && !IsCatalogRelation(rel) \
)
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:103
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:626

Definition at line 38 of file snapmgr.h.

Referenced by TestForOldSnapshot_impl(), and TransactionIdLimitedForOldSnapshots().

◆ SnapshotAny

◆ SnapshotSelf

Typedef Documentation

◆ GlobalVisState

Definition at line 151 of file snapmgr.h.

Function Documentation

◆ ActiveSnapshotSet()

bool ActiveSnapshotSet ( void  )

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1006 of file snapmgr.c.

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

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

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

◆ AtSubAbort_Snapshot()

void AtSubAbort_Snapshot ( int  level)

Definition at line 970 of file snapmgr.c.

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

Referenced by AbortSubTransaction(), and OldSnapshotThresholdActive().

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

◆ AtSubCommit_Snapshot()

void AtSubCommit_Snapshot ( int  level)

Definition at line 949 of file snapmgr.c.

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

Referenced by CommitSubTransaction(), and OldSnapshotThresholdActive().

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

◆ DeleteAllExportedSnapshotFiles()

void DeleteAllExportedSnapshotFiles ( void  )

Definition at line 1565 of file snapmgr.c.

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

Referenced by OldSnapshotThresholdActive(), and StartupXLOG().

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

◆ EstimateSnapshotSpace()

Size EstimateSnapshotSpace ( Snapshot  snapshot)

Definition at line 2078 of file snapmgr.c.

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

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

2079 {
2080  Size size;
2081 
2082  Assert(snap != InvalidSnapshot);
2083  Assert(snap->snapshot_type == SNAPSHOT_MVCC);
2084 
2085  /* We allocate any XID arrays needed in the same palloc block. */
2086  size = add_size(sizeof(SerializedSnapshotData),
2087  mul_size(snap->xcnt, sizeof(TransactionId)));
2088  if (snap->subxcnt > 0 &&
2089  (!snap->suboverflowed || snap->takenDuringRecovery))
2090  size = add_size(size,
2091  mul_size(snap->subxcnt, sizeof(TransactionId)));
2092 
2093  return size;
2094 }
uint32 TransactionId
Definition: c.h:587
#define InvalidSnapshot
Definition: snapshot.h:123
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
#define Assert(condition)
Definition: c.h:804
size_t Size
Definition: c.h:540

◆ ExportSnapshot()

char* ExportSnapshot ( Snapshot  snapshot)

Definition at line 1106 of file snapmgr.c.

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

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

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

◆ GetActiveSnapshot()

◆ GetCatalogSnapshot()

Snapshot GetCatalogSnapshot ( Oid  relid)

Definition at line 386 of file snapmgr.c.

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

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

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

◆ GetLatestSnapshot()

Snapshot GetLatestSnapshot ( void  )

Definition at line 325 of file snapmgr.c.

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

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

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

◆ GetNonHistoricCatalogSnapshot()

Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 408 of file snapmgr.c.

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

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

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

◆ GetOldestSnapshot()

Snapshot GetOldestSnapshot ( void  )

Definition at line 357 of file snapmgr.c.

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

Referenced by init_toast_snapshot(), and OldSnapshotThresholdActive().

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

◆ GetOldSnapshotThresholdTimestamp()

TimestampTz GetOldSnapshotThresholdTimestamp ( void  )

Definition at line 1660 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

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

◆ GetSnapshotCurrentTimestamp()

TimestampTz GetSnapshotCurrentTimestamp ( void  )

Definition at line 1635 of file snapmgr.c.

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

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

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

◆ GetTransactionSnapshot()

Snapshot GetTransactionSnapshot ( void  )

Definition at line 250 of file snapmgr.c.

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

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

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

◆ GlobalVisCheckRemovableFullXid()

bool GlobalVisCheckRemovableFullXid ( Relation  rel,
FullTransactionId  fxid 
)

Definition at line 4183 of file procarray.c.

References GlobalVisTestFor(), and GlobalVisTestIsRemovableFullXid().

Referenced by _bt_pendingfsm_finalize(), BTPageIsRecyclable(), and gistPageRecyclable().

4184 {
4186 
4187  state = GlobalVisTestFor(rel);
4188 
4189  return GlobalVisTestIsRemovableFullXid(state, fxid);
4190 }
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:4089
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:3963
Definition: regguts.h:317

◆ GlobalVisCheckRemovableXid()

bool GlobalVisCheckRemovableXid ( Relation  rel,
TransactionId  xid 
)

Definition at line 4197 of file procarray.c.

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by GinPageIsRecyclable().

4198 {
4200 
4201  state = GlobalVisTestFor(rel);
4202 
4203  return GlobalVisTestIsRemovableXid(state, xid);
4204 }
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4131
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:3963
Definition: regguts.h:317

◆ GlobalVisTestFor()

GlobalVisState* GlobalVisTestFor ( Relation  rel)

Definition at line 3963 of file procarray.c.

References Assert, GlobalVisState::definitely_needed, FullTransactionIdIsValid, GlobalVisCatalogRels, GlobalVisDataRels, GlobalVisSharedRels, GlobalVisTempRels, IsCatalogRelation(), GlobalVisState::maybe_needed, RelationData::rd_rel, RecentXmin, RecoveryInProgress(), RELATION_IS_LOCAL, and RelationIsAccessibleInLogicalDecoding.

Referenced by get_actual_variable_endpoint(), GlobalVisCheckRemovableFullXid(), GlobalVisCheckRemovableXid(), heap_hot_search_buffer(), heap_index_delete_tuples(), heap_page_prune_opt(), lazy_scan_heap(), and vacuumRedirectAndPlaceholder().

3964 {
3965  bool need_shared;
3966  bool need_catalog;
3968 
3969  /* XXX: we should assert that a snapshot is pushed or registered */
3970  Assert(RecentXmin);
3971 
3972  if (!rel)
3973  need_shared = need_catalog = true;
3974  else
3975  {
3976  /*
3977  * Other kinds currently don't contain xids, nor always the necessary
3978  * logical decoding markers.
3979  */
3980  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
3981  rel->rd_rel->relkind == RELKIND_MATVIEW ||
3982  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
3983 
3984  need_shared = rel->rd_rel->relisshared || RecoveryInProgress();
3985  need_catalog = IsCatalogRelation(rel) || RelationIsAccessibleInLogicalDecoding(rel);
3986  }
3987 
3988  if (need_shared)
3989  state = &GlobalVisSharedRels;
3990  else if (need_catalog)
3991  state = &GlobalVisCatalogRels;
3992  else if (RELATION_IS_LOCAL(rel))
3993  state = &GlobalVisTempRels;
3994  else
3995  state = &GlobalVisDataRels;
3996 
3999 
4000  return state;
4001 }
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:103
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:590
TransactionId RecentXmin
Definition: snapmgr.c:113
Form_pg_class rd_rel
Definition: rel.h:110
bool RecoveryInProgress(void)
Definition: xlog.c:8237
FullTransactionId definitely_needed
Definition: procarray.c:172
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:273
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:626
#define Assert(condition)
Definition: c.h:804
Definition: regguts.h:317
FullTransactionId maybe_needed
Definition: procarray.c:175
static GlobalVisState GlobalVisTempRels
Definition: procarray.c:276
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:274
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:275

◆ GlobalVisTestIsRemovableFullXid()

bool GlobalVisTestIsRemovableFullXid ( GlobalVisState state,
FullTransactionId  fxid 
)

Definition at line 4089 of file procarray.c.

References Assert, GlobalVisState::definitely_needed, FullTransactionIdFollowsOrEquals, FullTransactionIdPrecedes, GlobalVisTestShouldUpdate(), GlobalVisUpdate(), and GlobalVisState::maybe_needed.

Referenced by GlobalVisCheckRemovableFullXid(), and GlobalVisTestIsRemovableXid().

4091 {
4092  /*
4093  * If fxid is older than maybe_needed bound, it definitely is visible to
4094  * everyone.
4095  */
4096  if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4097  return true;
4098 
4099  /*
4100  * If fxid is >= definitely_needed bound, it is very likely to still be
4101  * considered running.
4102  */
4104  return false;
4105 
4106  /*
4107  * fxid is between maybe_needed and definitely_needed, i.e. there might or
4108  * might not exist a snapshot considering fxid running. If it makes sense,
4109  * update boundaries and recheck.
4110  */
4111  if (GlobalVisTestShouldUpdate(state))
4112  {
4113  GlobalVisUpdate();
4114 
4116 
4117  return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4118  }
4119  else
4120  return false;
4121 }
FullTransactionId definitely_needed
Definition: procarray.c:172
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:4014
#define Assert(condition)
Definition: c.h:804
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
FullTransactionId maybe_needed
Definition: procarray.c:175
#define FullTransactionIdPrecedes(a, b)
Definition: transam.h:51
static void GlobalVisUpdate(void)
Definition: procarray.c:4072

◆ GlobalVisTestIsRemovableXid()

bool GlobalVisTestIsRemovableXid ( GlobalVisState state,
TransactionId  xid 
)

Definition at line 4131 of file procarray.c.

References GlobalVisState::definitely_needed, FullXidRelativeTo(), and GlobalVisTestIsRemovableFullXid().

Referenced by GlobalVisCheckRemovableXid(), heap_page_prune_opt(), heap_prune_satisfies_vacuum(), HeapTupleIsSurelyDead(), HeapTupleSatisfiesNonVacuumable(), and vacuumRedirectAndPlaceholder().

4132 {
4133  FullTransactionId fxid;
4134 
4135  /*
4136  * Convert 32 bit argument to FullTransactionId. We can do so safely
4137  * because we know the xid has to, at the very least, be between
4138  * [oldestXid, nextFullXid), i.e. within 2 billion of xid. To avoid taking
4139  * a lock to determine either, we can just compare with
4140  * state->definitely_needed, which was based on those value at the time
4141  * the current snapshot was built.
4142  */
4143  fxid = FullXidRelativeTo(state->definitely_needed, xid);
4144 
4145  return GlobalVisTestIsRemovableFullXid(state, fxid);
4146 }
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4218
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:4089
FullTransactionId definitely_needed
Definition: procarray.c:172

◆ GlobalVisTestNonRemovableFullHorizon()

FullTransactionId GlobalVisTestNonRemovableFullHorizon ( GlobalVisState state)

Definition at line 4158 of file procarray.c.

References GlobalVisTestShouldUpdate(), GlobalVisUpdate(), and GlobalVisState::maybe_needed.

Referenced by GlobalVisTestNonRemovableHorizon().

4159 {
4160  /* acquire accurate horizon if not already done */
4161  if (GlobalVisTestShouldUpdate(state))
4162  GlobalVisUpdate();
4163 
4164  return state->maybe_needed;
4165 }
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:4014
FullTransactionId maybe_needed
Definition: procarray.c:175
static void GlobalVisUpdate(void)
Definition: procarray.c:4072

◆ GlobalVisTestNonRemovableHorizon()

TransactionId GlobalVisTestNonRemovableHorizon ( GlobalVisState state)

Definition at line 4169 of file procarray.c.

References GlobalVisTestNonRemovableFullHorizon(), and XidFromFullTransactionId.

Referenced by heap_page_prune_opt(), and heap_prune_satisfies_vacuum().

4170 {
4171  FullTransactionId cutoff;
4172 
4173  cutoff = GlobalVisTestNonRemovableFullHorizon(state);
4174 
4175  return XidFromFullTransactionId(cutoff);
4176 }
#define XidFromFullTransactionId(x)
Definition: transam.h:48
FullTransactionId GlobalVisTestNonRemovableFullHorizon(GlobalVisState *state)
Definition: procarray.c:4158

◆ HistoricSnapshotActive()

bool HistoricSnapshotActive ( void  )

◆ HistoricSnapshotGetTupleCids()

struct HTAB* HistoricSnapshotGetTupleCids ( void  )

Definition at line 2064 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

2065 {
2067  return tuplecid_data;
2068 }
static HTAB * tuplecid_data
Definition: snapmgr.c:116
#define Assert(condition)
Definition: c.h:804
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2058

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1377 of file snapmgr.c.

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

Referenced by ExecSetVariableStmt(), and OldSnapshotThresholdActive().

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

◆ InvalidateCatalogSnapshot()

void InvalidateCatalogSnapshot ( void  )

Definition at line 456 of file snapmgr.c.

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

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

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

◆ InvalidateCatalogSnapshotConditionally()

void InvalidateCatalogSnapshotConditionally ( void  )

Definition at line 477 of file snapmgr.c.

References InvalidateCatalogSnapshot(), and pairingheap_is_singular.

Referenced by OldSnapshotThresholdActive(), and PostgresMain().

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

◆ MaintainOldSnapshotTimeMapping()

void MaintainOldSnapshotTimeMapping ( TimestampTz  whenTaken,
TransactionId  xmin 
)

Definition at line 1858 of file snapmgr.c.

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

Referenced by GetSnapshotDataInitOldSnapshot(), and OldSnapshotThresholdActive().

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

◆ OldSnapshotThresholdActive()

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 759 of file snapmgr.c.

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

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

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

◆ PushActiveSnapshot()

void PushActiveSnapshot ( Snapshot  snapshot)

Definition at line 680 of file snapmgr.c.

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

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

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

◆ PushCopiedSnapshot()

void PushCopiedSnapshot ( Snapshot  snapshot)

Definition at line 716 of file snapmgr.c.

References CopySnapshot(), and PushActiveSnapshot().

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

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

◆ RegisterSnapshot()

◆ RegisterSnapshotOnOwner()

Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 823 of file snapmgr.c.

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

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

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

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 2161 of file snapmgr.c.

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

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

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

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  source_pgproc 
)

Definition at line 2226 of file snapmgr.c.

References InvalidPid, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

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

◆ SerializeSnapshot()

void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

Definition at line 2102 of file snapmgr.c.

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

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

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

◆ SetOldSnapshotThresholdTimestamp()

void SetOldSnapshotThresholdTimestamp ( TimestampTz  ts,
TransactionId  xlimit 
)

Definition at line 1672 of file snapmgr.c.

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

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

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

◆ SetupHistoricSnapshot()

void SetupHistoricSnapshot ( Snapshot  snapshot_now,
struct HTAB tuplecids 
)

Definition at line 2035 of file snapmgr.c.

References Assert.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

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

◆ SnapMgrInit()

void SnapMgrInit ( void  )

Definition at line 213 of file snapmgr.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ SnapMgrShmemSize()

Size SnapMgrShmemSize ( void  )

Definition at line 197 of file snapmgr.c.

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

Referenced by CreateSharedMemoryAndSemaphores(), and SnapMgrInit().

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

◆ SnapshotSetCommandId()

void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 490 of file snapmgr.c.

References SnapshotData::curcid, and FirstSnapshotSet.

Referenced by CommandCounterIncrement(), and OldSnapshotThresholdActive().

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

◆ SnapshotTooOldMagicForTest()

void SnapshotTooOldMagicForTest ( void  )

Definition at line 1689 of file snapmgr.c.

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

Referenced by heap_page_prune_opt().

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

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 2051 of file snapmgr.c.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

2052 {
2053  HistoricSnapshot = NULL;
2054  tuplecid_data = NULL;
2055 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:105
static HTAB * tuplecid_data
Definition: snapmgr.c:116

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1604 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom(), and OldSnapshotThresholdActive().

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

◆ TransactionIdLimitedForOldSnapshots()

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

Definition at line 1751 of file snapmgr.c.

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

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

1755 {
1756  TimestampTz ts;
1757  TransactionId xlimit = recentXmin;
1758  TransactionId latest_xmin;
1759  TimestampTz next_map_update_ts;
1760  TransactionId threshold_timestamp;
1761  TransactionId threshold_xid;
1762 
1763  Assert(TransactionIdIsNormal(recentXmin));
1765  Assert(limit_ts != NULL && limit_xid != NULL);
1766 
1767  /*
1768  * TestForOldSnapshot() assumes early pruning advances the page LSN, so we
1769  * can't prune early when skipping WAL.
1770  */
1771  if (!RelationAllowsEarlyPruning(relation) || !RelationNeedsWAL(relation))
1772  return false;
1773 
1775 
1777  latest_xmin = oldSnapshotControl->latest_xmin;
1778  next_map_update_ts = oldSnapshotControl->next_map_update;
1780 
1781  /*
1782  * Zero threshold always overrides to latest xmin, if valid. Without some
1783  * heuristic it will find its own snapshot too old on, for example, a
1784  * simple UPDATE -- which would make it useless for most testing, but
1785  * there is no principled way to ensure that it doesn't fail in this way.
1786  * Use a five-second delay to try to get useful testing behavior, but this
1787  * may need adjustment.
1788  */
1789  if (old_snapshot_threshold == 0)
1790  {
1791  if (TransactionIdPrecedes(latest_xmin, MyProc->xmin)
1792  && TransactionIdFollows(latest_xmin, xlimit))
1793  xlimit = latest_xmin;
1794 
1795  ts -= 5 * USECS_PER_SEC;
1796  }
1797  else
1798  {
1801 
1802  /* Check for fast exit without LW locking. */
1804  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1805  threshold_xid = oldSnapshotControl->threshold_xid;
1807 
1808  if (ts == threshold_timestamp)
1809  {
1810  /*
1811  * Current timestamp is in same bucket as the last limit that
1812  * was applied. Reuse.
1813  */
1814  xlimit = threshold_xid;
1815  }
1816  else if (ts == next_map_update_ts)
1817  {
1818  /*
1819  * FIXME: This branch is super iffy - but that should probably
1820  * fixed separately.
1821  */
1822  xlimit = latest_xmin;
1823  }
1824  else if (GetOldSnapshotFromTimeMapping(ts, &xlimit))
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 
1842  if (TransactionIdIsValid(xlimit) &&
1843  TransactionIdFollowsOrEquals(xlimit, recentXmin))
1844  {
1845  *limit_ts = ts;
1846  *limit_xid = xlimit;
1847 
1848  return true;
1849  }
1850 
1851  return false;
1852 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:587
#define USECS_PER_SEC
Definition: timestamp.h:94
PGPROC * MyProc
Definition: proc.c:68
int64 TimestampTz
Definition: timestamp.h:39
static bool OldSnapshotThresholdActive(void)
Definition: snapmgr.h:101
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define USECS_PER_MINUTE
Definition: timestamp.h:93
static bool GetOldSnapshotFromTimeMapping(TimestampTz ts, TransactionId *xlimitp)
Definition: snapmgr.c:1707
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: old_snapshot.h:36
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1635
TimestampTz next_map_update
Definition: old_snapshot.h:34
TransactionId threshold_xid
Definition: old_snapshot.h:37
TransactionId xmin
Definition: proc.h:138
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define SpinLockRelease(lock)
Definition: spin.h:64
TransactionId latest_xmin
Definition: old_snapshot.h:33
#define Assert(condition)
Definition: c.h:804
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1621
#define RelationNeedsWAL(relation)
Definition: rel.h:570
int old_snapshot_threshold
Definition: snapmgr.c:78
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 865 of file snapmgr.c.

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

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

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

◆ UpdateActiveSnapshotCommandId()

void UpdateActiveSnapshotCommandId ( void  )

Definition at line 728 of file snapmgr.c.

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

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

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

◆ WaitForOlderSnapshots()

void WaitForOlderSnapshots ( TransactionId  limitXmin,
bool  progress 
)

Definition at line 414 of file indexcmds.c.

References BackendIdGetProc(), GetCurrentVirtualXIDs(), i, pfree(), pgstat_progress_update_param(), PGPROC::pid, PROC_IN_SAFE_IC, PROC_IN_VACUUM, PROC_IS_AUTOVACUUM, PROGRESS_WAITFOR_CURRENT_PID, PROGRESS_WAITFOR_DONE, PROGRESS_WAITFOR_TOTAL, SetInvalidVirtualTransactionId, VirtualTransactionIdEquals, VirtualTransactionIdIsValid, and VirtualXactLock().

Referenced by ATExecDetachPartitionFinalize(), DefineIndex(), OldSnapshotThresholdActive(), and ReindexRelationConcurrently().

415 {
416  int n_old_snapshots;
417  int i;
418  VirtualTransactionId *old_snapshots;
419 
420  old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
422  | PROC_IN_SAFE_IC,
423  &n_old_snapshots);
424  if (progress)
426 
427  for (i = 0; i < n_old_snapshots; i++)
428  {
429  if (!VirtualTransactionIdIsValid(old_snapshots[i]))
430  continue; /* found uninteresting in previous cycle */
431 
432  if (i > 0)
433  {
434  /* see if anything's changed ... */
435  VirtualTransactionId *newer_snapshots;
436  int n_newer_snapshots;
437  int j;
438  int k;
439 
440  newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
441  true, false,
443  | PROC_IN_SAFE_IC,
444  &n_newer_snapshots);
445  for (j = i; j < n_old_snapshots; j++)
446  {
447  if (!VirtualTransactionIdIsValid(old_snapshots[j]))
448  continue; /* found uninteresting in previous cycle */
449  for (k = 0; k < n_newer_snapshots; k++)
450  {
451  if (VirtualTransactionIdEquals(old_snapshots[j],
452  newer_snapshots[k]))
453  break;
454  }
455  if (k >= n_newer_snapshots) /* not there anymore */
456  SetInvalidVirtualTransactionId(old_snapshots[j]);
457  }
458  pfree(newer_snapshots);
459  }
460 
461  if (VirtualTransactionIdIsValid(old_snapshots[i]))
462  {
463  /* If requested, publish who we're going to wait for. */
464  if (progress)
465  {
466  PGPROC *holder = BackendIdGetProc(old_snapshots[i].backendId);
467 
468  if (holder)
470  holder->pid);
471  }
472  VirtualXactLock(old_snapshots[i], true);
473  }
474 
475  if (progress)
477  }
478 }
VirtualTransactionId * GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
Definition: procarray.c:3195
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4460
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:75
void pfree(void *pointer)
Definition: mcxt.c:1169
#define PROC_IN_VACUUM
Definition: proc.h:55
#define PROGRESS_WAITFOR_CURRENT_PID
Definition: progress.h:116
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
int progress
Definition: pgbench.c:270
#define PROC_IN_SAFE_IC
Definition: proc.h:56
void pgstat_progress_update_param(int index, int64 val)
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:78
#define PROGRESS_WAITFOR_DONE
Definition: progress.h:115
int i
#define PROGRESS_WAITFOR_TOTAL
Definition: progress.h:114
Definition: proc.h:121
int pid
Definition: proc.h:146
#define PROC_IS_AUTOVACUUM
Definition: proc.h:54
PGPROC * BackendIdGetProc(int backendID)
Definition: sinvaladt.c:376

◆ XactHasExportedSnapshots()

bool XactHasExportedSnapshots ( void  )

Definition at line 1552 of file snapmgr.c.

References NIL.

Referenced by OldSnapshotThresholdActive(), and PrepareTransaction().

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

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 2242 of file snapmgr.c.

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

Referenced by asyncQueueProcessPageEntries(), find_inheritance_children(), and HeapTupleSatisfiesMVCC().

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

Variable Documentation

◆ CatalogSnapshotData

PGDLLIMPORT SnapshotData CatalogSnapshotData

Definition at line 97 of file snapmgr.c.

◆ FirstSnapshotSet

◆ old_snapshot_threshold

◆ RecentXmin

◆ SnapshotAnyData

PGDLLIMPORT SnapshotData SnapshotAnyData

Definition at line 99 of file snapmgr.c.

◆ SnapshotSelfData

PGDLLIMPORT SnapshotData SnapshotSelfData

Definition at line 98 of file snapmgr.c.

◆ TransactionXmin