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:91
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:560
bool RelationHasUnloggedIndex(Relation rel)
Definition: relcache.c:5969
#define RelationNeedsWAL(relation)
Definition: rel.h:506

Definition at line 38 of file snapmgr.h.

Referenced by TestForOldSnapshot_impl(), and TransactionIdLimitedForOldSnapshots().

Function Documentation

bool ActiveSnapshotSet ( void  )

Definition at line 846 of file snapmgr.c.

References NULL.

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

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

Definition at line 1054 of file snapmgr.c.

References ActiveSnapshotElt::as_next, Assert, buf, elog, FirstSnapshotSet, GetTopTransactionId(), i, InvalidateCatalogSnapshot(), lfirst, list_length(), MAXPGPATH, MyPgXact, NIL, NULL, pairingheap_is_empty, pairingheap_remove(), pairingheap_reset, SnapshotData::ph_node, SnapshotData::regd_count, SnapshotResetXmin(), unlink(), WARNING, XactExportFilePath, and PGXACT::xmin.

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

1055 {
1056  /*
1057  * In transaction-snapshot mode we must release our privately-managed
1058  * reference to the transaction snapshot. We must remove it from
1059  * RegisteredSnapshots to keep the check below happy. But we don't bother
1060  * to do FreeSnapshot, for two reasons: the memory will go away with
1061  * TopTransactionContext anyway, and if someone has left the snapshot
1062  * stacked as active, we don't want the code below to be chasing through a
1063  * dangling pointer.
1064  */
1065  if (FirstXactSnapshot != NULL)
1066  {
1070  }
1072 
1073  /*
1074  * If we exported any snapshots, clean them up.
1075  */
1076  if (exportedSnapshots != NIL)
1077  {
1079  int i;
1080  char buf[MAXPGPATH];
1081  ListCell *lc;
1082 
1083  /*
1084  * Get rid of the files. Unlink failure is only a WARNING because (1)
1085  * it's too late to abort the transaction, and (2) leaving a leaked
1086  * file around has little real consequence anyway.
1087  */
1088  for (i = 1; i <= list_length(exportedSnapshots); i++)
1089  {
1090  XactExportFilePath(buf, myxid, i, "");
1091  if (unlink(buf))
1092  elog(WARNING, "could not unlink file \"%s\": %m", buf);
1093  }
1094 
1095  /*
1096  * As with the FirstXactSnapshot, we needn't spend any effort on
1097  * cleaning up the per-snapshot data structures, but we do need to
1098  * remove them from RegisteredSnapshots to prevent a warning below.
1099  */
1100  foreach(lc, exportedSnapshots)
1101  {
1102  Snapshot snap = (Snapshot) lfirst(lc);
1103 
1105  }
1106 
1108  }
1109 
1110  /* Drop catalog snapshot if any */
1112 
1113  /* On commit, complain about leftover snapshots */
1114  if (isCommit)
1115  {
1116  ActiveSnapshotElt *active;
1117 
1119  elog(WARNING, "registered snapshots seem to remain after cleanup");
1120 
1121  /* complain about unpopped active snapshots */
1122  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1123  elog(WARNING, "snapshot %p still active", active);
1124  }
1125 
1126  /*
1127  * And reset our state. We don't need to free the memory explicitly --
1128  * it'll go away with TopTransactionContext.
1129  */
1130  ActiveSnapshot = NULL;
1133 
1136 
1137  FirstSnapshotSet = false;
1138 
1139  /*
1140  * During normal commit processing, we call
1141  * ProcArrayEndTransaction() to reset the PgXact->xmin. That call
1142  * happens prior to the call to AtEOXact_Snapshot(), so we need
1143  * 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
uint32 TransactionId
Definition: c.h:397
#define pairingheap_reset(h)
Definition: pairingheap.h:93
TransactionId xmin
Definition: proc.h:213
static void SnapshotResetXmin(void)
Definition: snapmgr.c:973
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:210
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
struct SnapshotData * Snapshot
Definition: snapshot.h:23
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:219
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
bool FirstSnapshotSet
Definition: snapmgr.c:203
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:191
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:66
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:184
int unlink(const char *filename)
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:506
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
#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 int list_length(const List *l)
Definition: pg_list.h:89
int i
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
#define XactExportFilePath(path, xid, num, suffix)
Definition: snapmgr.c:214
void AtSubAbort_Snapshot ( int  level)

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

1019 {
1020  /* Forget the active snapshots set by this subtransaction */
1021  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
1022  {
1024 
1025  next = ActiveSnapshot->as_next;
1026 
1027  /*
1028  * Decrement the snapshot's active count. If it's still registered or
1029  * marked as active by an outer subtransaction, we can't free it yet.
1030  */
1033 
1034  if (ActiveSnapshot->as_snap->active_count == 0 &&
1037 
1038  /* and free the stack element */
1040 
1041  ActiveSnapshot = next;
1042  if (ActiveSnapshot == NULL)
1044  }
1045 
1047 }
Snapshot as_snap
Definition: snapmgr.c:182
static int32 next
Definition: blutils.c:210
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:710
static void SnapshotResetXmin(void)
Definition: snapmgr.c:973
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 997 of file snapmgr.c.

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

Referenced by CommitSubTransaction().

998 {
999  ActiveSnapshotElt *active;
1000 
1001  /*
1002  * Relabel the active snapshots set in this subtransaction as though they
1003  * are owned by the parent subxact.
1004  */
1005  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1006  {
1007  if (active->as_level < level)
1008  break;
1009  active->as_level = level - 1;
1010  }
1011 }
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 1579 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().

1580 {
1581  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1582  DIR *s_dir;
1583  struct dirent *s_de;
1584 
1585  if (!(s_dir = AllocateDir(SNAPSHOT_EXPORT_DIR)))
1586  {
1587  /*
1588  * We really should have that directory in a sane cluster setup. But
1589  * then again if we don't, it's not fatal enough to make it FATAL.
1590  * Since we're running in the postmaster, LOG is our best bet.
1591  */
1592  elog(LOG, "could not open directory \"%s\": %m", SNAPSHOT_EXPORT_DIR);
1593  return;
1594  }
1595 
1596  while ((s_de = ReadDir(s_dir, SNAPSHOT_EXPORT_DIR)) != NULL)
1597  {
1598  if (strcmp(s_de->d_name, ".") == 0 ||
1599  strcmp(s_de->d_name, "..") == 0)
1600  continue;
1601 
1602  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1603  /* Again, unlink failure is not worthy of FATAL */
1604  if (unlink(buf))
1605  elog(LOG, "could not unlink file \"%s\": %m", buf);
1606  }
1607 
1608  FreeDir(s_dir);
1609 }
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 2001 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().

2002 {
2003  Size size;
2004 
2005  Assert(snap != InvalidSnapshot);
2006  Assert(snap->satisfies == HeapTupleSatisfiesMVCC);
2007 
2008  /* We allocate any XID arrays needed in the same palloc block. */
2009  size = add_size(sizeof(SerializedSnapshotData),
2010  mul_size(snap->xcnt, sizeof(TransactionId)));
2011  if (snap->subxcnt > 0 &&
2012  (!snap->suboverflowed || snap->takenDuringRecovery))
2013  size = add_size(size,
2014  mul_size(snap->subxcnt, sizeof(TransactionId)));
2015 
2016  return size;
2017 }
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(), buf, CopySnapshot(), StringInfoData::data, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, FreeFile(), GetMaxSnapshotSubxidCount(), GetTopTransactionId(), i, initStringInfo(), IsSubTransaction(), lappend(), StringInfoData::len, list_length(), MAXPGPATH, MemoryContextSwitchTo(), MyDatabaseId, pairingheap_add(), PG_BINARY_W, SnapshotData::ph_node, pstrdup(), SnapshotData::regd_count, SNAPSHOT_EXPORT_DIR, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TopTransactionContext, TransactionIdPrecedes(), XactExportFilePath, 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  int nchildren;
1164  int addTopXid;
1166  FILE *f;
1167  int i;
1168  MemoryContext oldcxt;
1169  char path[MAXPGPATH];
1170  char pathtmp[MAXPGPATH];
1171 
1172  /*
1173  * It's tempting to call RequireTransactionChain here, since it's not very
1174  * useful to export a snapshot that will disappear immediately afterwards.
1175  * However, we haven't got enough information to do that, since we don't
1176  * know if we're at top level or not. For example, we could be inside a
1177  * plpgsql function that is going to fire off other transactions via
1178  * dblink. Rather than disallow perfectly legitimate usages, don't make a
1179  * check.
1180  *
1181  * Also note that we don't make any restriction on the transaction's
1182  * isolation level; however, importers must check the level if they are
1183  * serializable.
1184  */
1185 
1186  /*
1187  * This will assign a transaction ID if we do not yet have one.
1188  */
1189  topXid = GetTopTransactionId();
1190 
1191  /*
1192  * We cannot export a snapshot from a subtransaction because there's no
1193  * easy way for importers to verify that the same subtransaction is still
1194  * running.
1195  */
1196  if (IsSubTransaction())
1197  ereport(ERROR,
1198  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1199  errmsg("cannot export a snapshot from a subtransaction")));
1200 
1201  /*
1202  * We do however allow previous committed subtransactions to exist.
1203  * Importers of the snapshot must see them as still running, so get their
1204  * XIDs to add them to the snapshot.
1205  */
1206  nchildren = xactGetCommittedChildren(&children);
1207 
1208  /*
1209  * Copy the snapshot into TopTransactionContext, add it to the
1210  * exportedSnapshots list, and mark it pseudo-registered. We do this to
1211  * ensure that the snapshot's xmin is honored for the rest of the
1212  * transaction.
1213  */
1214  snapshot = CopySnapshot(snapshot);
1215 
1218  MemoryContextSwitchTo(oldcxt);
1219 
1220  snapshot->regd_count++;
1222 
1223  /*
1224  * Fill buf with a text serialization of the snapshot, plus identification
1225  * data about this transaction. The format expected by ImportSnapshot is
1226  * pretty rigid: each line must be fieldname:value.
1227  */
1228  initStringInfo(&buf);
1229 
1230  appendStringInfo(&buf, "xid:%u\n", topXid);
1231  appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1232  appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1233  appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1234 
1235  appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1236  appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1237 
1238  /*
1239  * We must include our own top transaction ID in the top-xid data, since
1240  * by definition we will still be running when the importing transaction
1241  * adopts the snapshot, but GetSnapshotData never includes our own XID in
1242  * the snapshot. (There must, therefore, be enough room to add it.)
1243  *
1244  * However, it could be that our topXid is after the xmax, in which case
1245  * we shouldn't include it because xip[] members are expected to be before
1246  * xmax. (We need not make the same check for subxip[] members, see
1247  * snapshot.h.)
1248  */
1249  addTopXid = TransactionIdPrecedes(topXid, snapshot->xmax) ? 1 : 0;
1250  appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1251  for (i = 0; i < snapshot->xcnt; i++)
1252  appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1253  if (addTopXid)
1254  appendStringInfo(&buf, "xip:%u\n", topXid);
1255 
1256  /*
1257  * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1258  * we have to cope with possible overflow.
1259  */
1260  if (snapshot->suboverflowed ||
1261  snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1262  appendStringInfoString(&buf, "sof:1\n");
1263  else
1264  {
1265  appendStringInfoString(&buf, "sof:0\n");
1266  appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1267  for (i = 0; i < snapshot->subxcnt; i++)
1268  appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1269  for (i = 0; i < nchildren; i++)
1270  appendStringInfo(&buf, "sxp:%u\n", children[i]);
1271  }
1272  appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1273 
1274  /*
1275  * Now write the text representation into a file. We first write to a
1276  * ".tmp" filename, and rename to final filename if no error. This
1277  * ensures that no other backend can read an incomplete file
1278  * (ImportSnapshot won't allow it because of its valid-characters check).
1279  */
1280  XactExportFilePath(pathtmp, topXid, list_length(exportedSnapshots), ".tmp");
1281  if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1282  ereport(ERROR,
1284  errmsg("could not create file \"%s\": %m", pathtmp)));
1285 
1286  if (fwrite(buf.data, buf.len, 1, f) != 1)
1287  ereport(ERROR,
1289  errmsg("could not write to file \"%s\": %m", pathtmp)));
1290 
1291  /* no fsync() since file need not survive a system crash */
1292 
1293  if (FreeFile(f))
1294  ereport(ERROR,
1296  errmsg("could not write to file \"%s\": %m", pathtmp)));
1297 
1298  /*
1299  * Now that we have written everything into a .tmp file, rename the file
1300  * to remove the .tmp suffix.
1301  */
1302  XactExportFilePath(path, topXid, list_length(exportedSnapshots), "");
1303 
1304  if (rename(pathtmp, path) < 0)
1305  ereport(ERROR,
1307  errmsg("could not rename file \"%s\" to \"%s\": %m",
1308  pathtmp, path)));
1309 
1310  /*
1311  * The basename of the file is what we return from pg_export_snapshot().
1312  * It's already in path in a textual format and we know that the path
1313  * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1314  * and pstrdup it so as not to return the address of a local variable.
1315  */
1316  return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1317 }
int xactGetCommittedChildren(TransactionId **ptr)
Definition: xact.c:5084
MemoryContext TopTransactionContext
Definition: mcxt.c:48
uint32 TransactionId
Definition: c.h:397
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
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
uint32 regd_count
Definition: snapshot.h:108
static List * exportedSnapshots
Definition: snapmgr.c:219
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:213
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#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:189
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
#define ereport(elevel, rest)
Definition: elog.h:122
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
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
Oid MyDatabaseId
Definition: globals.c:76
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:655
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:4376
uint32 xcnt
Definition: snapshot.h:78
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 XactExportFilePath(path, xid, num, suffix)
Definition: snapmgr.c:214
TransactionId * subxip
Definition: snapshot.h:89
int32 subxcnt
Definition: snapshot.h:90
Snapshot GetCatalogSnapshot ( Oid  relid)

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

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

