PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
snapmgr.h File Reference
#include "fmgr.h"
#include "utils/relcache.h"
#include "utils/resowner.h"
#include "utils/snapshot.h"
Include dependency graph for snapmgr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define OLD_SNAPSHOT_PADDING_ENTRIES   10
 
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES   (old_snapshot_threshold + OLD_SNAPSHOT_PADDING_ENTRIES)
 
#define RelationAllowsEarlyPruning(rel)
 
#define EarlyPruningEnabled(rel)   (old_snapshot_threshold >= 0 && RelationAllowsEarlyPruning(rel))
 

Functions

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

Variables

PGDLLIMPORT int old_snapshot_threshold
 
bool FirstSnapshotSet
 
TransactionId TransactionXmin
 
TransactionId RecentXmin
 
PGDLLIMPORT TransactionId RecentGlobalXmin
 
TransactionId RecentGlobalDataXmin
 

Macro Definition Documentation

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

Definition at line 46 of file snapmgr.h.

Referenced by index_build(), and reindex_index().

#define OLD_SNAPSHOT_PADDING_ENTRIES   10

Definition at line 31 of file snapmgr.h.

#define OLD_SNAPSHOT_TIME_MAP_ENTRIES   (old_snapshot_threshold + OLD_SNAPSHOT_PADDING_ENTRIES)
#define RelationAllowsEarlyPruning (   rel)
Value:
( \
&& !IsCatalogRelation(rel) \
)
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:92
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:559
bool RelationHasUnloggedIndex(Relation rel)
Definition: relcache.c:5980
#define RelationNeedsWAL(relation)
Definition: rel.h:505

Definition at line 38 of file snapmgr.h.

Referenced by TestForOldSnapshot_impl(), and TransactionIdLimitedForOldSnapshots().

Function Documentation

bool ActiveSnapshotSet ( void  )

Definition at line 851 of file snapmgr.c.

References NULL.

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

852 {
853  return ActiveSnapshot != NULL;
854 }
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
#define NULL
Definition: c.h:229
void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1059 of file snapmgr.c.

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

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

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

Definition at line 1023 of file snapmgr.c.

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

Referenced by AbortSubTransaction().

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

Definition at line 1002 of file snapmgr.c.

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

Referenced by CommitSubTransaction().

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

Definition at line 1616 of file snapmgr.c.

References AllocateDir(), buf, dirent::d_name, elog, FreeDir(), LOG, MAXPGPATH, NULL, ReadDir(), SNAPSHOT_EXPORT_DIR, snprintf(), and unlink().

Referenced by StartupXLOG().

