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)
 
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 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 971 of file snapmgr.c.

972 {
973  /*
974  * In transaction-snapshot mode we must release our privately-managed
975  * reference to the transaction snapshot. We must remove it from
976  * RegisteredSnapshots to keep the check below happy. But we don't bother
977  * to do FreeSnapshot, for two reasons: the memory will go away with
978  * TopTransactionContext anyway, and if someone has left the snapshot
979  * stacked as active, we don't want the code below to be chasing through a
980  * dangling pointer.
981  */
982  if (FirstXactSnapshot != NULL)
983  {
987  }
988  FirstXactSnapshot = NULL;
989 
990  /*
991  * If we exported any snapshots, clean them up.
992  */
993  if (exportedSnapshots != NIL)
994  {
995  ListCell *lc;
996 
997  /*
998  * Get rid of the files. Unlink failure is only a WARNING because (1)
999  * it's too late to abort the transaction, and (2) leaving a leaked
1000  * file around has little real consequence anyway.
1001  *
1002  * We also need to remove the snapshots from RegisteredSnapshots to
1003  * prevent a warning below.
1004  *
1005  * As with the FirstXactSnapshot, we don't need to free resources of
1006  * the snapshot itself as it will go away with the memory context.
1007  */
1008  foreach(lc, exportedSnapshots)
1009  {
1010  ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1011 
1012  if (unlink(esnap->snapfile))
1013  elog(WARNING, "could not unlink file \"%s\": %m",
1014  esnap->snapfile);
1015 
1017  &esnap->snapshot->ph_node);
1018  }
1019 
1021  }
1022 
1023  /* Drop catalog snapshot if any */
1025 
1026  /* On commit, complain about leftover snapshots */
1027  if (isCommit)
1028  {
1029  ActiveSnapshotElt *active;
1030 
1032  elog(WARNING, "registered snapshots seem to remain after cleanup");
1033 
1034  /* complain about unpopped active snapshots */
1035  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1036  elog(WARNING, "snapshot %p still active", active);
1037  }
1038 
1039  /*
1040  * And reset our state. We don't need to free the memory explicitly --
1041  * it'll go away with TopTransactionContext.
1042  */
1043  ActiveSnapshot = NULL;
1044  OldestActiveSnapshot = NULL;
1046 
1047  CurrentSnapshot = NULL;
1048  SecondarySnapshot = NULL;
1049 
1050  FirstSnapshotSet = false;
1051 
1052  /*
1053  * During normal commit processing, we call ProcArrayEndTransaction() to
1054  * reset the MyProc->xmin. That call happens prior to the call to
1055  * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1056  */
1057  if (resetXmin)
1059 
1060  Assert(resetXmin || MyProc->xmin == 0);
1061 }
#define WARNING
Definition: elog.h:36
Assert(fmt[strlen(fmt) - 1] !='\n')
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:148
static Snapshot CurrentSnapshot
Definition: snapmgr.c:94
static Snapshot SecondarySnapshot
Definition: snapmgr.c:95
static List * exportedSnapshots
Definition: snapmgr.c:161
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:138
bool FirstSnapshotSet
Definition: snapmgr.c:141
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:129
static void SnapshotResetXmin(void)
Definition: snapmgr.c:890
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:403
PGPROC * MyProc
Definition: proc.c:66
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:122
char * snapfile
Definition: snapmgr.c:156
Snapshot snapshot
Definition: snapmgr.c:157
TransactionId xmin
Definition: proc.h:178
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 935 of file snapmgr.c.

936 {
937  /* Forget the active snapshots set by this subtransaction */
938  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
939  {
941 
943 
944  /*
945  * Decrement the snapshot's active count. If it's still registered or
946  * marked as active by an outer subtransaction, we can't free it yet.
947  */
950 
951  if (ActiveSnapshot->as_snap->active_count == 0 &&
954 
955  /* and free the stack element */
957 
959  if (ActiveSnapshot == NULL)
960  OldestActiveSnapshot = NULL;
961  }
962 
964 }
static int32 next
Definition: blutils.c:219
void pfree(void *pointer)
Definition: mcxt.c:1456
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:611
Snapshot as_snap
Definition: snapmgr.c:120
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 914 of file snapmgr.c.

915 {
916  ActiveSnapshotElt *active;
917 
918  /*
919  * Relabel the active snapshots set in this subtransaction as though they
920  * are owned by the parent subxact.
921  */
922  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
923  {
924  if (active->as_level < level)
925  break;
926  active->as_level = level - 1;
927  }
928 }

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

Referenced by CommitSubTransaction().

◆ DeleteAllExportedSnapshotFiles()

void DeleteAllExportedSnapshotFiles ( void  )

Definition at line 1542 of file snapmgr.c.

1543 {
1544  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1545  DIR *s_dir;
1546  struct dirent *s_de;
1547 
1548  /*
1549  * Problems in reading the directory, or unlinking files, are reported at
1550  * LOG level. Since we're running in the startup process, ERROR level
1551  * would prevent database start, and it's not important enough for that.
1552  */
1554 
1555  while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1556  {
1557  if (strcmp(s_de->d_name, ".") == 0 ||
1558  strcmp(s_de->d_name, "..") == 0)
1559  continue;
1560 
1561  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1562 
1563  if (unlink(buf) != 0)
1564  ereport(LOG,
1566  errmsg("could not remove file \"%s\": %m", buf)));
1567  }
1568 
1569  FreeDir(s_dir);
1570 }
int errcode_for_file_access(void)
Definition: elog.c:881
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:149
int FreeDir(DIR *dir)
Definition: fd.c:2906
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2869
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2788
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:67
#define snprintf
Definition: port.h:238
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:151
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 1667 of file snapmgr.c.