Definition at line 375 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(), and validateForeignKeyConstraint().

376 {
377  /*
378  * We might be able to relax this, but nothing that could otherwise work
379  * needs it.
380  */
381  if (IsInParallelMode())
382  elog(ERROR,
383  "cannot update SecondarySnapshot during a parallel operation");
384 
385  /*
386  * So far there are no cases requiring support for GetLatestSnapshot()
387  * during logical decoding, but it wouldn't be hard to add if required.
388  */
390 
391  /* If first call in transaction, go ahead and set the xact snapshot */
392  if (!FirstSnapshotSet)
393  return GetTransactionSnapshot();
394 
396 
397  return SecondarySnapshot;
398 }
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
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:1981
static Snapshot SecondarySnapshot
Definition: snapmgr.c:150
#define elog
Definition: elog.h:219
Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 458 of file snapmgr.c.

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

Referenced by GetCatalogSnapshot(), and ScanPgRelation().

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

408 {
409  Snapshot OldestRegisteredSnapshot = NULL;
410  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
411 
413  {
414  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
416  RegisteredLSN = OldestRegisteredSnapshot->lsn;
417  }
418 
419  if (OldestActiveSnapshot != NULL)
420  {
422 
423  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
425  }
426 
427  return OldestRegisteredSnapshot;
428 }
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 1668 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1669 {
1670  TimestampTz threshold_timestamp;
1671 
1673  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1675 
1676  return threshold_timestamp;
1677 }
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 1643 of file snapmgr.c.

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

