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

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 PushActiveSnapshotWithLevel (Snapshot snapshot, int snap_level)
 
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 HaveRegisteredOrActiveSnapshot (void)
 
char * ExportSnapshot (Snapshot snapshot)
 
GlobalVisStateGlobalVisTestFor (Relation rel)
 
bool GlobalVisTestIsRemovableXid (GlobalVisState *state, TransactionId xid)
 
bool GlobalVisTestIsRemovableFullXid (GlobalVisState *state, FullTransactionId fxid)
 
bool GlobalVisCheckRemovableXid (Relation rel, TransactionId xid)
 
bool GlobalVisCheckRemovableFullXid (Relation rel, FullTransactionId fxid)
 
bool XidInMVCCSnapshot (TransactionId xid, Snapshot snapshot)
 
struct HTABHistoricSnapshotGetTupleCids (void)
 
void SetupHistoricSnapshot (Snapshot historic_snapshot, 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 bool FirstSnapshotSet
 
PGDLLIMPORT TransactionId TransactionXmin
 
PGDLLIMPORT TransactionId RecentXmin
 
PGDLLIMPORT SnapshotData SnapshotSelfData
 
PGDLLIMPORT SnapshotData SnapshotAnyData
 
PGDLLIMPORT SnapshotData CatalogSnapshotData
 

Macro Definition Documentation

◆ InitDirtySnapshot

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

Definition at line 40 of file snapmgr.h.

◆ InitNonVacuumableSnapshot

#define InitNonVacuumableSnapshot (   snapshotdata,
  vistestp 
)
Value:
((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
(snapshotdata).vistest = (vistestp))
@ SNAPSHOT_NON_VACUUMABLE
Definition: snapshot.h:118

Definition at line 48 of file snapmgr.h.

◆ InitToastSnapshot

#define InitToastSnapshot (   snapshotdata,
  l,
 
)
Value:
((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \
(snapshotdata).lsn = (l), \
(snapshotdata).whenTaken = (w))
@ SNAPSHOT_TOAST
Definition: snapshot.h:74

Definition at line 56 of file snapmgr.h.

◆ IsMVCCSnapshot

#define IsMVCCSnapshot (   snapshot)
Value:
((snapshot)->snapshot_type == SNAPSHOT_MVCC || \
(snapshot)->snapshot_type == SNAPSHOT_HISTORIC_MVCC)
@ SNAPSHOT_MVCC
Definition: snapshot.h:50
@ SNAPSHOT_HISTORIC_MVCC
Definition: snapshot.h:109

Definition at line 62 of file snapmgr.h.

◆ SnapshotAny

#define SnapshotAny   (&SnapshotAnyData)

Definition at line 33 of file snapmgr.h.

◆ SnapshotSelf

#define SnapshotSelf   (&SnapshotSelfData)

Definition at line 32 of file snapmgr.h.

Typedef Documentation

◆ GlobalVisState

Definition at line 100 of file snapmgr.h.

Function Documentation

◆ ActiveSnapshotSet()

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 995 of file snapmgr.c.

996 {
997  /*
998  * In transaction-snapshot mode we must release our privately-managed
999  * reference to the transaction snapshot. We must remove it from
1000  * RegisteredSnapshots to keep the check below happy. But we don't bother
1001  * to do FreeSnapshot, for two reasons: the memory will go away with
1002  * TopTransactionContext anyway, and if someone has left the snapshot
1003  * stacked as active, we don't want the code below to be chasing through a
1004  * dangling pointer.
1005  */
1006  if (FirstXactSnapshot != NULL)
1007  {
1011  }
1012  FirstXactSnapshot = NULL;
1013 
1014  /*
1015  * If we exported any snapshots, clean them up.
1016  */
1017  if (exportedSnapshots != NIL)
1018  {
1019  ListCell *lc;
1020 
1021  /*
1022  * Get rid of the files. Unlink failure is only a WARNING because (1)
1023  * it's too late to abort the transaction, and (2) leaving a leaked
1024  * file around has little real consequence anyway.
1025  *
1026  * We also need to remove the snapshots from RegisteredSnapshots to
1027  * prevent a warning below.
1028  *
1029  * As with the FirstXactSnapshot, we don't need to free resources of
1030  * the snapshot itself as it will go away with the memory context.
1031  */
1032  foreach(lc, exportedSnapshots)
1033  {
1034  ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1035 
1036  if (unlink(esnap->snapfile))
1037  elog(WARNING, "could not unlink file \"%s\": %m",
1038  esnap->snapfile);
1039 
1041  &esnap->snapshot->ph_node);
1042  }
1043 
1045  }
1046 
1047  /* Drop catalog snapshot if any */
1049 
1050  /* On commit, complain about leftover snapshots */
1051  if (isCommit)
1052  {
1053  ActiveSnapshotElt *active;
1054 
1056  elog(WARNING, "registered snapshots seem to remain after cleanup");
1057 
1058  /* complain about unpopped active snapshots */
1059  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1060  elog(WARNING, "snapshot %p still active", active);
1061  }
1062 
1063  /*
1064  * And reset our state. We don't need to free the memory explicitly --
1065  * it'll go away with TopTransactionContext.
1066  */
1067  ActiveSnapshot = NULL;
1068  OldestActiveSnapshot = NULL;
1070 
1071  CurrentSnapshot = NULL;
1072  SecondarySnapshot = NULL;
1073 
1074  FirstSnapshotSet = false;
1075 
1076  /*
1077  * During normal commit processing, we call ProcArrayEndTransaction() to
1078  * reset the MyProc->xmin. That call happens prior to the call to
1079  * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1080  */
1081  if (resetXmin)
1083 
1084  Assert(resetXmin || MyProc->xmin == 0);
1085 }
#define Assert(condition)
Definition: c.h:849
#define WARNING
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:225
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
#define pairingheap_reset(h)
Definition: pairingheap.h:93
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:142
static Snapshot CurrentSnapshot
Definition: snapmgr.c:88
static Snapshot SecondarySnapshot
Definition: snapmgr.c:89
static List * exportedSnapshots
Definition: snapmgr.c:155
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:132
bool FirstSnapshotSet
Definition: snapmgr.c:135
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:123
static void SnapshotResetXmin(void)
Definition: snapmgr.c:914
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:422
PGPROC * MyProc
Definition: proc.c:66
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:116
char * snapfile
Definition: snapmgr.c:150
Snapshot snapshot
Definition: snapmgr.c:151
TransactionId xmin
Definition: proc.h:177
uint32 regd_count
Definition: snapshot.h:205
pairingheap_node ph_node
Definition: snapshot.h:206

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

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

