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)
 
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:5968
#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)

Definition at line 1054 of file snapmgr.c.

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

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 
1140 }
#define NIL
Definition: pg_list.h:69
uint32 TransactionId
Definition: c.h:397
#define pairingheap_reset(h)
Definition: pairingheap.h:93
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
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:65
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 1570 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().

1571 {
1572  char buf[MAXPGPATH];
1573  DIR *s_dir;
1574  struct dirent *s_de;
1575 
1576  if (!(s_dir = AllocateDir(SNAPSHOT_EXPORT_DIR)))
1577  {
1578  /*
1579  * We really should have that directory in a sane cluster setup. But
1580  * then again if we don't, it's not fatal enough to make it FATAL.
1581  * Since we're running in the postmaster, LOG is our best bet.
1582  */
1583  elog(LOG, "could not open directory \"%s\": %m", SNAPSHOT_EXPORT_DIR);
1584  return;
1585  }
1586 
1587  while ((s_de = ReadDir(s_dir, SNAPSHOT_EXPORT_DIR)) != NULL)
1588  {
1589  if (strcmp(s_de->d_name, ".") == 0 ||
1590  strcmp(s_de->d_name, "..") == 0)
1591  continue;
1592 
1593  snprintf(buf, MAXPGPATH, SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1594  /* Again, unlink failure is not worthy of FATAL */
1595  if (unlink(buf))
1596  elog(LOG, "could not unlink file \"%s\": %m", buf);
1597  }
1598 
1599  FreeDir(s_dir);
1600 }
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:65
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2298
int unlink(const char *filename)
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2364
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2407
Size EstimateSnapshotSpace ( Snapshot  snapshot)

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

1993 {
1994  Size size;
1995 
1996  Assert(snap != InvalidSnapshot);
1997  Assert(snap->satisfies == HeapTupleSatisfiesMVCC);
1998 
1999  /* We allocate any XID arrays needed in the same palloc block. */
2000  size = add_size(sizeof(SerializedSnapshotData),
2001  mul_size(snap->xcnt, sizeof(TransactionId)));
2002  if (snap->subxcnt > 0 &&
2003  (!snap->suboverflowed || snap->takenDuringRecovery))
2004  size = add_size(size,
2005  mul_size(snap->subxcnt, sizeof(TransactionId)));
2006 
2007  return size;
2008 }
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 1150 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().

1151 {
1152  TransactionId topXid;
1153  TransactionId *children;
1154  int nchildren;
1155  int addTopXid;
1157  FILE *f;
1158  int i;
1159  MemoryContext oldcxt;
1160  char path[MAXPGPATH];
1161  char pathtmp[MAXPGPATH];
1162 
1163  /*
1164  * It's tempting to call RequireTransactionChain here, since it's not very
1165  * useful to export a snapshot that will disappear immediately afterwards.
1166  * However, we haven't got enough information to do that, since we don't
1167  * know if we're at top level or not. For example, we could be inside a
1168  * plpgsql function that is going to fire off other transactions via
1169  * dblink. Rather than disallow perfectly legitimate usages, don't make a
1170  * check.
1171  *
1172  * Also note that we don't make any restriction on the transaction's
1173  * isolation level; however, importers must check the level if they are
1174  * serializable.
1175  */
1176 
1177  /*
1178  * This will assign a transaction ID if we do not yet have one.
1179  */
1180  topXid = GetTopTransactionId();
1181 
1182  /*
1183  * We cannot export a snapshot from a subtransaction because there's no
1184  * easy way for importers to verify that the same subtransaction is still
1185  * running.
1186  */
1187  if (IsSubTransaction())
1188  ereport(ERROR,
1189  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1190  errmsg("cannot export a snapshot from a subtransaction")));
1191 
1192  /*
1193  * We do however allow previous committed subtransactions to exist.
1194  * Importers of the snapshot must see them as still running, so get their
1195  * XIDs to add them to the snapshot.
1196  */
1197  nchildren = xactGetCommittedChildren(&children);
1198 
1199  /*
1200  * Copy the snapshot into TopTransactionContext, add it to the
1201  * exportedSnapshots list, and mark it pseudo-registered. We do this to
1202  * ensure that the snapshot's xmin is honored for the rest of the
1203  * transaction.
1204  */
1205  snapshot = CopySnapshot(snapshot);
1206 
1209  MemoryContextSwitchTo(oldcxt);
1210 
1211  snapshot->regd_count++;
1213 
1214  /*
1215  * Fill buf with a text serialization of the snapshot, plus identification
1216  * data about this transaction. The format expected by ImportSnapshot is
1217  * pretty rigid: each line must be fieldname:value.
1218  */
1219  initStringInfo(&buf);
1220 
1221  appendStringInfo(&buf, "xid:%u\n", topXid);
1222  appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1223  appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1224  appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1225 
1226  appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1227  appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1228 
1229  /*
1230  * We must include our own top transaction ID in the top-xid data, since
1231  * by definition we will still be running when the importing transaction
1232  * adopts the snapshot, but GetSnapshotData never includes our own XID in
1233  * the snapshot. (There must, therefore, be enough room to add it.)
1234  *
1235  * However, it could be that our topXid is after the xmax, in which case
1236  * we shouldn't include it because xip[] members are expected to be before
1237  * xmax. (We need not make the same check for subxip[] members, see
1238  * snapshot.h.)
1239  */
1240  addTopXid = TransactionIdPrecedes(topXid, snapshot->xmax) ? 1 : 0;
1241  appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1242  for (i = 0; i < snapshot->xcnt; i++)
1243  appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1244  if (addTopXid)
1245  appendStringInfo(&buf, "xip:%u\n", topXid);
1246 
1247  /*
1248  * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1249  * we have to cope with possible overflow.
1250  */
1251  if (snapshot->suboverflowed ||
1252  snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1253  appendStringInfoString(&buf, "sof:1\n");
1254  else
1255  {
1256  appendStringInfoString(&buf, "sof:0\n");
1257  appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1258  for (i = 0; i < snapshot->subxcnt; i++)
1259  appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1260  for (i = 0; i < nchildren; i++)
1261  appendStringInfo(&buf, "sxp:%u\n", children[i]);
1262  }
1263  appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1264 
1265  /*
1266  * Now write the text representation into a file. We first write to a
1267  * ".tmp" filename, and rename to final filename if no error. This
1268  * ensures that no other backend can read an incomplete file
1269  * (ImportSnapshot won't allow it because of its valid-characters check).
1270  */
1271  XactExportFilePath(pathtmp, topXid, list_length(exportedSnapshots), ".tmp");
1272  if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1273  ereport(ERROR,
1275  errmsg("could not create file \"%s\": %m", pathtmp)));
1276 
1277  if (fwrite(buf.data, buf.len, 1, f) != 1)
1278  ereport(ERROR,
1280  errmsg("could not write to file \"%s\": %m", pathtmp)));
1281 
1282  /* no fsync() since file need not survive a system crash */
1283 
1284  if (FreeFile(f))
1285  ereport(ERROR,
1287  errmsg("could not write to file \"%s\": %m", pathtmp)));
1288 
1289  /*
1290  * Now that we have written everything into a .tmp file, rename the file
1291  * to remove the .tmp suffix.
1292  */
1293  XactExportFilePath(path, topXid, list_length(exportedSnapshots), "");
1294 
1295  if (rename(pathtmp, path) < 0)
1296  ereport(ERROR,
1298  errmsg("could not rename file \"%s\" to \"%s\": %m",
1299  pathtmp, path)));
1300 
1301  /*
1302  * The basename of the file is what we return from pg_export_snapshot().
1303  * It's already in path in a textual format and we know that the path
1304  * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1305  * and pstrdup it so as not to return the address of a local variable.
1306  */
1307  return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1308 }
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:65
int errcode_for_file_access(void)
Definition: elog.c:598
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2057
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:2240
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:1463
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:1972
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:1504
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1972
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:1504
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 1659 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1660 {
1661  TimestampTz threshold_timestamp;
1662 
1664  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1666 
1667  return threshold_timestamp;
1668 }
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 1634 of file snapmgr.c.

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