1668 {
1669  Size size;
1670 
1671  Assert(snapshot != InvalidSnapshot);
1672  Assert(snapshot->snapshot_type == SNAPSHOT_MVCC);
1673 
1674  /* We allocate any XID arrays needed in the same palloc block. */
1675  size = add_size(sizeof(SerializedSnapshotData),
1676  mul_size(snapshot->xcnt, sizeof(TransactionId)));
1677  if (snapshot->subxcnt > 0 &&
1678  (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
1679  size = add_size(size,
1680  mul_size(snapshot->subxcnt, sizeof(TransactionId)));
1681 
1682  return size;
1683 }
uint32 TransactionId
Definition: c.h:641
size_t Size
Definition: c.h:594
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
#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(), 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().

◆ ExportSnapshot()

char* ExportSnapshot ( Snapshot  snapshot)

Definition at line 1071 of file snapmgr.c.

1072 {
1073  TransactionId topXid;
1074  TransactionId *children;
1075  ExportedSnapshot *esnap;
1076  int nchildren;
1077  int addTopXid;
1079  FILE *f;
1080  int i;
1081  MemoryContext oldcxt;
1082  char path[MAXPGPATH];
1083  char pathtmp[MAXPGPATH];
1084 
1085  /*
1086  * It's tempting to call RequireTransactionBlock here, since it's not very
1087  * useful to export a snapshot that will disappear immediately afterwards.
1088  * However, we haven't got enough information to do that, since we don't
1089  * know if we're at top level or not. For example, we could be inside a
1090  * plpgsql function that is going to fire off other transactions via
1091  * dblink. Rather than disallow perfectly legitimate usages, don't make a
1092  * check.
1093  *
1094  * Also note that we don't make any restriction on the transaction's
1095  * isolation level; however, importers must check the level if they are
1096  * serializable.
1097  */
1098 
1099  /*
1100  * Get our transaction ID if there is one, to include in the snapshot.
1101  */
1102  topXid = GetTopTransactionIdIfAny();
1103 
1104  /*
1105  * We cannot export a snapshot from a subtransaction because there's no
1106  * easy way for importers to verify that the same subtransaction is still
1107  * running.
1108  */
1109  if (IsSubTransaction())
1110  ereport(ERROR,
1111  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1112  errmsg("cannot export a snapshot from a subtransaction")));
1113 
1114  /*
1115  * We do however allow previous committed subtransactions to exist.
1116  * Importers of the snapshot must see them as still running, so get their
1117  * XIDs to add them to the snapshot.
1118  */
1119  nchildren = xactGetCommittedChildren(&children);
1120 
1121  /*
1122  * Generate file path for the snapshot. We start numbering of snapshots
1123  * inside the transaction from 1.
1124  */
1125  snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%08X-%d",
1127 
1128  /*
1129  * Copy the snapshot into TopTransactionContext, add it to the
1130  * exportedSnapshots list, and mark it pseudo-registered. We do this to
1131  * ensure that the snapshot's xmin is honored for the rest of the
1132  * transaction.
1133  */
1134  snapshot = CopySnapshot(snapshot);
1135 
1137  esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
1138  esnap->snapfile = pstrdup(path);
1139  esnap->snapshot = snapshot;
1141  MemoryContextSwitchTo(oldcxt);
1142 
1143  snapshot->regd_count++;
1145 
1146  /*
1147  * Fill buf with a text serialization of the snapshot, plus identification
1148  * data about this transaction. The format expected by ImportSnapshot is
1149  * pretty rigid: each line must be fieldname:value.
1150  */
1151  initStringInfo(&buf);
1152 
1153  appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->backendId, MyProc->lxid);
1154  appendStringInfo(&buf, "pid:%d\n", MyProcPid);
1155  appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1156  appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1157  appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1158 
1159  appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1160  appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1161 
1162  /*
1163  * We must include our own top transaction ID in the top-xid data, since
1164  * by definition we will still be running when the importing transaction
1165  * adopts the snapshot, but GetSnapshotData never includes our own XID in
1166  * the snapshot. (There must, therefore, be enough room to add it.)
1167  *
1168  * However, it could be that our topXid is after the xmax, in which case
1169  * we shouldn't include it because xip[] members are expected to be before
1170  * xmax. (We need not make the same check for subxip[] members, see
1171  * snapshot.h.)
1172  */
1173  addTopXid = (TransactionIdIsValid(topXid) &&
1174  TransactionIdPrecedes(topXid, snapshot->xmax)) ? 1 : 0;
1175  appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1176  for (i = 0; i < snapshot->xcnt; i++)
1177  appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1178  if (addTopXid)
1179  appendStringInfo(&buf, "xip:%u\n", topXid);
1180 
1181  /*
1182  * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1183  * we have to cope with possible overflow.
1184  */
1185  if (snapshot->suboverflowed ||
1186  snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1187  appendStringInfoString(&buf, "sof:1\n");
1188  else
1189  {
1190  appendStringInfoString(&buf, "sof:0\n");
1191  appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1192  for (i = 0; i < snapshot->subxcnt; i++)
1193  appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1194  for (i = 0; i < nchildren; i++)
1195  appendStringInfo(&buf, "sxp:%u\n", children[i]);
1196  }
1197  appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1198 
1199  /*
1200  * Now write the text representation into a file. We first write to a
1201  * ".tmp" filename, and rename to final filename if no error. This
1202  * ensures that no other backend can read an incomplete file
1203  * (ImportSnapshot won't allow it because of its valid-characters check).
1204  */
1205  snprintf(pathtmp, sizeof(pathtmp), "%s.tmp", path);
1206  if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1207  ereport(ERROR,
1209  errmsg("could not create file \"%s\": %m", pathtmp)));
1210 
1211  if (fwrite(buf.data, buf.len, 1, f) != 1)
1212  ereport(ERROR,
1214  errmsg("could not write to file \"%s\": %m", pathtmp)));
1215 
1216  /* no fsync() since file need not survive a system crash */
1217 
1218  if (FreeFile(f))
1219  ereport(ERROR,
1221  errmsg("could not write to file \"%s\": %m", pathtmp)));
1222 
1223  /*
1224  * Now that we have written everything into a .tmp file, rename the file
1225  * to remove the .tmp suffix.
1226  */
1227  if (rename(pathtmp, path) < 0)
1228  ereport(ERROR,
1230  errmsg("could not rename file \"%s\" to \"%s\": %m",
1231  pathtmp, path)));
1232 
1233  /*
1234  * The basename of the file is what we return from pg_export_snapshot().
1235  * It's already in path in a textual format and we know that the path
1236  * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1237  * and pstrdup it so as not to return the address of a local variable.
1238  */
1239  return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1240 }
#define PG_BINARY_W
Definition: c.h:1286
int errcode(int sqlerrcode)
Definition: elog.c:858
#define ERROR
Definition: elog.h:39
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2528
int FreeFile(FILE *file)
Definition: fd.c:2726
int MyProcPid
Definition: globals.c:44
Oid MyDatabaseId
Definition: globals.c:89
int i
Definition: isn.c:73
List * lappend(List *list, void *datum)
Definition: list.c:338
MemoryContext TopTransactionContext
Definition: mcxt.c:146
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void * palloc(Size size)
Definition: mcxt.c:1226
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
static int list_length(const List *l)
Definition: pg_list.h:152
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:2061
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:555
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
LocalTransactionId lxid
Definition: proc.h:183
BackendId backendId
Definition: proc.h:197
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:82
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:432
int XactIsoLevel
Definition: xact.c:79
bool IsSubTransaction(void)
Definition: xact.c:4889
int xactGetCommittedChildren(TransactionId **ptr)
Definition: xact.c:5612