Referenced by GetSnapshotData(), and TransactionIdLimitedForOldSnapshots().

1644 {
1646 
1647  /*
1648  * Don't let time move backward; if it hasn't advanced, use the old value.
1649  */
1651  if (now <= oldSnapshotControl->current_timestamp)
1653  else
1656 
1657  return now;
1658 }
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:86
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64
slock_t mutex_current
Definition: snapmgr.c:85
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
Snapshot GetTransactionSnapshot ( void  )

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

301 {
302  /*
303  * Return historic snapshot if doing logical decoding. We'll never need a
304  * non-historic transaction snapshot in this (sub-)transaction, so there's
305  * no need to be careful to set one up for later calls to
306  * GetTransactionSnapshot().
307  */
309  {
311  return HistoricSnapshot;
312  }
313 
314  /* First call in transaction? */
315  if (!FirstSnapshotSet)
316  {
317  /*
318  * Don't allow catalog snapshot to be older than xact snapshot. Must
319  * do this first to allow the empty-heap Assert to succeed.
320  */
322 
325 
326  if (IsInParallelMode())
327  elog(ERROR,
328  "cannot take query snapshot during a parallel operation");
329 
330  /*
331  * In transaction-snapshot mode, the first snapshot must live until
332  * end of xact regardless of what the caller does with it, so we must
333  * make a copy of it rather than returning CurrentSnapshotData
334  * directly. Furthermore, if we're running in serializable mode,
335  * predicate.c needs to wrap the snapshot fetch in its own processing.
336  */
338  {
339  /* First, create the snapshot in CurrentSnapshotData */
342  else
344  /* Make a saved copy */
347  /* Mark it as "registered" in FirstXactSnapshot */
350  }
351  else
353 
354  FirstSnapshotSet = true;
355  return CurrentSnapshot;
356  }
357 
359  return CurrentSnapshot;
360 
361  /* Don't allow catalog snapshot to be older than xact snapshot. */
363 
365 
366  return CurrentSnapshot;
367 }
#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:506
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:655
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:1620
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1508
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1981
#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 1981 of file snapmgr.c.