Referenced by GetSnapshotData(), and TransactionIdLimitedForOldSnapshots().

1635 {
1637 
1638  /*
1639  * Don't let time move backward; if it hasn't advanced, use the old value.
1640  */
1642  if (now <= oldSnapshotControl->current_timestamp)
1644  else
1647 
1648  return now;
1649 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1569
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:1533
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:1563
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1504
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1972
#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 1972 of file snapmgr.c.

References NULL.

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

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

Definition at line 1978 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

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

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

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

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

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

References InvalidTransactionId, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2140 {
2141  SetTransactionSnapshot(snapshot, InvalidTransactionId, master_pgproc);
2142 }
#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 2016 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().

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

References Assert, and NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1950 {
1951  Assert(historic_snapshot != NULL);
1952 
1953  /* setup the timetravel snapshot */
1954  HistoricSnapshot = historic_snapshot;
1955 
1956  /* setup (cmin, cmax) lookup hash */
1957  tuplecid_data = tuplecids;
1958 }
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 1965 of file snapmgr.c.

References NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1966 {
1968  tuplecid_data = NULL;
1969 }
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 1603 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom().

1604 {
1607  return true;
1608 
1609  return false;
1610 }
#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 1689 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().

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

References NIL.

Referenced by PrepareTransaction().

1558 {
1559  return (exportedSnapshots != NIL);
1560 }
#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().