◆ AtSubAbort_Snapshot()

void AtSubAbort_Snapshot ( int  level)

Definition at line 959 of file snapmgr.c.

960 {
961  /* Forget the active snapshots set by this subtransaction */
962  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
963  {
965 
967 
968  /*
969  * Decrement the snapshot's active count. If it's still registered or
970  * marked as active by an outer subtransaction, we can't free it yet.
971  */
974 
975  if (ActiveSnapshot->as_snap->active_count == 0 &&
978 
979  /* and free the stack element */
981 
983  if (ActiveSnapshot == NULL)
984  OldestActiveSnapshot = NULL;
985  }
986 
988 }
static int32 next
Definition: blutils.c:219
void pfree(void *pointer)
Definition: mcxt.c:1521
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:630
Snapshot as_snap
Definition: snapmgr.c:114
uint32 active_count
Definition: snapshot.h:204

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

Referenced by AbortSubTransaction().

◆ AtSubCommit_Snapshot()

void AtSubCommit_Snapshot ( int  level)

Definition at line 938 of file snapmgr.c.

939 {
940  ActiveSnapshotElt *active;
941 
942  /*
943  * Relabel the active snapshots set in this subtransaction as though they
944  * are owned by the parent subxact.
945  */
946  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
947  {
948  if (active->as_level < level)
949  break;
950  active->as_level = level - 1;
951  }
952 }

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

Referenced by CommitSubTransaction().

◆ DeleteAllExportedSnapshotFiles()

void DeleteAllExportedSnapshotFiles ( void  )

Definition at line 1567 of file snapmgr.c.

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

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

Referenced by StartupXLOG().

◆ EstimateSnapshotSpace()

Size EstimateSnapshotSpace ( Snapshot  snapshot)

Definition at line 1692 of file snapmgr.c.

1693 {
1694  Size size;
1695 
1696  Assert(snapshot != InvalidSnapshot);
1697  Assert(snapshot->snapshot_type == SNAPSHOT_MVCC);
1698 
1699  /* We allocate any XID arrays needed in the same palloc block. */
1701  mul_size(snapshot->xcnt, sizeof(TransactionId)));
1702  if (snapshot->subxcnt > 0 &&
1703  (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
1704  size = add_size(size,
1705  mul_size(snapshot->subxcnt, sizeof(TransactionId)));
1706 
1707  return size;
1708 }
uint32 TransactionId
Definition: c.h:643
size_t Size
Definition: c.h:596
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
static pg_noinline void Size size
Definition: slab.c:607
#define InvalidSnapshot
Definition: snapshot.h:123
int32 subxcnt
Definition: snapshot.h:181
uint32 xcnt
Definition: snapshot.h:169
SnapshotType snapshot_type
Definition: snapshot.h:144
bool suboverflowed
Definition: snapshot.h:182
bool takenDuringRecovery
Definition: snapshot.h:184

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

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

◆ ExportSnapshot()

char* ExportSnapshot ( Snapshot  snapshot)

Definition at line 1095 of file snapmgr.c.

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

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

Referenced by pg_export_snapshot(), and SnapBuildExportSnapshot().

◆ GetActiveSnapshot()

◆ GetCatalogSnapshot()

Snapshot GetCatalogSnapshot ( Oid  relid)

Definition at line 352 of file snapmgr.c.

353 {
354  /*
355  * Return historic snapshot while we're doing logical decoding, so we can
356  * see the appropriate state of the catalog.
357  *
358  * This is the primary reason for needing to reset the system caches after
359  * finishing decoding.
360  */
362  return HistoricSnapshot;
363 
364  return GetNonHistoricCatalogSnapshot(relid);
365 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:91
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1672
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:374

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

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

◆ GetLatestSnapshot()

Snapshot GetLatestSnapshot ( void  )

Definition at line 291 of file snapmgr.c.

292 {
293  /*
294  * We might be able to relax this, but nothing that could otherwise work
295  * needs it.
296  */
297  if (IsInParallelMode())
298  elog(ERROR,
299  "cannot update SecondarySnapshot during a parallel operation");
300 
301  /*
302  * So far there are no cases requiring support for GetLatestSnapshot()
303  * during logical decoding, but it wouldn't be hard to add if required.
304  */
306 
307  /* If first call in transaction, go ahead and set the xact snapshot */
308  if (!FirstSnapshotSet)
309  return GetTransactionSnapshot();
310 
312 
313  return SecondarySnapshot;
314 }
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2177
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:216
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:82
bool IsInParallelMode(void)
Definition: xact.c:1088

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

Referenced by asyncQueueReadAllNotifications(), ATRewriteTable(), check_default_partition_contents(), currtid_internal(), FindConflictTuple(), IndexCheckExclusion(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RI_Initial_Check(), RI_PartitionRemove_Check(), ri_PerformCheck(), ScanSourceDatabasePgClass(), validateDomainCheckConstraint(), validateDomainNotNullConstraint(), and validateForeignKeyConstraint().

◆ GetNonHistoricCatalogSnapshot()

Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 374 of file snapmgr.c.

375 {
376  /*
377  * If the caller is trying to scan a relation that has no syscache, no
378  * catcache invalidations will be sent when it is updated. For a few key
379  * relations, snapshot invalidations are sent instead. If we're trying to
380  * scan a relation for which neither catcache nor snapshot invalidations
381  * are sent, we must refresh the snapshot every time.
382  */
383  if (CatalogSnapshot &&
385  !RelationHasSysCache(relid))
387 
388  if (CatalogSnapshot == NULL)
389  {
390  /* Get new snapshot. */
392 
393  /*
394  * Make sure the catalog snapshot will be accounted for in decisions
395  * about advancing PGPROC->xmin. We could apply RegisterSnapshot, but
396  * that would result in making a physical copy, which is overkill; and
397  * it would also create a dependency on some resource owner, which we
398  * do not want for reasons explained at the head of this file. Instead
399  * just shove the CatalogSnapshot into the pairing heap manually. This
400  * has to be reversed in InvalidateCatalogSnapshot, of course.
401  *
402  * NB: it had better be impossible for this to throw error, since the
403  * CatalogSnapshot pointer is already valid.
404  */
406  }
407 
408  return CatalogSnapshot;
409 }
SnapshotData CatalogSnapshotData
Definition: snapmgr.c:83
static Snapshot CatalogSnapshot
Definition: snapmgr.c:90
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:740
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:717

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

Referenced by GetCatalogSnapshot(), and ScanPgRelation().

◆ GetOldestSnapshot()

Snapshot GetOldestSnapshot ( void  )

Definition at line 323 of file snapmgr.c.

324 {
325  Snapshot OldestRegisteredSnapshot = NULL;
326  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
327 
329  {
330  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
332  RegisteredLSN = OldestRegisteredSnapshot->lsn;
333  }
334 
335  if (OldestActiveSnapshot != NULL)
336  {
338 
339  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
341  }
342 
343  return OldestRegisteredSnapshot;
344 }
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
#define pairingheap_container(type, membername, ptr)
Definition: pairingheap.h:43
XLogRecPtr lsn
Definition: snapshot.h:209
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

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

Referenced by init_toast_snapshot().

◆ GetTransactionSnapshot()

Snapshot GetTransactionSnapshot ( void  )

Definition at line 216 of file snapmgr.c.

217 {
218  /*
219  * Return historic snapshot if doing logical decoding. We'll never need a
220  * non-historic transaction snapshot in this (sub-)transaction, so there's
221  * no need to be careful to set one up for later calls to
222  * GetTransactionSnapshot().
223  */
225  {
227  return HistoricSnapshot;
228  }
229 
230  /* First call in transaction? */
231  if (!FirstSnapshotSet)
232  {
233  /*
234  * Don't allow catalog snapshot to be older than xact snapshot. Must
235  * do this first to allow the empty-heap Assert to succeed.
236  */
238 
240  Assert(FirstXactSnapshot == NULL);
241 
242  if (IsInParallelMode())
243  elog(ERROR,
244  "cannot take query snapshot during a parallel operation");
245 
246  /*
247  * In transaction-snapshot mode, the first snapshot must live until
248  * end of xact regardless of what the caller does with it, so we must
249  * make a copy of it rather than returning CurrentSnapshotData
250  * directly. Furthermore, if we're running in serializable mode,
251  * predicate.c needs to wrap the snapshot fetch in its own processing.
252  */
254  {
255  /* First, create the snapshot in CurrentSnapshotData */
258  else
260  /* Make a saved copy */
263  /* Mark it as "registered" in FirstXactSnapshot */
266  }
267  else
269 
270  FirstSnapshotSet = true;
271  return CurrentSnapshot;
272  }
273 
275  return CurrentSnapshot;
276 
277  /* Don't allow catalog snapshot to be older than xact snapshot. */
279 
281 
282  return CurrentSnapshot;
283 }
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1672
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:81
#define IsolationUsesXactSnapshot()
Definition: xact.h:51
#define IsolationIsSerializable()
Definition: xact.h:52

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

Referenced by _brin_begin_parallel(), _bt_begin_parallel(), _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), begin_replication_step(), bt_check_every_level(), BuildCachedPlan(), CheckTargetForConflictsIn(), cluster_multiple_rels(), DefineIndex(), EnsurePortalSnapshotExists(), EventTriggerOnLogin(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), execute_sql_string(), ExecuteCallStmt(), fmgr_sql(), get_database_list(), get_subscription_list(), GetLatestSnapshot(), HandleFunctionRequest(), heapam_index_build_range_scan(), index_drop(), initialize_worker_spi(), InitializeParallelDSM(), InitPostgres(), LogicalRepSyncTableStart(), pg_get_constraintdef_worker(), PortalRunMulti(), PortalRunUtility(), PortalStart(), PreCommit_on_commit_actions(), ReindexMultipleInternal(), ReindexRelationConcurrently(), RemoveTempRelationsCallback(), RevalidateCachedQuery(), ri_PerformCheck(), SPI_cursor_open_internal(), vacuum(), vacuum_rel(), verify_heapam(), worker_spi_main(), and XidIsConcurrent().

◆ GlobalVisCheckRemovableFullXid()

bool GlobalVisCheckRemovableFullXid ( Relation  rel,
FullTransactionId  fxid 
)

Definition at line 4290 of file procarray.c.

4291 {
4293 
4294  state = GlobalVisTestFor(rel);
4295 
4296  return GlobalVisTestIsRemovableFullXid(state, fxid);
4297 }
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:4226
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:4111
Definition: regguts.h:323

References GlobalVisTestFor(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisCheckRemovableXid()

bool GlobalVisCheckRemovableXid ( Relation  rel,
TransactionId  xid 
)

Definition at line 4304 of file procarray.c.

4305 {
4307 
4308  state = GlobalVisTestFor(rel);
4309 
4310  return GlobalVisTestIsRemovableXid(state, xid);
4311 }
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4268

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by GinPageIsRecyclable().

◆ GlobalVisTestFor()

GlobalVisState* GlobalVisTestFor ( Relation  rel)

Definition at line 4111 of file procarray.c.

4112 {
4113  GlobalVisState *state = NULL;
4114 
4115  /* XXX: we should assert that a snapshot is pushed or registered */
4116  Assert(RecentXmin);
4117 
4118  switch (GlobalVisHorizonKindForRel(rel))
4119  {
4120  case VISHORIZON_SHARED:
4122  break;
4123  case VISHORIZON_CATALOG:
4125  break;
4126  case VISHORIZON_DATA:
4128  break;
4129  case VISHORIZON_TEMP:
4131  break;
4132  }
4133 
4134  Assert(FullTransactionIdIsValid(state->definitely_needed) &&
4135  FullTransactionIdIsValid(state->maybe_needed));
4136 
4137  return state;
4138 }
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:299
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:297
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:298
static GlobalVisState GlobalVisTempRels
Definition: procarray.c:300
@ VISHORIZON_SHARED
Definition: procarray.c:251
@ VISHORIZON_DATA
Definition: procarray.c:253
@ VISHORIZON_CATALOG
Definition: procarray.c:252
@ VISHORIZON_TEMP
Definition: procarray.c:254
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition: procarray.c:1971
TransactionId RecentXmin
Definition: snapmgr.c:99
#define FullTransactionIdIsValid(x)
Definition: transam.h:55

References Assert, FullTransactionIdIsValid, GlobalVisCatalogRels, GlobalVisDataRels, GlobalVisHorizonKindForRel(), GlobalVisSharedRels, GlobalVisTempRels, RecentXmin, VISHORIZON_CATALOG, VISHORIZON_DATA, VISHORIZON_SHARED, and VISHORIZON_TEMP.

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

◆ GlobalVisTestIsRemovableFullXid()

bool GlobalVisTestIsRemovableFullXid ( GlobalVisState state,
FullTransactionId  fxid 
)

Definition at line 4226 of file procarray.c.

4228 {
4229  /*
4230  * If fxid is older than maybe_needed bound, it definitely is visible to
4231  * everyone.
4232  */
4233  if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4234  return true;
4235 
4236  /*
4237  * If fxid is >= definitely_needed bound, it is very likely to still be
4238  * considered running.
4239  */
4240  if (FullTransactionIdFollowsOrEquals(fxid, state->definitely_needed))
4241  return false;
4242 
4243  /*
4244  * fxid is between maybe_needed and definitely_needed, i.e. there might or
4245  * might not exist a snapshot considering fxid running. If it makes sense,
4246  * update boundaries and recheck.
4247  */
4249  {
4250  GlobalVisUpdate();
4251 
4252  Assert(FullTransactionIdPrecedes(fxid, state->definitely_needed));
4253 
4254  return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4255  }
4256  else
4257  return false;
4258 }
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:4151
static void GlobalVisUpdate(void)
Definition: procarray.c:4209
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
#define FullTransactionIdPrecedes(a, b)
Definition: transam.h:51

References Assert, FullTransactionIdFollowsOrEquals, FullTransactionIdPrecedes, GlobalVisTestShouldUpdate(), and GlobalVisUpdate().

Referenced by GlobalVisCheckRemovableFullXid(), and GlobalVisTestIsRemovableXid().

◆ GlobalVisTestIsRemovableXid()

bool GlobalVisTestIsRemovableXid ( GlobalVisState state,
TransactionId  xid 
)

Definition at line 4268 of file procarray.c.

4269 {
4270  FullTransactionId fxid;
4271 
4272  /*
4273  * Convert 32 bit argument to FullTransactionId. We can do so safely
4274  * because we know the xid has to, at the very least, be between
4275  * [oldestXid, nextXid), i.e. within 2 billion of xid. To avoid taking a
4276  * lock to determine either, we can just compare with
4277  * state->definitely_needed, which was based on those value at the time
4278  * the current snapshot was built.
4279  */
4280  fxid = FullXidRelativeTo(state->definitely_needed, xid);
4281 
4282  return GlobalVisTestIsRemovableFullXid(state, fxid);
4283 }
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4325

References FullXidRelativeTo(), and GlobalVisTestIsRemovableFullXid().

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

◆ HaveRegisteredOrActiveSnapshot()

bool HaveRegisteredOrActiveSnapshot ( void  )

Definition at line 1624 of file snapmgr.c.

1625 {
1626  if (ActiveSnapshot != NULL)
1627  return true;
1628 
1629  /*
1630  * The catalog snapshot is in RegisteredSnapshots when valid, but can be
1631  * removed at any time due to invalidation processing. If explicitly
1632  * registered more than one snapshot has to be in RegisteredSnapshots.
1633  */
1634  if (CatalogSnapshot != NULL &&
1636  return false;
1637 
1639 }
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99

References ActiveSnapshot, CatalogSnapshot, pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by init_toast_snapshot(), and SnapBuildInitialSnapshot().

◆ HistoricSnapshotActive()

◆ HistoricSnapshotGetTupleCids()

struct HTAB* HistoricSnapshotGetTupleCids ( void  )

Definition at line 1678 of file snapmgr.c.

1679 {
1681  return tuplecid_data;
1682 }
static HTAB * tuplecid_data
Definition: snapmgr.c:102

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1367 of file snapmgr.c.

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

References AllocateFile(), elog, ereport, errcode(), errcode_for_file_access(), 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().

◆ InvalidateCatalogSnapshot()

◆ InvalidateCatalogSnapshotConditionally()

void InvalidateCatalogSnapshotConditionally ( void  )

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 743 of file snapmgr.c.

744 {
745  ActiveSnapshotElt *newstack;
746 
747  newstack = ActiveSnapshot->as_next;
748 
750 
752 
753  if (ActiveSnapshot->as_snap->active_count == 0 &&
756 
758  ActiveSnapshot = newstack;
759  if (ActiveSnapshot == NULL)
760  OldestActiveSnapshot = NULL;
761 
763 }

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

Referenced by _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), ATExecDetachPartition(), BuildCachedPlan(), cluster_multiple_rels(), DefineIndex(), DoPortalRewind(), end_replication_step(), EndCopyTo(), EventTriggerOnLogin(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), ExecCreateTableAs(), execute_sql_string(), ExecuteCallStmt(), ExplainOnePlan(), FindConflictTuple(), fmgr_sql(), ForgetPortalSnapshots(), HandleFunctionRequest(), index_drop(), initialize_worker_spi(), LogicalRepSyncTableStart(), movedb(), ParallelWorkerMain(), PersistHoldablePortal(), PortalRunMulti(), PortalRunSelect(), PortalRunUtility(), PortalStart(), PreCommit_on_commit_actions(), refresh_matview_datafill(), ReindexMultipleInternal(), ReindexRelationConcurrently(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RemoveTempRelationsCallback(), RevalidateCachedQuery(), ShutdownSQLFunction(), vacuum(), vacuum_rel(), and worker_spi_main().

◆ PushActiveSnapshot()

◆ PushActiveSnapshotWithLevel()

void PushActiveSnapshotWithLevel ( Snapshot  snapshot,
int  snap_level 
)

Definition at line 662 of file snapmgr.c.

663 {
664  ActiveSnapshotElt *newactive;
665 
666  Assert(snapshot != InvalidSnapshot);
667  Assert(ActiveSnapshot == NULL || snap_level >= ActiveSnapshot->as_level);
668 
670 
671  /*
672  * Checking SecondarySnapshot is probably useless here, but it seems
673  * better to be sure.
674  */
675  if (snapshot == CurrentSnapshot || snapshot == SecondarySnapshot ||
676  !snapshot->copied)
677  newactive->as_snap = CopySnapshot(snapshot);
678  else
679  newactive->as_snap = snapshot;
680 
681  newactive->as_next = ActiveSnapshot;
682  newactive->as_level = snap_level;
683 
684  newactive->as_snap->active_count++;
685 
686  ActiveSnapshot = newactive;
687  if (OldestActiveSnapshot == NULL)
689 }
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
bool copied
Definition: snapshot.h:185

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

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

◆ PushCopiedSnapshot()

void PushCopiedSnapshot ( Snapshot  snapshot)

Definition at line 700 of file snapmgr.c.

701 {
702  PushActiveSnapshot(CopySnapshot(snapshot));
703 }
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:648

References CopySnapshot(), and PushActiveSnapshot().

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

◆ RegisterSnapshot()

◆ RegisterSnapshotOnOwner()

Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 807 of file snapmgr.c.

808 {
809  Snapshot snap;
810 
811  if (snapshot == InvalidSnapshot)
812  return InvalidSnapshot;
813 
814  /* Static snapshot? Create a persistent copy */
815  snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
816 
817  /* and tell resowner.c about it */
818  ResourceOwnerEnlarge(owner);
819  snap->regd_count++;
820  ResourceOwnerRememberSnapshot(owner, snap);
821 
822  if (snap->regd_count == 1)
824 
825  return snap;
826 }
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442
static void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snap)
Definition: snapmgr.c:177

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

Referenced by be_lo_open(), and RegisterSnapshot().

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 1775 of file snapmgr.c.

1776 {
1777  SerializedSnapshotData serialized_snapshot;
1778  Size size;
1779  Snapshot snapshot;
1780  TransactionId *serialized_xids;
1781 
1782  memcpy(&serialized_snapshot, start_address,
1783  sizeof(SerializedSnapshotData));
1784  serialized_xids = (TransactionId *)
1785  (start_address + sizeof(SerializedSnapshotData));
1786 
1787  /* We allocate any XID arrays needed in the same palloc block. */
1788  size = sizeof(SnapshotData)
1789  + serialized_snapshot.xcnt * sizeof(TransactionId)
1790  + serialized_snapshot.subxcnt * sizeof(TransactionId);
1791 
1792  /* Copy all required fields */
1794  snapshot->snapshot_type = SNAPSHOT_MVCC;
1795  snapshot->xmin = serialized_snapshot.xmin;
1796  snapshot->xmax = serialized_snapshot.xmax;
1797  snapshot->xip = NULL;
1798  snapshot->xcnt = serialized_snapshot.xcnt;
1799  snapshot->subxip = NULL;
1800  snapshot->subxcnt = serialized_snapshot.subxcnt;
1801  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
1802  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
1803  snapshot->curcid = serialized_snapshot.curcid;
1804  snapshot->whenTaken = serialized_snapshot.whenTaken;
1805  snapshot->lsn = serialized_snapshot.lsn;
1806  snapshot->snapXactCompletionCount = 0;
1807 
1808  /* Copy XIDs, if present. */
1809  if (serialized_snapshot.xcnt > 0)
1810  {
1811  snapshot->xip = (TransactionId *) (snapshot + 1);
1812  memcpy(snapshot->xip, serialized_xids,
1813  serialized_snapshot.xcnt * sizeof(TransactionId));
1814  }
1815 
1816  /* Copy SubXIDs, if present. */
1817  if (serialized_snapshot.subxcnt > 0)
1818  {
1819  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
1820  serialized_snapshot.xcnt;
1821  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
1822  serialized_snapshot.subxcnt * sizeof(TransactionId));
1823  }
1824 
1825  /* Set the copied flag so that the caller will set refcounts correctly. */
1826  snapshot->regd_count = 0;
1827  snapshot->active_count = 0;
1828  snapshot->copied = true;
1829 
1830  return snapshot;
1831 }
struct SnapshotData * Snapshot
Definition: snapshot.h:121
struct SnapshotData SnapshotData
TransactionId xmax
Definition: snapmgr.c:196
TimestampTz whenTaken
Definition: snapmgr.c:202
TransactionId xmin
Definition: snapmgr.c:195
CommandId curcid
Definition: snapshot.h:187
TimestampTz whenTaken
Definition: snapshot.h:208
uint64 snapXactCompletionCount
Definition: snapshot.h:216

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

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

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  source_pgproc 
)

Definition at line 1840 of file snapmgr.c.

1841 {
1842  SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
1843 }
#define InvalidPid
Definition: miscadmin.h:32

References InvalidPid, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

◆ SerializeSnapshot()

void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

Definition at line 1716 of file snapmgr.c.

1717 {
1718  SerializedSnapshotData serialized_snapshot;
1719 
1720  Assert(snapshot->subxcnt >= 0);
1721 
1722  /* Copy all required fields */
1723  serialized_snapshot.xmin = snapshot->xmin;
1724  serialized_snapshot.xmax = snapshot->xmax;
1725  serialized_snapshot.xcnt = snapshot->xcnt;
1726  serialized_snapshot.subxcnt = snapshot->subxcnt;
1727  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
1728  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
1729  serialized_snapshot.curcid = snapshot->curcid;
1730  serialized_snapshot.whenTaken = snapshot->whenTaken;
1731  serialized_snapshot.lsn = snapshot->lsn;
1732 
1733  /*
1734  * Ignore the SubXID array if it has overflowed, unless the snapshot was
1735  * taken during recovery - in that case, top-level XIDs are in subxip as
1736  * well, and we mustn't lose them.
1737  */
1738  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
1739  serialized_snapshot.subxcnt = 0;
1740 
1741  /* Copy struct to possibly-unaligned buffer */
1742  memcpy(start_address,
1743  &serialized_snapshot, sizeof(SerializedSnapshotData));
1744 
1745  /* Copy XID array */
1746  if (snapshot->xcnt > 0)
1747  memcpy((TransactionId *) (start_address +
1748  sizeof(SerializedSnapshotData)),
1749  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
1750 
1751  /*
1752  * Copy SubXID array. Don't bother to copy it if it had overflowed,
1753  * though, because it's not used anywhere in that case. Except if it's a
1754  * snapshot taken during recovery; all the top-level XIDs are in subxip as
1755  * well in that case, so we mustn't lose them.
1756  */
1757  if (serialized_snapshot.subxcnt > 0)
1758  {
1759  Size subxipoff = sizeof(SerializedSnapshotData) +
1760  snapshot->xcnt * sizeof(TransactionId);
1761 
1762  memcpy((TransactionId *) (start_address + subxipoff),
1763  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
1764  }
1765 }
struct SerializedSnapshotData SerializedSnapshotData

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

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

◆ SetupHistoricSnapshot()

void SetupHistoricSnapshot ( Snapshot  historic_snapshot,
struct HTAB tuplecids 
)

Definition at line 1649 of file snapmgr.c.

1650 {
1651  Assert(historic_snapshot != NULL);
1652 
1653  /* setup the timetravel snapshot */
1654  HistoricSnapshot = historic_snapshot;
1655 
1656  /* setup (cmin, cmax) lookup hash */
1657  tuplecid_data = tuplecids;
1658 }

References Assert, HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ SnapshotSetCommandId()

void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 456 of file snapmgr.c.

457 {
458  if (!FirstSnapshotSet)
459  return;
460 
461  if (CurrentSnapshot)
462  CurrentSnapshot->curcid = curcid;
463  if (SecondarySnapshot)
464  SecondarySnapshot->curcid = curcid;
465  /* Should we do the same with CatalogSnapshot? */
466 }

References SnapshotData::curcid, CurrentSnapshot, FirstSnapshotSet, and SecondarySnapshot.

Referenced by CommandCounterIncrement().

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 1665 of file snapmgr.c.

1666 {
1667  HistoricSnapshot = NULL;
1668  tuplecid_data = NULL;
1669 }

References HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1606 of file snapmgr.c.

1607 {
1610  return true;
1611 
1612  return false;
1613 }

References pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by CopyFrom().

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 849 of file snapmgr.c.

850 {
851  if (snapshot == NULL)
852  return;
853 
854  ResourceOwnerForgetSnapshot(owner, snapshot);
855  UnregisterSnapshotNoOwner(snapshot);
856 }
static void UnregisterSnapshotNoOwner(Snapshot snapshot)
Definition: snapmgr.c:859
static void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snap)
Definition: snapmgr.c:182

References ResourceOwnerForgetSnapshot(), and UnregisterSnapshotNoOwner().

Referenced by closeLOfd(), PortalDrop(), PreCommit_Portals(), and UnregisterSnapshot().

◆ UpdateActiveSnapshotCommandId()

void UpdateActiveSnapshotCommandId ( void  )

Definition at line 712 of file snapmgr.c.

713 {
714  CommandId save_curcid,
715  curcid;
716 
717  Assert(ActiveSnapshot != NULL);
720 
721  /*
722  * Don't allow modification of the active snapshot during parallel
723  * operation. We share the snapshot to worker backends at the beginning
724  * of parallel operation, so any change to the snapshot can lead to
725  * inconsistencies. We have other defenses against
726  * CommandCounterIncrement, but there are a few places that call this
727  * directly, so we put an additional guard here.
728  */
729  save_curcid = ActiveSnapshot->as_snap->curcid;
730  curcid = GetCurrentCommandId(false);
731  if (IsInParallelMode() && save_curcid != curcid)
732  elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
733  ActiveSnapshot->as_snap->curcid = curcid;
734 }
uint32 CommandId
Definition: c.h:657
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:828

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

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

◆ WaitForOlderSnapshots()

void WaitForOlderSnapshots ( TransactionId  limitXmin,
bool  progress 
)

Definition at line 429 of file indexcmds.c.

430 {
431  int n_old_snapshots;
432  int i;
433  VirtualTransactionId *old_snapshots;
434 
435  old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
437  | PROC_IN_SAFE_IC,
438  &n_old_snapshots);
439  if (progress)
441 
442  for (i = 0; i < n_old_snapshots; i++)
443  {
444  if (!VirtualTransactionIdIsValid(old_snapshots[i]))
445  continue; /* found uninteresting in previous cycle */
446 
447  if (i > 0)
448  {
449  /* see if anything's changed ... */
450  VirtualTransactionId *newer_snapshots;
451  int n_newer_snapshots;
452  int j;
453  int k;
454 
455  newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
456  true, false,
458  | PROC_IN_SAFE_IC,
459  &n_newer_snapshots);
460  for (j = i; j < n_old_snapshots; j++)
461  {
462  if (!VirtualTransactionIdIsValid(old_snapshots[j]))
463  continue; /* found uninteresting in previous cycle */
464  for (k = 0; k < n_newer_snapshots; k++)
465  {
466  if (VirtualTransactionIdEquals(old_snapshots[j],
467  newer_snapshots[k]))
468  break;
469  }
470  if (k >= n_newer_snapshots) /* not there anymore */
471  SetInvalidVirtualTransactionId(old_snapshots[j]);
472  }
473  pfree(newer_snapshots);
474  }
475 
476  if (VirtualTransactionIdIsValid(old_snapshots[i]))
477  {
478  /* If requested, publish who we're going to wait for. */
479  if (progress)
480  {
481  PGPROC *holder = ProcNumberGetProc(old_snapshots[i].procNumber);
482 
483  if (holder)
485  holder->pid);
486  }
487  VirtualXactLock(old_snapshots[i], true);
488  }
489 
490  if (progress)
492  }
493 }
void pgstat_progress_update_param(int index, int64 val)
int j
Definition: isn.c:73
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4650
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:71
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:74
static int progress
Definition: pgbench.c:261
#define PROC_IN_SAFE_IC
Definition: proc.h:59
#define PROC_IN_VACUUM
Definition: proc.h:58
#define PROC_IS_AUTOVACUUM
Definition: proc.h:57
PGPROC * ProcNumberGetProc(ProcNumber procNumber)
Definition: procarray.c:3142
VirtualTransactionId * GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
Definition: procarray.c:3328
#define PROGRESS_WAITFOR_DONE
Definition: progress.h:118
#define PROGRESS_WAITFOR_TOTAL
Definition: progress.h:117
#define PROGRESS_WAITFOR_CURRENT_PID
Definition: progress.h:119
Definition: proc.h:162
int pid
Definition: proc.h:182

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

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

◆ XactHasExportedSnapshots()

bool XactHasExportedSnapshots ( void  )

Definition at line 1554 of file snapmgr.c.

1555 {
1556  return (exportedSnapshots != NIL);
1557 }

References exportedSnapshots, and NIL.

Referenced by PrepareTransaction().

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 1856 of file snapmgr.c.

1857 {
1858  /*
1859  * Make a quick range check to eliminate most XIDs without looking at the
1860  * xip arrays. Note that this is OK even if we convert a subxact XID to
1861  * its parent below, because a subxact with XID < xmin has surely also got
1862  * a parent with XID < xmin, while one with XID >= xmax must belong to a
1863  * parent that was not yet committed at the time of this snapshot.
1864  */
1865 
1866  /* Any xid < xmin is not in-progress */
1867  if (TransactionIdPrecedes(xid, snapshot->xmin))
1868  return false;
1869  /* Any xid >= xmax is in-progress */
1870  if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
1871  return true;
1872 
1873  /*
1874  * Snapshot information is stored slightly differently in snapshots taken
1875  * during recovery.
1876  */
1877  if (!snapshot->takenDuringRecovery)
1878  {
1879  /*
1880  * If the snapshot contains full subxact data, the fastest way to
1881  * check things is just to compare the given XID against both subxact
1882  * XIDs and top-level XIDs. If the snapshot overflowed, we have to
1883  * use pg_subtrans to convert a subxact XID to its parent XID, but
1884  * then we need only look at top-level XIDs not subxacts.
1885  */
1886  if (!snapshot->suboverflowed)
1887  {
1888  /* we have full data, so search subxip */
1889  if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1890  return true;
1891 
1892  /* not there, fall through to search xip[] */
1893  }
1894  else
1895  {
1896  /*
1897  * Snapshot overflowed, so convert xid to top-level. This is safe
1898  * because we eliminated too-old XIDs above.
1899  */
1900  xid = SubTransGetTopmostTransaction(xid);
1901 
1902  /*
1903  * If xid was indeed a subxact, we might now have an xid < xmin,
1904  * so recheck to avoid an array scan. No point in rechecking
1905  * xmax.
1906  */
1907  if (TransactionIdPrecedes(xid, snapshot->xmin))
1908  return false;
1909  }
1910 
1911  if (pg_lfind32(xid, snapshot->xip, snapshot->xcnt))
1912  return true;
1913  }
1914  else
1915  {
1916  /*
1917  * In recovery we store all xids in the subxip array because it is by
1918  * far the bigger array, and we mostly don't know which xids are
1919  * top-level and which are subxacts. The xip array is empty.
1920  *
1921  * We start by searching subtrans, if we overflowed.
1922  */
1923  if (snapshot->suboverflowed)
1924  {
1925  /*
1926  * Snapshot overflowed, so convert xid to top-level. This is safe
1927  * because we eliminated too-old XIDs above.
1928  */
1929  xid = SubTransGetTopmostTransaction(xid);
1930 
1931  /*
1932  * If xid was indeed a subxact, we might now have an xid < xmin,
1933  * so recheck to avoid an array scan. No point in rechecking
1934  * xmax.
1935  */
1936  if (TransactionIdPrecedes(xid, snapshot->xmin))
1937  return false;
1938  }
1939 
1940  /*
1941  * We now have either a top-level xid higher than xmin or an
1942  * indeterminate xid. We don't know whether it's top level or subxact
1943  * but it doesn't matter. If it's present, the xid is visible.
1944  */
1945  if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1946  return true;
1947  }
1948 
1949  return false;
1950 }
static bool pg_lfind32(uint32 key, const uint32 *base, uint32 nelem)
Definition: pg_lfind.h:153
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:163
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:329

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

Referenced by asyncQueueProcessPageEntries(), find_inheritance_children_extended(), HeapTupleSatisfiesMVCC(), and RelationGetPartitionDesc().

Variable Documentation

◆ CatalogSnapshotData

PGDLLIMPORT SnapshotData CatalogSnapshotData
extern

Definition at line 83 of file snapmgr.c.

Referenced by GetNonHistoricCatalogSnapshot().

◆ FirstSnapshotSet

◆ RecentXmin

◆ SnapshotAnyData

PGDLLIMPORT SnapshotData SnapshotAnyData
extern

Definition at line 85 of file snapmgr.c.

◆ SnapshotSelfData

PGDLLIMPORT SnapshotData SnapshotSelfData
extern

Definition at line 84 of file snapmgr.c.

◆ TransactionXmin