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)
 
int64 GetSnapshotCurrentTimestamp (void)
 
int64 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 (int64 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
 
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:556
bool RelationHasUnloggedIndex(Relation rel)
Definition: relcache.c:5892
#define RelationNeedsWAL(relation)
Definition: rel.h:502

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:226
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:393
#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:388
struct SnapshotData * Snapshot
Definition: snapshot.h:22
uint32 regd_count
Definition: snapshot.h:107
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:108
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#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:107
void pfree(void *pointer)
Definition: mcxt.c:992
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:226
#define Assert(condition)
Definition: c.h:670
uint32 active_count
Definition: snapshot.h:106
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:226
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:2207
int unlink(const char *filename)
#define NULL
Definition: c.h:226
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2273
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2316
Size EstimateSnapshotSpace ( Snapshot  snapshot)

Definition at line 1989 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 heap_parallelscan_estimate(), index_parallelscan_estimate(), index_parallelscan_initialize(), and InitializeParallelDSM().

1990 {
1991  Size size;
1992 
1993  Assert(snap != InvalidSnapshot);
1994  Assert(snap->satisfies == HeapTupleSatisfiesMVCC);
1995 
1996  /* We allocate any XID arrays needed in the same palloc block. */
1997  size = add_size(sizeof(SerializedSnapshotData),
1998  mul_size(snap->xcnt, sizeof(TransactionId)));
1999  if (snap->subxcnt > 0 &&
2000  (!snap->suboverflowed || snap->takenDuringRecovery))
2001  size = add_size(size,
2002  mul_size(snap->subxcnt, sizeof(TransactionId)));
2003 
2004  return size;
2005 }
uint32 TransactionId
Definition: c.h:393
#define InvalidSnapshot
Definition: snapshot.h:24
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:670
size_t Size
Definition: c.h:352
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:5082
MemoryContext TopTransactionContext
Definition: mcxt.c:48
uint32 TransactionId
Definition: c.h:393
char * pstrdup(const char *in)
Definition: mcxt.c:1165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_BINARY_W
Definition: c.h:1040
bool suboverflowed
Definition: snapshot.h:90
TransactionId GetTopTransactionId(void)
Definition: xact.c:388
uint32 regd_count
Definition: snapshot.h:107
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:1966
TransactionId xmax
Definition: snapshot.h:66
TransactionId xmin
Definition: snapshot.h:65
#define ereport(elevel, rest)
Definition: elog.h:122
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:76
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:108
bool takenDuringRecovery
Definition: snapshot.h:92
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:2149
bool IsSubTransaction(void)
Definition: xact.c:4374
uint32 xcnt
Definition: snapshot.h:77
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1462
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:88
int32 subxcnt
Definition: snapshot.h:89
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:1969
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:912
#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:670
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1503
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1969
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:1343
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:108
#define NULL
Definition: c.h:226
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1320
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1503
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:111
#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:226
uint64 XLogRecPtr
Definition: xlogdefs.h:21
int64 GetOldSnapshotThresholdTimestamp ( void  )

Definition at line 1656 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1657 {
1658  int64 threshold_timestamp;
1659 
1661  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1663 
1664  return threshold_timestamp;
1665 }
slock_t mutex_threshold
Definition: snapmgr.c:91
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64
int64 threshold_timestamp
Definition: snapmgr.c:92
int64 GetSnapshotCurrentTimestamp ( void  )

Definition at line 1631 of file snapmgr.c.

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

Referenced by GetSnapshotData(), and TransactionIdLimitedForOldSnapshots().

1632 {
1633  int64 now = GetCurrentIntegerTimestamp();
1634 
1635  /*
1636  * Don't let time move backward; if it hasn't advanced, use the old value.
1637  */
1639  if (now <= oldSnapshotControl->current_timestamp)
1641  else
1644 
1645  return now;
1646 }
int64 GetCurrentIntegerTimestamp(void)
Definition: timestamp.c:1716
#define SpinLockAcquire(lock)
Definition: spin.h:62
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:1652
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:107
static Snapshot CurrentSnapshot
Definition: snapmgr.c:149
bool IsInParallelMode(void)
Definition: xact.c:912
#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:108
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1563
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1503
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1969
#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 1969 of file snapmgr.c.

References NULL.

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

1970 {
1971  return HistoricSnapshot != NULL;
1972 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
#define NULL
Definition: c.h:226
struct HTAB* HistoricSnapshotGetTupleCids ( void  )

Definition at line 1975 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

1976 {
1978  return tuplecid_data;
1979 }
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define Assert(condition)
Definition: c.h:670
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1969
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:393
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:90
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:533
#define PG_BINARY_R
Definition: c.h:1039
#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:1966
#define InvalidTransactionId
Definition: transam.h:31
TransactionId xmax
Definition: snapshot.h:66
TransactionId xmin
Definition: snapshot.h:65
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:403
#define ereport(elevel, rest)
Definition: elog.h:122
TransactionId * xip
Definition: snapshot.h:76
Oid MyDatabaseId
Definition: globals.c:76
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1451
bool XactReadOnly
Definition: xact.c:77
#define NULL
Definition: c.h:226
bool takenDuringRecovery
Definition: snapshot.h:92
int FreeFile(FILE *file)
Definition: fd.c:2149
bool IsSubTransaction(void)
Definition: xact.c:4374
static void SetTransactionSnapshot(Snapshot sourcesnap, TransactionId sourcexid, PGPROC *sourceproc)
Definition: snapmgr.c:561
uint32 xcnt
Definition: snapshot.h:77
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
int i
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1462
#define elog
Definition: elog.h:219
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
TransactionId * subxip
Definition: snapshot.h:88
int32 subxcnt
Definition: snapshot.h:89
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:108
#define NULL
Definition: c.h:226
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:226
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99
void MaintainOldSnapshotTimeMapping ( int64  whenTaken,
TransactionId  xmin 
)

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

1794 {
1795  int64 ts;
1796  TransactionId latest_xmin;
1797  int64 update_ts;
1798  bool map_update_required = false;
1799 
1800  /* Never call this function when old snapshot checking is disabled. */
1802 
1803  ts = AlignTimestampToMinuteBoundary(whenTaken);
1804 
1805  /*
1806  * Keep track of the latest xmin seen by any process. Update mapping with
1807  * a new value when we have crossed a bucket boundary.
1808  */
1810  latest_xmin = oldSnapshotControl->latest_xmin;
1811  update_ts = oldSnapshotControl->next_map_update;
1812  if (ts > update_ts)
1813  {
1815  map_update_required = true;
1816  }
1817  if (TransactionIdFollows(xmin, latest_xmin))
1820 
1821  /* We only needed to update the most recent xmin value. */
1822  if (!map_update_required)
1823  return;
1824 
1825  /* No further tracking needed for 0 (used for testing). */
1826  if (old_snapshot_threshold == 0)
1827  return;
1828 
1829  /*
1830  * We don't want to do something stupid with unusual values, but we don't
1831  * want to litter the log with warnings or break otherwise normal
1832  * processing for this feature; so if something seems unreasonable, just
1833  * log at DEBUG level and return without doing anything.
1834  */
1835  if (whenTaken < 0)
1836  {
1837  elog(DEBUG1,
1838  "MaintainOldSnapshotTimeMapping called with negative whenTaken = %ld",
1839  (long) whenTaken);
1840  return;
1841  }
1842  if (!TransactionIdIsNormal(xmin))
1843  {
1844  elog(DEBUG1,
1845  "MaintainOldSnapshotTimeMapping called with xmin = %lu",
1846  (unsigned long) xmin);
1847  return;
1848  }
1849 
1850  LWLockAcquire(OldSnapshotTimeMapLock, LW_EXCLUSIVE);
1851 
1857 
1858  if (oldSnapshotControl->count_used == 0)
1859  {
1860  /* set up first entry for empty mapping */
1864  oldSnapshotControl->xid_by_minute[0] = xmin;
1865  }
1866  else if (ts < oldSnapshotControl->head_timestamp)
1867  {
1868  /* old ts; log it at DEBUG */
1869  LWLockRelease(OldSnapshotTimeMapLock);
1870  elog(DEBUG1,
1871  "MaintainOldSnapshotTimeMapping called with old whenTaken = %ld",
1872  (long) whenTaken);
1873  return;
1874  }
1875  else if (ts <= (oldSnapshotControl->head_timestamp +
1877  * USECS_PER_MINUTE)))
1878  {
1879  /* existing mapping; advance xid if possible */
1880  int bucket = (oldSnapshotControl->head_offset
1882  / USECS_PER_MINUTE))
1884 
1886  oldSnapshotControl->xid_by_minute[bucket] = xmin;
1887  }
1888  else
1889  {
1890  /* We need a new bucket, but it might not be the very next one. */
1891  int advance = ((ts - oldSnapshotControl->head_timestamp)
1892  / USECS_PER_MINUTE);
1893 
1895 
1896  if (advance >= OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1897  {
1898  /* Advance is so far that all old data is junk; start over. */
1901  oldSnapshotControl->xid_by_minute[0] = xmin;
1902  }
1903  else
1904  {
1905  /* Store the new value in one or more buckets. */
1906  int i;
1907 
1908  for (i = 0; i < advance; i++)
1909  {
1911  {
1912  /* Map full and new value replaces old head. */
1913  int old_head = oldSnapshotControl->head_offset;
1914 
1915  if (old_head == (OLD_SNAPSHOT_TIME_MAP_ENTRIES - 1))
1917  else
1918  oldSnapshotControl->head_offset = old_head + 1;
1919  oldSnapshotControl->xid_by_minute[old_head] = xmin;
1920  }
1921  else
1922  {
1923  /* Extend map to unused entry. */
1924  int new_tail = (oldSnapshotControl->head_offset
1927 
1929  oldSnapshotControl->xid_by_minute[new_tail] = xmin;
1930  }
1931  }
1932  }
1933  }
1934 
1935  LWLockRelease(OldSnapshotTimeMapLock);
1936 }
#define DEBUG1
Definition: elog.h:25
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:393
#define USECS_PER_MINUTE
Definition: timestamp.h:105
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define SpinLockAcquire(lock)
Definition: spin.h:62
slock_t mutex_latest_xmin
Definition: snapmgr.c:87
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
static int64 AlignTimestampToMinuteBoundary(int64 ts)
Definition: snapmgr.c:1620
TransactionId latest_xmin
Definition: snapmgr.c:89
#define Assert(condition)
Definition: c.h:670
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: snapmgr.c:126
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
int old_snapshot_threshold
Definition: snapmgr.c:74
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:107
void pfree(void *pointer)
Definition: mcxt.c:992
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:226
#define Assert(condition)
Definition: c.h:670
uint32 active_count
Definition: snapshot.h:106
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:93
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:24
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:655
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:760
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
static Snapshot SecondarySnapshot
Definition: snapmgr.c:150
uint32 active_count
Definition: snapshot.h:106
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:93
void ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
Definition: resowner.c:1143
uint32 regd_count
Definition: snapshot.h:107
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
#define InvalidSnapshot
Definition: snapshot.h:24
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:655
pairingheap_node ph_node
Definition: snapshot.h:108
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 2069 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 heap_beginscan_parallel(), index_beginscan_parallel(), and ParallelWorkerMain().

2070 {
2071  SerializedSnapshotData *serialized_snapshot;
2072  Size size;
2073  Snapshot snapshot;
2074  TransactionId *serialized_xids;
2075 
2076  serialized_snapshot = (SerializedSnapshotData *) start_address;
2077  serialized_xids = (TransactionId *)
2078  (start_address + sizeof(SerializedSnapshotData));
2079 
2080  /* We allocate any XID arrays needed in the same palloc block. */
2081  size = sizeof(SnapshotData)
2082  + serialized_snapshot->xcnt * sizeof(TransactionId)
2083  + serialized_snapshot->subxcnt * sizeof(TransactionId);
2084 
2085  /* Copy all required fields */
2087  snapshot->satisfies = HeapTupleSatisfiesMVCC;
2088  snapshot->xmin = serialized_snapshot->xmin;
2089  snapshot->xmax = serialized_snapshot->xmax;
2090  snapshot->xip = NULL;
2091  snapshot->xcnt = serialized_snapshot->xcnt;
2092  snapshot->subxip = NULL;
2093  snapshot->subxcnt = serialized_snapshot->subxcnt;
2094  snapshot->suboverflowed = serialized_snapshot->suboverflowed;
2095  snapshot->takenDuringRecovery = serialized_snapshot->takenDuringRecovery;
2096  snapshot->curcid = serialized_snapshot->curcid;
2097  snapshot->whenTaken = serialized_snapshot->whenTaken;
2098  snapshot->lsn = serialized_snapshot->lsn;
2099 
2100  /* Copy XIDs, if present. */
2101  if (serialized_snapshot->xcnt > 0)
2102  {
2103  snapshot->xip = (TransactionId *) (snapshot + 1);
2104  memcpy(snapshot->xip, serialized_xids,
2105  serialized_snapshot->xcnt * sizeof(TransactionId));
2106  }
2107 
2108  /* Copy SubXIDs, if present. */
2109  if (serialized_snapshot->subxcnt > 0)
2110  {
2111  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2112  serialized_snapshot->xcnt;
2113  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot->xcnt,
2114  serialized_snapshot->subxcnt * sizeof(TransactionId));
2115  }
2116 
2117  /* Set the copied flag so that the caller will set refcounts correctly. */
2118  snapshot->regd_count = 0;
2119  snapshot->active_count = 0;
2120  snapshot->copied = true;
2121 
2122  return snapshot;
2123 }
SnapshotSatisfiesFunc satisfies
Definition: snapshot.h:53
MemoryContext TopTransactionContext
Definition: mcxt.c:48
uint32 TransactionId
Definition: c.h:393
bool copied
Definition: snapshot.h:93
XLogRecPtr lsn
Definition: snapshot.h:111
bool suboverflowed
Definition: snapshot.h:90
struct SnapshotData * Snapshot
Definition: snapshot.h:22
uint32 regd_count
Definition: snapshot.h:107
struct SnapshotData SnapshotData
TransactionId xmax
Definition: snapshot.h:66
TransactionId xmin
Definition: snapshot.h:65
TransactionId * xip
Definition: snapshot.h:76
TransactionId xmax
Definition: snapmgr.c:236
CommandId curcid
Definition: snapshot.h:95
int64 whenTaken
Definition: snapshot.h:110
#define NULL
Definition: c.h:226
bool takenDuringRecovery
Definition: snapshot.h:92
size_t Size
Definition: c.h:352
uint32 xcnt
Definition: snapshot.h:77
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
TransactionId xmin
Definition: snapmgr.c:235
bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:963
TransactionId * subxip
Definition: snapshot.h:88
uint32 active_count
Definition: snapshot.h:106
int32 subxcnt
Definition: snapshot.h:89
void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  master_pgproc 
)