References NULL.

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

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

Definition at line 1987 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

1988 {
1990  return tuplecid_data;
1991 }
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define Assert(condition)
Definition: c.h:675
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1981
void ImportSnapshot ( const char *  idstr)

Definition at line 1395 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(), parseXidFromText(), PG_BINARY_R, SetTransactionSnapshot(), SNAPSHOT_EXPORT_DIR, snprintf(), SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdIsNormal, XACT_SERIALIZABLE, XactReadOnly, SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by ExecSetVariableStmt().

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

507 {
508  if (CatalogSnapshot)
509  {
513  }
514 }
static void SnapshotResetXmin(void)
Definition: snapmgr.c:973
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 527 of file snapmgr.c.

References InvalidateCatalogSnapshot(), NULL, and pairingheap_is_singular.

Referenced by PostgresMain().

528 {
529  if (CatalogSnapshot &&
530  ActiveSnapshot == NULL &&
533 }
static Snapshot CatalogSnapshot
Definition: snapmgr.c:151
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:506
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 1805 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().

1806 {
1807  TimestampTz ts;
1808  TransactionId latest_xmin;
1809  TimestampTz update_ts;
1810  bool map_update_required = false;
1811 
1812  /* Never call this function when old snapshot checking is disabled. */
1814 
1815  ts = AlignTimestampToMinuteBoundary(whenTaken);
1816 
1817  /*
1818  * Keep track of the latest xmin seen by any process. Update mapping with
1819  * a new value when we have crossed a bucket boundary.
1820  */
1822  latest_xmin = oldSnapshotControl->latest_xmin;
1823  update_ts = oldSnapshotControl->next_map_update;
1824  if (ts > update_ts)
1825  {
1827  map_update_required = true;
1828  }
1829  if (TransactionIdFollows(xmin, latest_xmin))
1832 
1833  /* We only needed to update the most recent xmin value. */
1834  if (!map_update_required)
1835  return;
1836 
1837  /* No further tracking needed for 0 (used for testing). */
1838  if (old_snapshot_threshold == 0)
1839  return;
1840 
1841  /*
1842  * We don't want to do something stupid with unusual values, but we don't
1843  * want to litter the log with warnings or break otherwise normal
1844  * processing for this feature; so if something seems unreasonable, just
1845  * log at DEBUG level and return without doing anything.
1846  */
1847  if (whenTaken < 0)
1848  {
1849  elog(DEBUG1,
1850  "MaintainOldSnapshotTimeMapping called with negative whenTaken = %ld",
1851  (long) whenTaken);
1852  return;
1853  }
1854  if (!TransactionIdIsNormal(xmin))
1855  {
1856  elog(DEBUG1,
1857  "MaintainOldSnapshotTimeMapping called with xmin = %lu",
1858  (unsigned long) xmin);
1859  return;
1860  }
1861 
1862  LWLockAcquire(OldSnapshotTimeMapLock, LW_EXCLUSIVE);
1863 
1869 
1870  if (oldSnapshotControl->count_used == 0)
1871  {
1872  /* set up first entry for empty mapping */
1876  oldSnapshotControl->xid_by_minute[0] = xmin;
1877  }
1878  else if (ts < oldSnapshotControl->head_timestamp)
1879  {
1880  /* old ts; log it at DEBUG */
1881  LWLockRelease(OldSnapshotTimeMapLock);
1882  elog(DEBUG1,
1883  "MaintainOldSnapshotTimeMapping called with old whenTaken = %ld",
1884  (long) whenTaken);
1885  return;
1886  }
1887  else if (ts <= (oldSnapshotControl->head_timestamp +
1889  * USECS_PER_MINUTE)))
1890  {
1891  /* existing mapping; advance xid if possible */
1892  int bucket = (oldSnapshotControl->head_offset
1894  / USECS_PER_MINUTE))
1896 
1898  oldSnapshotControl->xid_by_minute[bucket] = xmin;
1899  }
1900  else
1901  {
1902  /* We need a new bucket, but it might not be the very next one. */
1903  int advance = ((ts - oldSnapshotControl->head_timestamp)
1904  / USECS_PER_MINUTE);
1905 
1907 
1908  if (advance >= OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1909  {
1910  /* Advance is so far that all old data is junk; start over. */
1913  oldSnapshotControl->xid_by_minute[0] = xmin;
1914  }
1915  else
1916  {
1917  /* Store the new value in one or more buckets. */
1918  int i;
1919 
1920  for (i = 0; i < advance; i++)
1921  {
1923  {
1924  /* Map full and new value replaces old head. */
1925  int old_head = oldSnapshotControl->head_offset;
1926 
1927  if (old_head == (OLD_SNAPSHOT_TIME_MAP_ENTRIES - 1))
1929  else
1930  oldSnapshotControl->head_offset = old_head + 1;
1931  oldSnapshotControl->xid_by_minute[old_head] = xmin;
1932  }
1933  else
1934  {
1935  /* Extend map to unused entry. */
1936  int new_tail = (oldSnapshotControl->head_offset
1939 
1941  oldSnapshotControl->xid_by_minute[new_tail] = xmin;
1942  }
1943  }
1944  }
1945  }
1946 
1947  LWLockRelease(OldSnapshotTimeMapLock);
1948 }
#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:87
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:1629
int old_snapshot_threshold
Definition: snapmgr.c:74
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 807 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(), and vacuum_rel().

808 {
809  ActiveSnapshotElt *newstack;
810 
811  newstack = ActiveSnapshot->as_next;
812 
814 
816 
817  if (ActiveSnapshot->as_snap->active_count == 0 &&
820 
822  ActiveSnapshot = newstack;
823  if (ActiveSnapshot == NULL)
825 
827 }
Snapshot as_snap
Definition: snapmgr.c:182
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:710
static void SnapshotResetXmin(void)
Definition: snapmgr.c:973
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 728 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(), and vacuum_rel().

729 {
730  ActiveSnapshotElt *newactive;
731 
732  Assert(snap != InvalidSnapshot);
733 
735 
736  /*
737  * Checking SecondarySnapshot is probably useless here, but it seems
738  * better to be sure.
739  */
740  if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
741  newactive->as_snap = CopySnapshot(snap);
742  else
743  newactive->as_snap = snap;
744 
745  newactive->as_next = ActiveSnapshot;
747 
748  newactive->as_snap->active_count++;
749 
750  ActiveSnapshot = newactive;
751  if (OldestActiveSnapshot == NULL)
753 }
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:655
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 764 of file snapmgr.c.

References CopySnapshot(), and PushActiveSnapshot().

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

765 {
766  PushActiveSnapshot(CopySnapshot(snapshot));
767 }
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:655
Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

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

872 {
873  Snapshot snap;
874 
875  if (snapshot == InvalidSnapshot)
876  return InvalidSnapshot;
877 
878  /* Static snapshot? Create a persistent copy */
879  snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
880 
881  /* and tell resowner.c about it */
883  snap->regd_count++;
884  ResourceOwnerRememberSnapshot(owner, snap);
885 
886  if (snap->regd_count == 1)
888 
889  return snap;
890 }
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:655
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 2084 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().

2085 {
2086  SerializedSnapshotData serialized_snapshot;
2087  Size size;
2088  Snapshot snapshot;
2089  TransactionId *serialized_xids;
2090 
2091  memcpy(&serialized_snapshot, start_address,
2092  sizeof(SerializedSnapshotData));
2093  serialized_xids = (TransactionId *)
2094  (start_address + sizeof(SerializedSnapshotData));
2095 
2096  /* We allocate any XID arrays needed in the same palloc block. */
2097  size = sizeof(SnapshotData)
2098  + serialized_snapshot.xcnt * sizeof(TransactionId)
2099  + serialized_snapshot.subxcnt * sizeof(TransactionId);
2100 
2101  /* Copy all required fields */
2103  snapshot->satisfies = HeapTupleSatisfiesMVCC;
2104  snapshot->xmin = serialized_snapshot.xmin;
2105  snapshot->xmax = serialized_snapshot.xmax;
2106  snapshot->xip = NULL;
2107  snapshot->xcnt = serialized_snapshot.xcnt;
2108  snapshot->subxip = NULL;
2109  snapshot->subxcnt = serialized_snapshot.subxcnt;
2110  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
2111  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
2112  snapshot->curcid = serialized_snapshot.curcid;
2113  snapshot->whenTaken = serialized_snapshot.whenTaken;
2114  snapshot->lsn = serialized_snapshot.lsn;
2115 
2116  /* Copy XIDs, if present. */
2117  if (serialized_snapshot.xcnt > 0)
2118  {
2119  snapshot->xip = (TransactionId *) (snapshot + 1);
2120  memcpy(snapshot->xip, serialized_xids,
2121  serialized_snapshot.xcnt * sizeof(TransactionId));
2122  }
2123 
2124  /* Copy SubXIDs, if present. */
2125  if (serialized_snapshot.subxcnt > 0)
2126  {
2127  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2128  serialized_snapshot.xcnt;
2129  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
2130  serialized_snapshot.subxcnt * sizeof(TransactionId));
2131  }
2132 
2133  /* Set the copied flag so that the caller will set refcounts correctly. */
2134  snapshot->regd_count = 0;
2135  snapshot->active_count = 0;
2136  snapshot->copied = true;
2137 
2138  return snapshot;
2139 }
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:242
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:236
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:235
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 2148 of file snapmgr.c.

References InvalidTransactionId, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2149 {
2150  SetTransactionSnapshot(snapshot, InvalidTransactionId, master_pgproc);
2151 }
#define InvalidTransactionId
Definition: transam.h:31
static void SetTransactionSnapshot(Snapshot sourcesnap, TransactionId sourcexid, PGPROC *sourceproc)
Definition: snapmgr.c:561
void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

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

2026 {
2027  SerializedSnapshotData serialized_snapshot;
2028 
2029  Assert(snapshot->subxcnt >= 0);
2030 
2031  /* Copy all required fields */
2032  serialized_snapshot.xmin = snapshot->xmin;
2033  serialized_snapshot.xmax = snapshot->xmax;
2034  serialized_snapshot.xcnt = snapshot->xcnt;
2035  serialized_snapshot.subxcnt = snapshot->subxcnt;
2036  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2037  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2038  serialized_snapshot.curcid = snapshot->curcid;
2039  serialized_snapshot.whenTaken = snapshot->whenTaken;
2040  serialized_snapshot.lsn = snapshot->lsn;
2041 
2042  /*
2043  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2044  * taken during recovey - in that case, top-level XIDs are in subxip as
2045  * well, and we mustn't lose them.
2046  */
2047  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
2048  serialized_snapshot.subxcnt = 0;
2049 
2050  /* Copy struct to possibly-unaligned buffer */
2051  memcpy(start_address,
2052  &serialized_snapshot, sizeof(SerializedSnapshotData));
2053 
2054  /* Copy XID array */
2055  if (snapshot->xcnt > 0)
2056  memcpy((TransactionId *) (start_address +
2057  sizeof(SerializedSnapshotData)),
2058  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2059 
2060  /*
2061  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2062  * though, because it's not used anywhere in that case. Except if it's a
2063  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2064  * well in that case, so we mustn't lose them.
2065  */
2066  if (serialized_snapshot.subxcnt > 0)
2067  {
2068  Size subxipoff = sizeof(SerializedSnapshotData) +
2069  snapshot->xcnt * sizeof(TransactionId);
2070 
2071  memcpy((TransactionId *) (start_address + subxipoff),
2072  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2073  }
2074 }
uint32 TransactionId
Definition: c.h:397
XLogRecPtr lsn
Definition: snapshot.h:112
TimestampTz whenTaken
Definition: snapmgr.c:242
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:236
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:235
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 1958 of file snapmgr.c.

References Assert, and NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1959 {
1960  Assert(historic_snapshot != NULL);
1961 
1962  /* setup the timetravel snapshot */
1963  HistoricSnapshot = historic_snapshot;
1964 
1965  /* setup (cmin, cmax) lookup hash */
1966  tuplecid_data = tuplecids;
1967 }
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 263 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().

264 {
265  bool found;
266 
267  /*
268  * Create or attach to the OldSnapshotControlData structure.
269  */
271  ShmemInitStruct("OldSnapshotControlData",
272  SnapMgrShmemSize(), &found);
273 
274  if (!found)
275  {
287  }
288 }
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:87
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:86
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:85
TimestampTz head_timestamp
Definition: snapmgr.c:124
Size SnapMgrShmemSize(void)
Definition: snapmgr.c:247
Size SnapMgrShmemSize ( void  )

Definition at line 247 of file snapmgr.c.

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

Referenced by CreateSharedMemoryAndSemaphores(), and SnapMgrInit().

248 {
249  Size size;
250 
251  size = offsetof(OldSnapshotControlData, xid_by_minute);
252  if (old_snapshot_threshold > 0)
253  size = add_size(size, mul_size(sizeof(TransactionId),
255 
256  return size;
257 }
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:74
#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 540 of file snapmgr.c.

References SnapshotData::curcid, and FirstSnapshotSet.

Referenced by CommandCounterIncrement().

541 {
542  if (!FirstSnapshotSet)
543  return;
544 
545  if (CurrentSnapshot)
546  CurrentSnapshot->curcid = curcid;
547  if (SecondarySnapshot)
548  SecondarySnapshot->curcid = curcid;
549  /* Should we do the same with CatalogSnapshot? */
550 }
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 1974 of file snapmgr.c.

References NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1975 {
1977  tuplecid_data = NULL;
1978 }
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 1612 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom().

1613 {
1616  return true;
1617 
1618  return false;
1619 }
#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 1698 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().

1700 {
1701  if (TransactionIdIsNormal(recentXmin)
1702  && old_snapshot_threshold >= 0
1703  && RelationAllowsEarlyPruning(relation))
1704  {
1706  TransactionId xlimit = recentXmin;
1707  TransactionId latest_xmin;
1708  TimestampTz update_ts;
1709  bool same_ts_as_threshold = false;
1710 
1712  latest_xmin = oldSnapshotControl->latest_xmin;
1713  update_ts = oldSnapshotControl->next_map_update;
1715 
1716  /*
1717  * Zero threshold always overrides to latest xmin, if valid. Without
1718  * some heuristic it will find its own snapshot too old on, for
1719  * example, a simple UPDATE -- which would make it useless for most
1720  * testing, but there is no principled way to ensure that it doesn't
1721  * fail in this way. Use a five-second delay to try to get useful
1722  * testing behavior, but this may need adjustment.
1723  */
1724  if (old_snapshot_threshold == 0)
1725  {
1726  if (TransactionIdPrecedes(latest_xmin, MyPgXact->xmin)
1727  && TransactionIdFollows(latest_xmin, xlimit))
1728  xlimit = latest_xmin;
1729 
1730  ts -= 5 * USECS_PER_SEC;
1732 
1733  return xlimit;
1734  }
1735 
1738 
1739  /* Check for fast exit without LW locking. */
1742  {
1744  same_ts_as_threshold = true;
1745  }
1747 
1748  if (!same_ts_as_threshold)
1749  {
1750  if (ts == update_ts)
1751  {
1752  xlimit = latest_xmin;
1753  if (NormalTransactionIdFollows(xlimit, recentXmin))
1755  }
1756  else
1757  {
1758  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1759 
1762  {
1763  int offset;
1764 
1765  offset = ((ts - oldSnapshotControl->head_timestamp)
1766  / USECS_PER_MINUTE);
1767  if (offset > oldSnapshotControl->count_used - 1)
1768  offset = oldSnapshotControl->count_used - 1;
1769  offset = (oldSnapshotControl->head_offset + offset)
1771  xlimit = oldSnapshotControl->xid_by_minute[offset];
1772 
1773  if (NormalTransactionIdFollows(xlimit, recentXmin))
1775  }
1776 
1777  LWLockRelease(OldSnapshotTimeMapLock);
1778  }
1779  }
1780 
1781  /*
1782  * Failsafe protection against vacuuming work of active transaction.
1783  *
1784  * This is not an assertion because we avoid the spinlock for
1785  * performance, leaving open the possibility that xlimit could advance
1786  * and be more current; but it seems prudent to apply this limit. It
1787  * might make pruning a tiny bit less aggressive than it could be, but
1788  * protects against data loss bugs.
1789  */
1790  if (TransactionIdIsNormal(latest_xmin)
1791  && TransactionIdPrecedes(latest_xmin, xlimit))
1792  xlimit = latest_xmin;
1793 
1794  if (NormalTransactionIdFollows(xlimit, recentXmin))
1795  return xlimit;
1796  }
1797 
1798  return recentXmin;
1799 }
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:1643
slock_t mutex_latest_xmin
Definition: snapmgr.c:87
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:1680
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:1629
int old_snapshot_threshold
Definition: snapmgr.c:74
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 913 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().

914 {
915  if (snapshot == NULL)
916  return;
917 
918  Assert(snapshot->regd_count > 0);
920 
921  ResourceOwnerForgetSnapshot(owner, snapshot);
922 
923  snapshot->regd_count--;
924  if (snapshot->regd_count == 0)
926 
927  if (snapshot->regd_count == 0 && snapshot->active_count == 0)
928  {
929  FreeSnapshot(snapshot);
931  }
932 }
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:710
static void SnapshotResetXmin(void)
Definition: snapmgr.c:973
#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 776 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().

777 {
778  CommandId save_curcid,
779  curcid;
780 
784 
785  /*
786  * Don't allow modification of the active snapshot during parallel
787  * operation. We share the snapshot to worker backends at the beginning
788  * of parallel operation, so any change to the snapshot can lead to
789  * inconsistencies. We have other defenses against
790  * CommandCounterIncrement, but there are a few places that call this
791  * directly, so we put an additional guard here.
792  */
793  save_curcid = ActiveSnapshot->as_snap->curcid;
794  curcid = GetCurrentCommandId(false);
795  if (IsInParallelMode() && save_curcid != curcid)
796  elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
797  ActiveSnapshot->as_snap->curcid = curcid;
798 }
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 1566 of file snapmgr.c.

References NIL.

Referenced by PrepareTransaction().

1567 {
1568  return (exportedSnapshots != NIL);
1569 }
#define NIL
Definition: pg_list.h:69
static List * exportedSnapshots
Definition: snapmgr.c:219

Variable Documentation

TransactionId RecentGlobalDataXmin

Definition at line 167 of file snapmgr.c.

Referenced by GetSnapshotData(), and heap_page_prune_opt().