1617 {
1618  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1619  DIR *s_dir;
1620  struct dirent *s_de;
1621 
1622  if (!(s_dir = AllocateDir(SNAPSHOT_EXPORT_DIR)))
1623  {
1624  /*
1625  * We really should have that directory in a sane cluster setup. But
1626  * then again if we don't, it's not fatal enough to make it FATAL.
1627  * Since we're running in the postmaster, LOG is our best bet.
1628  */
1629  elog(LOG, "could not open directory \"%s\": %m", SNAPSHOT_EXPORT_DIR);
1630  return;
1631  }
1632 
1633  while ((s_de = ReadDir(s_dir, SNAPSHOT_EXPORT_DIR)) != NULL)
1634  {
1635  if (strcmp(s_de->d_name, ".") == 0 ||
1636  strcmp(s_de->d_name, "..") == 0)
1637  continue;
1638 
1639  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1640  /* Again, unlink failure is not worthy of FATAL */
1641  if (unlink(buf))
1642  elog(LOG, "could not unlink file \"%s\": %m", buf);
1643  }
1644 
1645  FreeDir(s_dir);
1646 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:213
Definition: dirent.c:25
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:66
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2335
int unlink(const char *filename)
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2444
Size EstimateSnapshotSpace ( Snapshot  snapshot)

Definition at line 2038 of file snapmgr.c.

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

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

2039 {
2040  Size size;
2041 
2042  Assert(snap != InvalidSnapshot);
2043  Assert(snap->satisfies == HeapTupleSatisfiesMVCC);
2044 
2045  /* We allocate any XID arrays needed in the same palloc block. */
2046  size = add_size(sizeof(SerializedSnapshotData),
2047  mul_size(snap->xcnt, sizeof(TransactionId)));
2048  if (snap->subxcnt > 0 &&
2049  (!snap->suboverflowed || snap->takenDuringRecovery))
2050  size = add_size(size,
2051  mul_size(snap->subxcnt, sizeof(TransactionId)));
2052 
2053  return size;
2054 }
uint32 TransactionId
Definition: c.h:397
#define InvalidSnapshot
Definition: snapshot.h:25
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define Assert(condition)
Definition: c.h:675
size_t Size
Definition: c.h:356
bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:963
char* ExportSnapshot ( Snapshot  snapshot)

Definition at line 1159 of file snapmgr.c.

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

Referenced by pg_export_snapshot(), and SnapBuildExportSnapshot().

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

Definition at line 440 of file snapmgr.c.

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

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

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

Definition at line 379 of file snapmgr.c.

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

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

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

Definition at line 462 of file snapmgr.c.

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

Referenced by GetCatalogSnapshot(), and ScanPgRelation().

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

Definition at line 411 of file snapmgr.c.

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

Referenced by init_toast_snapshot().

412 {
413  Snapshot OldestRegisteredSnapshot = NULL;
414  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
415 
417  {
418  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
420  RegisteredLSN = OldestRegisteredSnapshot->lsn;
421  }
422 
423  if (OldestActiveSnapshot != NULL)
424  {
426 
427  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
429  }
430 
431  return OldestRegisteredSnapshot;
432 }
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
Snapshot as_snap
Definition: snapmgr.c:182
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr lsn
Definition: snapshot.h:112
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
#define pairingheap_container(type, membername, ptr)
Definition: pairingheap.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:191
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
TimestampTz GetOldSnapshotThresholdTimestamp ( void  )

Definition at line 1705 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1706 {
1707  TimestampTz threshold_timestamp;
1708 
1710  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1712 
1713  return threshold_timestamp;
1714 }
int64 TimestampTz
Definition: timestamp.h:39
slock_t mutex_threshold
Definition: snapmgr.c:91
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: snapmgr.c:92
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64
TimestampTz GetSnapshotCurrentTimestamp ( void  )

Definition at line 1680 of file snapmgr.c.

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

Referenced by GetSnapshotData(), and TransactionIdLimitedForOldSnapshots().

1681 {
1683 
1684  /*
1685  * Don't let time move backward; if it hasn't advanced, use the old value.
1686  */
1688  if (now <= oldSnapshotControl->current_timestamp)
1690  else
1693 
1694  return now;
1695 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
int64 TimestampTz
Definition: timestamp.h:39
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz current_timestamp
Definition: snapmgr.c:87
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64
slock_t mutex_current
Definition: snapmgr.c:86
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
Snapshot GetTransactionSnapshot ( void  )

Definition at line 304 of file snapmgr.c.

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

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

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

Definition at line 2018 of file snapmgr.c.

References NULL.

Referenced by GetCatalogSnapshot(), GetLatestSnapshot(), GetTransactionSnapshot(), HistoricSnapshotGetTupleCids(), RelationClearRelation(), RelationInitPhysicalAddr(), and SetTransactionSnapshot().

2019 {
2020  return HistoricSnapshot != NULL;
2021 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
#define NULL
Definition: c.h:229
struct HTAB* HistoricSnapshotGetTupleCids ( void  )

Definition at line 2024 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

2025 {
2027  return tuplecid_data;
2028 }
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define Assert(condition)
Definition: c.h:675
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2018
void ImportSnapshot ( const char *  idstr)

Definition at line 1430 of file snapmgr.c.

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

Referenced by ExecSetVariableStmt().

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

Definition at line 510 of file snapmgr.c.

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

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

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

Definition at line 531 of file snapmgr.c.

References InvalidateCatalogSnapshot(), NULL, and pairingheap_is_singular.

Referenced by PostgresMain().

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

Definition at line 1842 of file snapmgr.c.

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

Referenced by GetSnapshotData().

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

Definition at line 812 of file snapmgr.c.

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

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

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

Definition at line 733 of file snapmgr.c.

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

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

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

Definition at line 769 of file snapmgr.c.

References CopySnapshot(), and PushActiveSnapshot().

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

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

Definition at line 876 of file snapmgr.c.

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

Referenced by inv_open(), and RegisterSnapshot().

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

Definition at line 2121 of file snapmgr.c.

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

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

2122 {
2123  SerializedSnapshotData serialized_snapshot;
2124  Size size;
2125  Snapshot snapshot;
2126  TransactionId *serialized_xids;
2127 
2128  memcpy(&serialized_snapshot, start_address,
2129  sizeof(SerializedSnapshotData));
2130  serialized_xids = (TransactionId *)
2131  (start_address + sizeof(SerializedSnapshotData));
2132 
2133  /* We allocate any XID arrays needed in the same palloc block. */
2134  size = sizeof(SnapshotData)
2135  + serialized_snapshot.xcnt * sizeof(TransactionId)
2136  + serialized_snapshot.subxcnt * sizeof(TransactionId);
2137 
2138  /* Copy all required fields */
2140  snapshot->satisfies = HeapTupleSatisfiesMVCC;
2141  snapshot->xmin = serialized_snapshot.xmin;
2142  snapshot->xmax = serialized_snapshot.xmax;
2143  snapshot->xip = NULL;
2144  snapshot->xcnt = serialized_snapshot.xcnt;
2145  snapshot->subxip = NULL;
2146  snapshot->subxcnt = serialized_snapshot.subxcnt;
2147  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
2148  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
2149  snapshot->curcid = serialized_snapshot.curcid;
2150  snapshot->whenTaken = serialized_snapshot.whenTaken;
2151  snapshot->lsn = serialized_snapshot.lsn;
2152 
2153  /* Copy XIDs, if present. */
2154  if (serialized_snapshot.xcnt > 0)
2155  {
2156  snapshot->xip = (TransactionId *) (snapshot + 1);
2157  memcpy(snapshot->xip, serialized_xids,
2158  serialized_snapshot.xcnt * sizeof(TransactionId));
2159  }
2160 
2161  /* Copy SubXIDs, if present. */
2162  if (serialized_snapshot.subxcnt > 0)
2163  {
2164  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2165  serialized_snapshot.xcnt;
2166  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
2167  serialized_snapshot.subxcnt * sizeof(TransactionId));
2168  }
2169 
2170  /* Set the copied flag so that the caller will set refcounts correctly. */
2171  snapshot->regd_count = 0;
2172  snapshot->active_count = 0;
2173  snapshot->copied = true;
2174 
2175  return snapshot;
2176 }
SnapshotSatisfiesFunc satisfies
Definition: snapshot.h:54
MemoryContext TopTransactionContext
Definition: mcxt.c:48
uint32 TransactionId
Definition: c.h:397
bool copied
Definition: snapshot.h:94
XLogRecPtr lsn
Definition: snapshot.h:112
TimestampTz whenTaken
Definition: snapmgr.c:246
bool suboverflowed
Definition: snapshot.h:91
struct SnapshotData * Snapshot
Definition: snapshot.h:23
uint32 regd_count
Definition: snapshot.h:108
struct SnapshotData SnapshotData
TransactionId xmax
Definition: snapshot.h:67
TransactionId xmin
Definition: snapshot.h:66
TransactionId * xip
Definition: snapshot.h:77
TransactionId xmax
Definition: snapmgr.c:240
CommandId curcid
Definition: snapshot.h:96
#define NULL
Definition: c.h:229
bool takenDuringRecovery
Definition: snapshot.h:93
size_t Size
Definition: c.h:356
uint32 xcnt
Definition: snapshot.h:78
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
TransactionId xmin
Definition: snapmgr.c:239
TimestampTz whenTaken
Definition: snapshot.h:111
bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:963
TransactionId * subxip
Definition: snapshot.h:89
uint32 active_count
Definition: snapshot.h:107
int32 subxcnt
Definition: snapshot.h:90
void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  master_pgproc 
)

Definition at line 2185 of file snapmgr.c.

References InvalidPid, NULL, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2186 {
2187  SetTransactionSnapshot(snapshot, NULL, InvalidPid, master_pgproc);
2188 }
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:565
#define NULL
Definition: c.h:229
#define InvalidPid
Definition: miscadmin.h:33
void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

Definition at line 2062 of file snapmgr.c.

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

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

2063 {
2064  SerializedSnapshotData serialized_snapshot;
2065 
2066  Assert(snapshot->subxcnt >= 0);
2067 
2068  /* Copy all required fields */
2069  serialized_snapshot.xmin = snapshot->xmin;
2070  serialized_snapshot.xmax = snapshot->xmax;
2071  serialized_snapshot.xcnt = snapshot->xcnt;
2072  serialized_snapshot.subxcnt = snapshot->subxcnt;
2073  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2074  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2075  serialized_snapshot.curcid = snapshot->curcid;
2076  serialized_snapshot.whenTaken = snapshot->whenTaken;
2077  serialized_snapshot.lsn = snapshot->lsn;
2078 
2079  /*
2080  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2081  * taken during recovery - in that case, top-level XIDs are in subxip as
2082  * well, and we mustn't lose them.
2083  */
2084  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
2085  serialized_snapshot.subxcnt = 0;
2086 
2087  /* Copy struct to possibly-unaligned buffer */
2088  memcpy(start_address,
2089  &serialized_snapshot, sizeof(SerializedSnapshotData));
2090 
2091  /* Copy XID array */
2092  if (snapshot->xcnt > 0)
2093  memcpy((TransactionId *) (start_address +
2094  sizeof(SerializedSnapshotData)),
2095  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2096 
2097  /*
2098  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2099  * though, because it's not used anywhere in that case. Except if it's a
2100  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2101  * well in that case, so we mustn't lose them.
2102  */
2103  if (serialized_snapshot.subxcnt > 0)
2104  {
2105  Size subxipoff = sizeof(SerializedSnapshotData) +
2106  snapshot->xcnt * sizeof(TransactionId);
2107 
2108  memcpy((TransactionId *) (start_address + subxipoff),
2109  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2110  }
2111 }
uint32 TransactionId
Definition: c.h:397
XLogRecPtr lsn
Definition: snapshot.h:112
TimestampTz whenTaken
Definition: snapmgr.c:246
bool suboverflowed
Definition: snapshot.h:91
struct SerializedSnapshotData SerializedSnapshotData
TransactionId xmax
Definition: snapshot.h:67
TransactionId xmin
Definition: snapshot.h:66
TransactionId * xip
Definition: snapshot.h:77
TransactionId xmax
Definition: snapmgr.c:240
CommandId curcid
Definition: snapshot.h:96
#define Assert(condition)
Definition: c.h:675
bool takenDuringRecovery
Definition: snapshot.h:93
size_t Size
Definition: c.h:356
uint32 xcnt
Definition: snapshot.h:78
TransactionId xmin
Definition: snapmgr.c:239
TimestampTz whenTaken
Definition: snapshot.h:111
TransactionId * subxip
Definition: snapshot.h:89
int32 subxcnt
Definition: snapshot.h:90
void SetupHistoricSnapshot ( Snapshot  snapshot_now,
struct HTAB tuplecids 
)

Definition at line 1995 of file snapmgr.c.

References Assert, and NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1996 {
1997  Assert(historic_snapshot != NULL);
1998 
1999  /* setup the timetravel snapshot */
2000  HistoricSnapshot = historic_snapshot;
2001 
2002  /* setup (cmin, cmax) lookup hash */
2003  tuplecid_data = tuplecids;
2004 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void SnapMgrInit ( void  )

Definition at line 267 of file snapmgr.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

Definition at line 251 of file snapmgr.c.

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

Referenced by CreateSharedMemoryAndSemaphores(), and SnapMgrInit().

252 {
253  Size size;
254 
255  size = offsetof(OldSnapshotControlData, xid_by_minute);
256  if (old_snapshot_threshold > 0)
257  size = add_size(size, mul_size(sizeof(TransactionId),
259 
260  return size;
261 }
uint32 TransactionId
Definition: c.h:397
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:356
int old_snapshot_threshold
Definition: snapmgr.c:75
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
#define offsetof(type, field)
Definition: c.h:555
void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 544 of file snapmgr.c.

References SnapshotData::curcid, and FirstSnapshotSet.

Referenced by CommandCounterIncrement().

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

Definition at line 2011 of file snapmgr.c.

References NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

2012 {
2014  tuplecid_data = NULL;
2015 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define NULL
Definition: c.h:229
bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1649 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom().

1650 {
1653  return true;
1654 
1655  return false;
1656 }
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99
TransactionId TransactionIdLimitedForOldSnapshots ( TransactionId  recentXmin,
Relation  relation 
)

Definition at line 1735 of file snapmgr.c.

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

Referenced by heap_page_prune_opt(), and vacuum_set_xid_limits().

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

Definition at line 918 of file snapmgr.c.

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

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

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

Definition at line 781 of file snapmgr.c.

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

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

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

Definition at line 1603 of file snapmgr.c.

References NIL.

Referenced by PrepareTransaction().

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

Variable Documentation

TransactionId RecentGlobalDataXmin

Definition at line 167 of file snapmgr.c.

Referenced by GetSnapshotData(), and heap_page_prune_opt().