Definition at line 2132 of file snapmgr.c.

References InvalidTransactionId, and SetTransactionSnapshot().

Referenced by ParallelWorkerMain().

2133 {
2134  SetTransactionSnapshot(snapshot, InvalidTransactionId, master_pgproc);
2135 }
#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 2013 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 heap_parallelscan_initialize(), index_parallelscan_initialize(), and InitializeParallelDSM().

2014 {
2015  SerializedSnapshotData *serialized_snapshot;
2016 
2017  Assert(snapshot->subxcnt >= 0);
2018 
2019  serialized_snapshot = (SerializedSnapshotData *) start_address;
2020 
2021  /* Copy all required fields */
2022  serialized_snapshot->xmin = snapshot->xmin;
2023  serialized_snapshot->xmax = snapshot->xmax;
2024  serialized_snapshot->xcnt = snapshot->xcnt;
2025  serialized_snapshot->subxcnt = snapshot->subxcnt;
2026  serialized_snapshot->suboverflowed = snapshot->suboverflowed;
2027  serialized_snapshot->takenDuringRecovery = snapshot->takenDuringRecovery;
2028  serialized_snapshot->curcid = snapshot->curcid;
2029  serialized_snapshot->whenTaken = snapshot->whenTaken;
2030  serialized_snapshot->lsn = snapshot->lsn;
2031 
2032  /*
2033  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2034  * taken during recovey - in that case, top-level XIDs are in subxip as
2035  * well, and we mustn't lose them.
2036  */
2037  if (serialized_snapshot->suboverflowed && !snapshot->takenDuringRecovery)
2038  serialized_snapshot->subxcnt = 0;
2039 
2040  /* Copy XID array */
2041  if (snapshot->xcnt > 0)
2042  memcpy((TransactionId *) (serialized_snapshot + 1),
2043  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2044 
2045  /*
2046  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2047  * though, because it's not used anywhere in that case. Except if it's a
2048  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2049  * well in that case, so we mustn't lose them.
2050  */
2051  if (serialized_snapshot->subxcnt > 0)
2052  {
2053  Size subxipoff = sizeof(SerializedSnapshotData) +
2054  snapshot->xcnt * sizeof(TransactionId);
2055 
2056  memcpy((TransactionId *) ((char *) serialized_snapshot + subxipoff),
2057  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2058  }
2059 }
uint32 TransactionId
Definition: c.h:393
XLogRecPtr lsn
Definition: snapshot.h:111
bool suboverflowed
Definition: snapshot.h:90
struct SerializedSnapshotData SerializedSnapshotData
TransactionId xmax
Definition: snapshot.h:66
TransactionId xmin
Definition: snapshot.h:65
TransactionId * xip
Definition: snapshot.h:76
TransactionId xmax
Definition: snapmgr.c:236
CommandId curcid
Definition: snapshot.h:95
int64 whenTaken
Definition: snapshot.h:110
#define Assert(condition)
Definition: c.h:670
bool takenDuringRecovery
Definition: snapshot.h:92
size_t Size
Definition: c.h:352
uint32 xcnt
Definition: snapshot.h:77
TransactionId xmin
Definition: snapmgr.c:235
TransactionId * subxip
Definition: snapshot.h:88
int32 subxcnt
Definition: snapshot.h:89
void SetupHistoricSnapshot ( Snapshot  snapshot_now,
struct HTAB tuplecids 
)

Definition at line 1946 of file snapmgr.c.

References Assert, and NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1947 {
1948  Assert(historic_snapshot != NULL);
1949 
1950  /* setup the timetravel snapshot */
1951  HistoricSnapshot = historic_snapshot;
1952 
1953  /* setup (cmin, cmax) lookup hash */
1954  tuplecid_data = tuplecids;
1955 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
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
slock_t mutex_latest_xmin
Definition: snapmgr.c:87
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
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
int64 threshold_timestamp
Definition: snapmgr.c:92
slock_t mutex_current
Definition: snapmgr.c:85
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:393
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:352
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:550
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:95
static Snapshot SecondarySnapshot
Definition: snapmgr.c:150
void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 1962 of file snapmgr.c.

References NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1963 {
1965  tuplecid_data = NULL;
1966 }
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define NULL
Definition: c.h:226
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 1686 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().

1688 {
1689  if (TransactionIdIsNormal(recentXmin)
1690  && old_snapshot_threshold >= 0
1691  && RelationAllowsEarlyPruning(relation))
1692  {
1693  int64 ts = GetSnapshotCurrentTimestamp();
1694  TransactionId xlimit = recentXmin;
1695  TransactionId latest_xmin;
1696  int64 update_ts;
1697  bool same_ts_as_threshold = false;
1698 
1700  latest_xmin = oldSnapshotControl->latest_xmin;
1701  update_ts = oldSnapshotControl->next_map_update;
1703 
1704  /*
1705  * Zero threshold always overrides to latest xmin, if valid. Without
1706  * some heuristic it will find its own snapshot too old on, for
1707  * example, a simple UPDATE -- which would make it useless for most
1708  * testing, but there is no principled way to ensure that it doesn't
1709  * fail in this way. Use a five-second delay to try to get useful
1710  * testing behavior, but this may need adjustment.
1711  */
1712  if (old_snapshot_threshold == 0)
1713  {
1714  if (TransactionIdPrecedes(latest_xmin, MyPgXact->xmin)
1715  && TransactionIdFollows(latest_xmin, xlimit))
1716  xlimit = latest_xmin;
1717 
1718  ts -= 5 * USECS_PER_SEC;
1720 
1721  return xlimit;
1722  }
1723 
1726 
1727  /* Check for fast exit without LW locking. */
1730  {
1732  same_ts_as_threshold = true;
1733  }
1735 
1736  if (!same_ts_as_threshold)
1737  {
1738  if (ts == update_ts)
1739  {
1740  xlimit = latest_xmin;
1741  if (NormalTransactionIdFollows(xlimit, recentXmin))
1743  }
1744  else
1745  {
1746  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1747 
1750  {
1751  int offset;
1752 
1753  offset = ((ts - oldSnapshotControl->head_timestamp)
1754  / USECS_PER_MINUTE);
1755  if (offset > oldSnapshotControl->count_used - 1)
1756  offset = oldSnapshotControl->count_used - 1;
1757  offset = (oldSnapshotControl->head_offset + offset)
1759  xlimit = oldSnapshotControl->xid_by_minute[offset];
1760 
1761  if (NormalTransactionIdFollows(xlimit, recentXmin))
1763  }
1764 
1765  LWLockRelease(OldSnapshotTimeMapLock);
1766  }
1767  }
1768 
1769  /*
1770  * Failsafe protection against vacuuming work of active transaction.
1771  *
1772  * This is not an assertion because we avoid the spinlock for
1773  * performance, leaving open the possibility that xlimit could advance
1774  * and be more current; but it seems prudent to apply this limit. It
1775  * might make pruning a tiny bit less aggressive than it could be, but
1776  * protects against data loss bugs.
1777  */
1778  if (TransactionIdIsNormal(latest_xmin)
1779  && TransactionIdPrecedes(latest_xmin, xlimit))
1780  xlimit = latest_xmin;
1781 
1782  if (NormalTransactionIdFollows(xlimit, recentXmin))
1783  return xlimit;
1784  }
1785 
1786  return recentXmin;
1787 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:393
#define USECS_PER_SEC
Definition: timestamp.h:106
TransactionId xmin
Definition: proc.h:203
slock_t mutex_threshold
Definition: snapmgr.c:91
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38
#define USECS_PER_MINUTE
Definition: timestamp.h:105
static void SetOldSnapshotThresholdTimestamp(int64 ts, TransactionId xlimit)
Definition: snapmgr.c:1668
PGXACT * MyPgXact
Definition: proc.c:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define SpinLockAcquire(lock)
Definition: spin.h:62
int64 GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1631
slock_t mutex_latest_xmin
Definition: snapmgr.c:87
TransactionId threshold_xid
Definition: snapmgr.c:93
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
static int64 AlignTimestampToMinuteBoundary(int64 ts)
Definition: snapmgr.c:1620
TransactionId latest_xmin
Definition: snapmgr.c:89
int64 threshold_timestamp
Definition: snapmgr.c:92
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:1110
int old_snapshot_threshold
Definition: snapmgr.c:74
#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:107
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1163
pairingheap_node ph_node
Definition: snapshot.h:108
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170
uint32 active_count
Definition: snapshot.h:106
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:407
Snapshot as_snap
Definition: snapmgr.c:182
uint32 regd_count
Definition: snapshot.h:107
bool IsInParallelMode(void)
Definition: xact.c:912
#define ERROR
Definition: elog.h:43
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
CommandId curcid
Definition: snapshot.h:95
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:686
#define elog
Definition: elog.h:219
uint32 active_count
Definition: snapshot.h:106
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().