References AllocateFile(), appendStringInfo(), appendStringInfoString(), PGPROC::backendId, 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, pstrdup(), SnapshotData::regd_count, RegisteredSnapshots, ExportedSnapshot::snapfile, ExportedSnapshot::snapshot, SNAPSHOT_EXPORT_DIR, snprintf, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TopTransactionContext, TransactionIdIsValid, TransactionIdPrecedes(), xactGetCommittedChildren(), XactIsoLevel, XactReadOnly, SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by pg_export_snapshot(), and SnapBuildExportSnapshot().

◆ GetActiveSnapshot()

◆ GetCatalogSnapshot()

Snapshot GetCatalogSnapshot ( Oid  relid)

Definition at line 333 of file snapmgr.c.

334 {
335  /*
336  * Return historic snapshot while we're doing logical decoding, so we can
337  * see the appropriate state of the catalog.
338  *
339  * This is the primary reason for needing to reset the system caches after
340  * finishing decoding.
341  */
343  return HistoricSnapshot;
344 
345  return GetNonHistoricCatalogSnapshot(relid);
346 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:97
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1647
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:355

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 272 of file snapmgr.c.

273 {
274  /*
275  * We might be able to relax this, but nothing that could otherwise work
276  * needs it.
277  */
278  if (IsInParallelMode())
279  elog(ERROR,
280  "cannot update SecondarySnapshot during a parallel operation");
281 
282  /*
283  * So far there are no cases requiring support for GetLatestSnapshot()
284  * during logical decoding, but it wouldn't be hard to add if required.
285  */
287 
288  /* If first call in transaction, go ahead and set the xact snapshot */
289  if (!FirstSnapshotSet)
290  return GetTransactionSnapshot();
291 
293 
294  return SecondarySnapshot;
295 }
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2159
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:197
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:88
bool IsInParallelMode(void)
Definition: xact.c:1069

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

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

◆ GetNonHistoricCatalogSnapshot()

Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 355 of file snapmgr.c.

356 {
357  /*
358  * If the caller is trying to scan a relation that has no syscache, no
359  * catcache invalidations will be sent when it is updated. For a few key
360  * relations, snapshot invalidations are sent instead. If we're trying to
361  * scan a relation for which neither catcache nor snapshot invalidations
362  * are sent, we must refresh the snapshot every time.
363  */
364  if (CatalogSnapshot &&
366  !RelationHasSysCache(relid))
368 
369  if (CatalogSnapshot == NULL)
370  {
371  /* Get new snapshot. */
373 
374  /*
375  * Make sure the catalog snapshot will be accounted for in decisions
376  * about advancing PGPROC->xmin. We could apply RegisterSnapshot, but
377  * that would result in making a physical copy, which is overkill; and
378  * it would also create a dependency on some resource owner, which we
379  * do not want for reasons explained at the head of this file. Instead
380  * just shove the CatalogSnapshot into the pairing heap manually. This
381  * has to be reversed in InvalidateCatalogSnapshot, of course.
382  *
383  * NB: it had better be impossible for this to throw error, since the
384  * CatalogSnapshot pointer is already valid.
385  */
387  }
388 
389  return CatalogSnapshot;
390 }
SnapshotData CatalogSnapshotData
Definition: snapmgr.c:89
static Snapshot CatalogSnapshot
Definition: snapmgr.c:96
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:1226
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1203

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 304 of file snapmgr.c.

305 {
306  Snapshot OldestRegisteredSnapshot = NULL;
307  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
308 
310  {
311  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
313  RegisteredLSN = OldestRegisteredSnapshot->lsn;
314  }
315 
316  if (OldestActiveSnapshot != NULL)
317  {
319 
320  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
322  }
323 
324  return OldestRegisteredSnapshot;
325 }
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 197 of file snapmgr.c.

198 {
199  /*
200  * Return historic snapshot if doing logical decoding. We'll never need a
201  * non-historic transaction snapshot in this (sub-)transaction, so there's
202  * no need to be careful to set one up for later calls to
203  * GetTransactionSnapshot().
204  */
206  {
208  return HistoricSnapshot;
209  }
210 
211  /* First call in transaction? */
212  if (!FirstSnapshotSet)
213  {
214  /*
215  * Don't allow catalog snapshot to be older than xact snapshot. Must
216  * do this first to allow the empty-heap Assert to succeed.
217  */
219 
221  Assert(FirstXactSnapshot == NULL);
222 
223  if (IsInParallelMode())
224  elog(ERROR,
225  "cannot take query snapshot during a parallel operation");
226 
227  /*
228  * In transaction-snapshot mode, the first snapshot must live until
229  * end of xact regardless of what the caller does with it, so we must
230  * make a copy of it rather than returning CurrentSnapshotData
231  * directly. Furthermore, if we're running in serializable mode,
232  * predicate.c needs to wrap the snapshot fetch in its own processing.
233  */
235  {
236  /* First, create the snapshot in CurrentSnapshotData */
239  else
241  /* Make a saved copy */
244  /* Mark it as "registered" in FirstXactSnapshot */
247  }
248  else
250 
251  FirstSnapshotSet = true;
252  return CurrentSnapshot;
253  }
254 
256  return CurrentSnapshot;
257 
258  /* Don't allow catalog snapshot to be older than xact snapshot. */
260 
262 
263  return CurrentSnapshot;
264 }
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1616
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:87
#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 _bt_begin_parallel(), _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), begin_replication_step(), bt_check_every_level(), BuildCachedPlan(), CheckTargetForConflictsIn(), cluster_multiple_rels(), DefineIndex(), EnsurePortalSnapshotExists(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), execute_sql_string(), ExecuteCallStmt(), fmgr_sql(), get_database_list(), get_subscription_list(), GetLatestSnapshot(), HandleFunctionRequest(), heapam_index_build_range_scan(), initialize_worker_spi(), InitializeParallelDSM(), InitPostgres(), LogicalRepSyncTableStart(), pg_get_constraintdef_worker(), PortalRunMulti(), PortalRunUtility(), PortalStart(), 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 4220 of file procarray.c.

4221 {
4223 
4224  state = GlobalVisTestFor(rel);
4225 
4226  return GlobalVisTestIsRemovableFullXid(state, fxid);
4227 }
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:4126
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:4011
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 4234 of file procarray.c.

4235 {
4237 
4238  state = GlobalVisTestFor(rel);
4239 
4240  return GlobalVisTestIsRemovableXid(state, xid);
4241 }
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4168

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by GinPageIsRecyclable().

◆ GlobalVisTestFor()

GlobalVisState* GlobalVisTestFor ( Relation  rel)

Definition at line 4011 of file procarray.c.

4012 {
4013  GlobalVisState *state = NULL;
4014 
4015  /* XXX: we should assert that a snapshot is pushed or registered */
4016  Assert(RecentXmin);
4017 
4018  switch (GlobalVisHorizonKindForRel(rel))
4019  {
4020  case VISHORIZON_SHARED:
4022  break;
4023  case VISHORIZON_CATALOG:
4025  break;
4026  case VISHORIZON_DATA:
4028  break;
4029  case VISHORIZON_TEMP:
4031  break;
4032  }
4033 
4034  Assert(FullTransactionIdIsValid(state->definitely_needed) &&
4035  FullTransactionIdIsValid(state->maybe_needed));
4036 
4037  return state;
4038 }
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:300
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:298
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:299
static GlobalVisState GlobalVisTempRels
Definition: procarray.c:301
@ VISHORIZON_SHARED
Definition: procarray.c:252
@ VISHORIZON_DATA
Definition: procarray.c:254
@ VISHORIZON_CATALOG
Definition: procarray.c:253
@ VISHORIZON_TEMP
Definition: procarray.c:255
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition: procarray.c:1952
TransactionId RecentXmin
Definition: snapmgr.c:105
#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 4126 of file procarray.c.

4128 {
4129  /*
4130  * If fxid is older than maybe_needed bound, it definitely is visible to
4131  * everyone.
4132  */
4133  if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4134  return true;
4135 
4136  /*
4137  * If fxid is >= definitely_needed bound, it is very likely to still be
4138  * considered running.
4139  */
4140  if (FullTransactionIdFollowsOrEquals(fxid, state->definitely_needed))
4141  return false;
4142 
4143  /*
4144  * fxid is between maybe_needed and definitely_needed, i.e. there might or
4145  * might not exist a snapshot considering fxid running. If it makes sense,
4146  * update boundaries and recheck.
4147  */
4149  {
4150  GlobalVisUpdate();
4151 
4152  Assert(FullTransactionIdPrecedes(fxid, state->definitely_needed));
4153 
4154  return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4155  }
4156  else
4157  return false;
4158 }
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:4051
static void GlobalVisUpdate(void)
Definition: procarray.c:4109
#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 4168 of file procarray.c.

4169 {
4170  FullTransactionId fxid;
4171 
4172  /*
4173  * Convert 32 bit argument to FullTransactionId. We can do so safely
4174  * because we know the xid has to, at the very least, be between
4175  * [oldestXid, nextXid), i.e. within 2 billion of xid. To avoid taking a
4176  * lock to determine either, we can just compare with
4177  * state->definitely_needed, which was based on those value at the time
4178  * the current snapshot was built.
4179  */
4180  fxid = FullXidRelativeTo(state->definitely_needed, xid);
4181 
4182  return GlobalVisTestIsRemovableFullXid(state, fxid);
4183 }
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4255

References FullXidRelativeTo(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisTestNonRemovableFullHorizon()

FullTransactionId GlobalVisTestNonRemovableFullHorizon ( GlobalVisState state)

Definition at line 4195 of file procarray.c.

4196 {
4197  /* acquire accurate horizon if not already done */
4199  GlobalVisUpdate();
4200 
4201  return state->maybe_needed;
4202 }

References GlobalVisTestShouldUpdate(), and GlobalVisUpdate().

Referenced by GlobalVisTestNonRemovableHorizon().

◆ GlobalVisTestNonRemovableHorizon()

TransactionId GlobalVisTestNonRemovableHorizon ( GlobalVisState state)

Definition at line 4206 of file procarray.c.

4207 {
4208  FullTransactionId cutoff;
4209 
4211 
4212  return XidFromFullTransactionId(cutoff);
4213 }
FullTransactionId GlobalVisTestNonRemovableFullHorizon(GlobalVisState *state)
Definition: procarray.c:4195
#define XidFromFullTransactionId(x)
Definition: transam.h:48

References GlobalVisTestNonRemovableFullHorizon(), and XidFromFullTransactionId.

◆ HaveRegisteredOrActiveSnapshot()

bool HaveRegisteredOrActiveSnapshot ( void  )

Definition at line 1599 of file snapmgr.c.

1600 {
1601  if (ActiveSnapshot != NULL)
1602  return true;
1603 
1604  /*
1605  * The catalog snapshot is in RegisteredSnapshots when valid, but can be
1606  * removed at any time due to invalidation processing. If explicitly
1607  * registered more than one snapshot has to be in RegisteredSnapshots.
1608  */
1609  if (CatalogSnapshot != NULL &&
1611  return false;
1612 
1614 }
#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 1653 of file snapmgr.c.

1654 {
1656  return tuplecid_data;
1657 }
static HTAB * tuplecid_data
Definition: snapmgr.c:108

References Assert(), HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1342 of file snapmgr.c.

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

725 {
726  ActiveSnapshotElt *newstack;
727 
728  newstack = ActiveSnapshot->as_next;
729 
731 
733 
734  if (ActiveSnapshot->as_snap->active_count == 0 &&
737 
739  ActiveSnapshot = newstack;
740  if (ActiveSnapshot == NULL)
741  OldestActiveSnapshot = NULL;
742 
744 }

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(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), ExecCreateTableAs(), execute_sql_string(), ExecuteCallStmt(), ExplainOnePlan(), fmgr_sql(), ForgetPortalSnapshots(), HandleFunctionRequest(), index_drop(), initialize_worker_spi(), LogicalRepSyncTableStart(), movedb(), ParallelWorkerMain(), PersistHoldablePortal(), PortalRunMulti(), PortalRunSelect(), PortalRunUtility(), PortalStart(), 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 643 of file snapmgr.c.

644 {
645  ActiveSnapshotElt *newactive;
646 
647  Assert(snapshot != InvalidSnapshot);
648  Assert(ActiveSnapshot == NULL || snap_level >= ActiveSnapshot->as_level);
649 
651 
652  /*
653  * Checking SecondarySnapshot is probably useless here, but it seems
654  * better to be sure.
655  */
656  if (snapshot == CurrentSnapshot || snapshot == SecondarySnapshot ||
657  !snapshot->copied)
658  newactive->as_snap = CopySnapshot(snapshot);
659  else
660  newactive->as_snap = snapshot;
661 
662  newactive->as_next = ActiveSnapshot;
663  newactive->as_level = snap_level;
664 
665  newactive->as_snap->active_count++;
666 
667  ActiveSnapshot = newactive;
668  if (OldestActiveSnapshot == NULL)
670 }
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
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 681 of file snapmgr.c.

682 {
683  PushActiveSnapshot(CopySnapshot(snapshot));
684 }
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:629

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 788 of file snapmgr.c.

789 {
790  Snapshot snap;
791 
792  if (snapshot == InvalidSnapshot)
793  return InvalidSnapshot;
794 
795  /* Static snapshot? Create a persistent copy */
796  snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
797 
798  /* and tell resowner.c about it */
800  snap->regd_count++;
801  ResourceOwnerRememberSnapshot(owner, snap);
802 
803  if (snap->regd_count == 1)
805 
806  return snap;
807 }
void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1315
void ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
Definition: resowner.c:1304

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

Referenced by be_lo_open(), and RegisterSnapshot().

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 1750 of file snapmgr.c.

1751 {
1752  SerializedSnapshotData serialized_snapshot;
1753  Size size;
1754  Snapshot snapshot;
1755  TransactionId *serialized_xids;
1756 
1757  memcpy(&serialized_snapshot, start_address,
1758  sizeof(SerializedSnapshotData));
1759  serialized_xids = (TransactionId *)
1760  (start_address + sizeof(SerializedSnapshotData));
1761 
1762  /* We allocate any XID arrays needed in the same palloc block. */
1763  size = sizeof(SnapshotData)
1764  + serialized_snapshot.xcnt * sizeof(TransactionId)
1765  + serialized_snapshot.subxcnt * sizeof(TransactionId);
1766 
1767  /* Copy all required fields */
1769  snapshot->snapshot_type = SNAPSHOT_MVCC;
1770  snapshot->xmin = serialized_snapshot.xmin;
1771  snapshot->xmax = serialized_snapshot.xmax;
1772  snapshot->xip = NULL;
1773  snapshot->xcnt = serialized_snapshot.xcnt;
1774  snapshot->subxip = NULL;
1775  snapshot->subxcnt = serialized_snapshot.subxcnt;
1776  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
1777  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
1778  snapshot->curcid = serialized_snapshot.curcid;
1779  snapshot->whenTaken = serialized_snapshot.whenTaken;
1780  snapshot->lsn = serialized_snapshot.lsn;
1781  snapshot->snapXactCompletionCount = 0;
1782 
1783  /* Copy XIDs, if present. */
1784  if (serialized_snapshot.xcnt > 0)
1785  {
1786  snapshot->xip = (TransactionId *) (snapshot + 1);
1787  memcpy(snapshot->xip, serialized_xids,
1788  serialized_snapshot.xcnt * sizeof(TransactionId));
1789  }
1790 
1791  /* Copy SubXIDs, if present. */
1792  if (serialized_snapshot.subxcnt > 0)
1793  {
1794  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
1795  serialized_snapshot.xcnt;
1796  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
1797  serialized_snapshot.subxcnt * sizeof(TransactionId));
1798  }
1799 
1800  /* Set the copied flag so that the caller will set refcounts correctly. */
1801  snapshot->regd_count = 0;
1802  snapshot->active_count = 0;
1803  snapshot->copied = true;
1804 
1805  return snapshot;
1806 }
struct SnapshotData * Snapshot
Definition: snapshot.h:121
struct SnapshotData SnapshotData
TransactionId xmax
Definition: snapmgr.c:177
TimestampTz whenTaken
Definition: snapmgr.c:183
TransactionId xmin
Definition: snapmgr.c:176
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, 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 ExecBitmapHeapInitializeWorker(), index_beginscan_parallel(), ParallelWorkerMain(), and table_beginscan_parallel().

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  source_pgproc 
)

Definition at line 1815 of file snapmgr.c.

1816 {
1817  SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
1818 }
#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 1691 of file snapmgr.c.

1692 {
1693  SerializedSnapshotData serialized_snapshot;
1694 
1695  Assert(snapshot->subxcnt >= 0);
1696 
1697  /* Copy all required fields */
1698  serialized_snapshot.xmin = snapshot->xmin;
1699  serialized_snapshot.xmax = snapshot->xmax;
1700  serialized_snapshot.xcnt = snapshot->xcnt;
1701  serialized_snapshot.subxcnt = snapshot->subxcnt;
1702  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
1703  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
1704  serialized_snapshot.curcid = snapshot->curcid;
1705  serialized_snapshot.whenTaken = snapshot->whenTaken;
1706  serialized_snapshot.lsn = snapshot->lsn;
1707 
1708  /*
1709  * Ignore the SubXID array if it has overflowed, unless the snapshot was
1710  * taken during recovery - in that case, top-level XIDs are in subxip as
1711  * well, and we mustn't lose them.
1712  */
1713  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
1714  serialized_snapshot.subxcnt = 0;
1715 
1716  /* Copy struct to possibly-unaligned buffer */
1717  memcpy(start_address,
1718  &serialized_snapshot, sizeof(SerializedSnapshotData));
1719 
1720  /* Copy XID array */
1721  if (snapshot->xcnt > 0)
1722  memcpy((TransactionId *) (start_address +
1723  sizeof(SerializedSnapshotData)),
1724  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
1725 
1726  /*
1727  * Copy SubXID array. Don't bother to copy it if it had overflowed,
1728  * though, because it's not used anywhere in that case. Except if it's a
1729  * snapshot taken during recovery; all the top-level XIDs are in subxip as
1730  * well in that case, so we mustn't lose them.
1731  */
1732  if (serialized_snapshot.subxcnt > 0)
1733  {
1734  Size subxipoff = sizeof(SerializedSnapshotData) +
1735  snapshot->xcnt * sizeof(TransactionId);
1736 
1737  memcpy((TransactionId *) (start_address + subxipoff),
1738  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
1739  }
1740 }
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 ExecBitmapHeapInitializeDSM(), index_parallelscan_initialize(), InitializeParallelDSM(), and table_parallelscan_initialize().

◆ SetupHistoricSnapshot()

void SetupHistoricSnapshot ( Snapshot  historic_snapshot,
struct HTAB tuplecids 
)

Definition at line 1624 of file snapmgr.c.

1625 {
1626  Assert(historic_snapshot != NULL);
1627 
1628  /* setup the timetravel snapshot */
1629  HistoricSnapshot = historic_snapshot;
1630 
1631  /* setup (cmin, cmax) lookup hash */
1632  tuplecid_data = tuplecids;
1633 }

References Assert(), HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ SnapshotSetCommandId()

void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 437 of file snapmgr.c.

438 {
439  if (!FirstSnapshotSet)
440  return;
441 
442  if (CurrentSnapshot)
443  CurrentSnapshot->curcid = curcid;
444  if (SecondarySnapshot)
445  SecondarySnapshot->curcid = curcid;
446  /* Should we do the same with CatalogSnapshot? */
447 }

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

Referenced by CommandCounterIncrement().

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 1640 of file snapmgr.c.

1641 {
1642  HistoricSnapshot = NULL;
1643  tuplecid_data = NULL;
1644 }

References HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1581 of file snapmgr.c.

1582 {
1585  return true;
1586 
1587  return false;
1588 }

References pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by CopyFrom().

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 830 of file snapmgr.c.

831 {
832  if (snapshot == NULL)
833  return;
834 
835  Assert(snapshot->regd_count > 0);
837 
838  ResourceOwnerForgetSnapshot(owner, snapshot);
839 
840  snapshot->regd_count--;
841  if (snapshot->regd_count == 0)
843 
844  if (snapshot->regd_count == 0 && snapshot->active_count == 0)
845  {
846  FreeSnapshot(snapshot);
848  }
849 }
void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1324

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

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

◆ UpdateActiveSnapshotCommandId()

void UpdateActiveSnapshotCommandId ( void  )

Definition at line 693 of file snapmgr.c.

694 {
695  CommandId save_curcid,
696  curcid;
697 
698  Assert(ActiveSnapshot != NULL);
701 
702  /*
703  * Don't allow modification of the active snapshot during parallel
704  * operation. We share the snapshot to worker backends at the beginning
705  * of parallel operation, so any change to the snapshot can lead to
706  * inconsistencies. We have other defenses against
707  * CommandCounterIncrement, but there are a few places that call this
708  * directly, so we put an additional guard here.
709  */
710  save_curcid = ActiveSnapshot->as_snap->curcid;
711  curcid = GetCurrentCommandId(false);
712  if (IsInParallelMode() && save_curcid != curcid)
713  elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
714  ActiveSnapshot->as_snap->curcid = curcid;
715 }
uint32 CommandId
Definition: c.h:655
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:818

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 418 of file indexcmds.c.

419 {
420  int n_old_snapshots;
421  int i;
422  VirtualTransactionId *old_snapshots;
423 
424  old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
426  | PROC_IN_SAFE_IC,
427  &n_old_snapshots);
428  if (progress)
430 
431  for (i = 0; i < n_old_snapshots; i++)
432  {
433  if (!VirtualTransactionIdIsValid(old_snapshots[i]))
434  continue; /* found uninteresting in previous cycle */
435 
436  if (i > 0)
437  {
438  /* see if anything's changed ... */
439  VirtualTransactionId *newer_snapshots;
440  int n_newer_snapshots;
441  int j;
442  int k;
443 
444  newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
445  true, false,
447  | PROC_IN_SAFE_IC,
448  &n_newer_snapshots);
449  for (j = i; j < n_old_snapshots; j++)
450  {
451  if (!VirtualTransactionIdIsValid(old_snapshots[j]))
452  continue; /* found uninteresting in previous cycle */
453  for (k = 0; k < n_newer_snapshots; k++)
454  {
455  if (VirtualTransactionIdEquals(old_snapshots[j],
456  newer_snapshots[k]))
457  break;
458  }
459  if (k >= n_newer_snapshots) /* not there anymore */
460  SetInvalidVirtualTransactionId(old_snapshots[j]);
461  }
462  pfree(newer_snapshots);
463  }
464 
465  if (VirtualTransactionIdIsValid(old_snapshots[i]))
466  {
467  /* If requested, publish who we're going to wait for. */
468  if (progress)
469  {
470  PGPROC *holder = BackendIdGetProc(old_snapshots[i].backendId);
471 
472  if (holder)
474  holder->pid);
475  }
476  VirtualXactLock(old_snapshots[i], true);
477  }
478 
479  if (progress)
481  }
482 }
void pgstat_progress_update_param(int index, int64 val)
int j
Definition: isn.c:74
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4511
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:71
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:74
int progress
Definition: pgbench.c:261
#define PROC_IN_SAFE_IC
Definition: proc.h:58
#define PROC_IN_VACUUM
Definition: proc.h:57
#define PROC_IS_AUTOVACUUM
Definition: proc.h:56
VirtualTransactionId * GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
Definition: procarray.c:3231
#define PROGRESS_WAITFOR_DONE
Definition: progress.h:117
#define PROGRESS_WAITFOR_TOTAL
Definition: progress.h:116
#define PROGRESS_WAITFOR_CURRENT_PID
Definition: progress.h:118
PGPROC * BackendIdGetProc(int backendID)
Definition: sinvaladt.c:385
Definition: proc.h:162
int pid
Definition: proc.h:186

References BackendIdGetProc(), GetCurrentVirtualXIDs(), i, j, pfree(), pgstat_progress_update_param(), PGPROC::pid, PROC_IN_SAFE_IC, PROC_IN_VACUUM, PROC_IS_AUTOVACUUM, 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 1529 of file snapmgr.c.

1530 {
1531  return (exportedSnapshots != NIL);
1532 }

References exportedSnapshots, and NIL.

Referenced by PrepareTransaction().

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 1831 of file snapmgr.c.

1832 {
1833  /*
1834  * Make a quick range check to eliminate most XIDs without looking at the
1835  * xip arrays. Note that this is OK even if we convert a subxact XID to
1836  * its parent below, because a subxact with XID < xmin has surely also got
1837  * a parent with XID < xmin, while one with XID >= xmax must belong to a
1838  * parent that was not yet committed at the time of this snapshot.
1839  */
1840 
1841  /* Any xid < xmin is not in-progress */
1842  if (TransactionIdPrecedes(xid, snapshot->xmin))
1843  return false;
1844  /* Any xid >= xmax is in-progress */
1845  if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
1846  return true;
1847 
1848  /*
1849  * Snapshot information is stored slightly differently in snapshots taken
1850  * during recovery.
1851  */
1852  if (!snapshot->takenDuringRecovery)
1853  {
1854  /*
1855  * If the snapshot contains full subxact data, the fastest way to
1856  * check things is just to compare the given XID against both subxact
1857  * XIDs and top-level XIDs. If the snapshot overflowed, we have to
1858  * use pg_subtrans to convert a subxact XID to its parent XID, but
1859  * then we need only look at top-level XIDs not subxacts.
1860  */
1861  if (!snapshot->suboverflowed)
1862  {
1863  /* we have full data, so search subxip */
1864  if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1865  return true;
1866 
1867  /* not there, fall through to search xip[] */
1868  }
1869  else
1870  {
1871  /*
1872  * Snapshot overflowed, so convert xid to top-level. This is safe
1873  * because we eliminated too-old XIDs above.
1874  */
1875  xid = SubTransGetTopmostTransaction(xid);
1876 
1877  /*
1878  * If xid was indeed a subxact, we might now have an xid < xmin,
1879  * so recheck to avoid an array scan. No point in rechecking
1880  * xmax.
1881  */
1882  if (TransactionIdPrecedes(xid, snapshot->xmin))
1883  return false;
1884  }
1885 
1886  if (pg_lfind32(xid, snapshot->xip, snapshot->xcnt))
1887  return true;
1888  }
1889  else
1890  {
1891  /*
1892  * In recovery we store all xids in the subxip array because it is by
1893  * far the bigger array, and we mostly don't know which xids are
1894  * top-level and which are subxacts. The xip array is empty.
1895  *
1896  * We start by searching subtrans, if we overflowed.
1897  */
1898  if (snapshot->suboverflowed)
1899  {
1900  /*
1901  * Snapshot overflowed, so convert xid to top-level. This is safe
1902  * because we eliminated too-old XIDs above.
1903  */
1904  xid = SubTransGetTopmostTransaction(xid);
1905 
1906  /*
1907  * If xid was indeed a subxact, we might now have an xid < xmin,
1908  * so recheck to avoid an array scan. No point in rechecking
1909  * xmax.
1910  */
1911  if (TransactionIdPrecedes(xid, snapshot->xmin))
1912  return false;
1913  }
1914 
1915  /*
1916  * We now have either a top-level xid higher than xmin or an
1917  * indeterminate xid. We don't know whether it's top level or subxact
1918  * but it doesn't matter. If it's present, the xid is visible.
1919  */
1920  if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1921  return true;
1922  }
1923 
1924  return false;
1925 }
static bool pg_lfind32(uint32 key, uint32 *base, uint32 nelem)
Definition: pg_lfind.h:90
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
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 89 of file snapmgr.c.

Referenced by GetNonHistoricCatalogSnapshot().

◆ FirstSnapshotSet

◆ RecentXmin

◆ SnapshotAnyData

PGDLLIMPORT SnapshotData SnapshotAnyData
extern

Definition at line 91 of file snapmgr.c.

◆ SnapshotSelfData

PGDLLIMPORT SnapshotData SnapshotSelfData
extern

Definition at line 90 of file snapmgr.c.

◆ TransactionXmin