PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
snapmgr.c File Reference
#include "postgres.h"
#include <sys/stat.h>
#include <unistd.h>
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "lib/pairingheap.h"
#include "miscadmin.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/sinval.h"
#include "storage/spin.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/resowner_private.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for snapmgr.c:

Go to the source code of this file.

Data Structures

struct  OldSnapshotControlData
 
struct  ActiveSnapshotElt
 
struct  SerializedSnapshotData
 

Macros

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"
 
#define XactExportFilePath(path, xid, num, suffix)
 

Typedefs

typedef struct
OldSnapshotControlData 
OldSnapshotControlData
 
typedef struct ActiveSnapshotElt ActiveSnapshotElt
 
typedef struct
SerializedSnapshotData 
SerializedSnapshotData
 

Functions

static int xmin_cmp (const pairingheap_node *a, const pairingheap_node *b, void *arg)
 
static TimestampTz AlignTimestampToMinuteBoundary (TimestampTz ts)
 
static Snapshot CopySnapshot (Snapshot snapshot)
 
static void FreeSnapshot (Snapshot snapshot)
 
static void SnapshotResetXmin (void)
 
Size SnapMgrShmemSize (void)
 
void SnapMgrInit (void)
 
Snapshot GetTransactionSnapshot (void)
 
Snapshot GetLatestSnapshot (void)
 
Snapshot GetOldestSnapshot (void)
 
Snapshot GetCatalogSnapshot (Oid relid)
 
Snapshot GetNonHistoricCatalogSnapshot (Oid relid)
 
void InvalidateCatalogSnapshot (void)
 
void InvalidateCatalogSnapshotConditionally (void)
 
void SnapshotSetCommandId (CommandId curcid)
 
static void SetTransactionSnapshot (Snapshot sourcesnap, TransactionId sourcexid, PGPROC *sourceproc)
 
void PushActiveSnapshot (Snapshot snap)
 
void PushCopiedSnapshot (Snapshot snapshot)
 
void UpdateActiveSnapshotCommandId (void)
 
void PopActiveSnapshot (void)
 
Snapshot GetActiveSnapshot (void)
 
bool ActiveSnapshotSet (void)
 
Snapshot RegisterSnapshot (Snapshot snapshot)
 
Snapshot RegisterSnapshotOnOwner (Snapshot snapshot, ResourceOwner owner)
 
void UnregisterSnapshot (Snapshot snapshot)
 
void UnregisterSnapshotFromOwner (Snapshot snapshot, ResourceOwner owner)
 
void AtSubCommit_Snapshot (int level)
 
void AtSubAbort_Snapshot (int level)
 
void AtEOXact_Snapshot (bool isCommit)
 
char * ExportSnapshot (Snapshot snapshot)
 
Datum pg_export_snapshot (PG_FUNCTION_ARGS)
 
static int parseIntFromText (const char *prefix, char **s, const char *filename)
 
static TransactionId parseXidFromText (const char *prefix, char **s, const char *filename)
 
void ImportSnapshot (const char *idstr)
 
bool XactHasExportedSnapshots (void)
 
void DeleteAllExportedSnapshotFiles (void)
 
bool ThereAreNoPriorRegisteredSnapshots (void)
 
TimestampTz GetSnapshotCurrentTimestamp (void)
 
TimestampTz GetOldSnapshotThresholdTimestamp (void)
 
static void SetOldSnapshotThresholdTimestamp (TimestampTz ts, TransactionId xlimit)
 
TransactionId TransactionIdLimitedForOldSnapshots (TransactionId recentXmin, Relation relation)
 
void MaintainOldSnapshotTimeMapping (TimestampTz whenTaken, TransactionId xmin)
 
void SetupHistoricSnapshot (Snapshot historic_snapshot, HTAB *tuplecids)
 
void TeardownHistoricSnapshot (bool is_error)
 
bool HistoricSnapshotActive (void)
 
HTABHistoricSnapshotGetTupleCids (void)
 
Size EstimateSnapshotSpace (Snapshot snap)
 
void SerializeSnapshot (Snapshot snapshot, char *start_address)
 
Snapshot RestoreSnapshot (char *start_address)
 
void RestoreTransactionSnapshot (Snapshot snapshot, void *master_pgproc)
 

Variables

int old_snapshot_threshold
 
static volatile
OldSnapshotControlData
oldSnapshotControl
 
static SnapshotData CurrentSnapshotData = {HeapTupleSatisfiesMVCC}
 
static SnapshotData SecondarySnapshotData = {HeapTupleSatisfiesMVCC}
 
SnapshotData CatalogSnapshotData = {HeapTupleSatisfiesMVCC}
 
static Snapshot CurrentSnapshot = NULL
 
static Snapshot SecondarySnapshot = NULL
 
static Snapshot CatalogSnapshot = NULL
 
static Snapshot HistoricSnapshot = NULL
 
TransactionId TransactionXmin = FirstNormalTransactionId
 
TransactionId RecentXmin = FirstNormalTransactionId
 
TransactionId RecentGlobalXmin = InvalidTransactionId
 
TransactionId RecentGlobalDataXmin = InvalidTransactionId
 
static HTABtuplecid_data = NULL
 
static ActiveSnapshotEltActiveSnapshot = NULL
 
static ActiveSnapshotEltOldestActiveSnapshot = NULL
 
static pairingheap RegisteredSnapshots = {&xmin_cmp, NULL, NULL}
 
bool FirstSnapshotSet = false
 
static Snapshot FirstXactSnapshot = NULL
 
static ListexportedSnapshots = NIL
 

Macro Definition Documentation

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"

Definition at line 213 of file snapmgr.c.

Referenced by DeleteAllExportedSnapshotFiles(), ExportSnapshot(), and ImportSnapshot().

#define XactExportFilePath (   path,
  xid,
  num,
  suffix 
)
Value:
snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%d%s", \
xid, num, suffix)
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:213

Definition at line 214 of file snapmgr.c.

Referenced by AtEOXact_Snapshot(), and ExportSnapshot().

Typedef Documentation

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
static TimestampTz AlignTimestampToMinuteBoundary ( TimestampTz  ts)
static

Definition at line 1620 of file snapmgr.c.

References USECS_PER_MINUTE.

Referenced by MaintainOldSnapshotTimeMapping(), and TransactionIdLimitedForOldSnapshots().

1621 {
1622  TimestampTz retval = ts + (USECS_PER_MINUTE - 1);
1623 
1624  return retval - (retval % USECS_PER_MINUTE);
1625 }
int64 TimestampTz
Definition: timestamp.h:39
#define USECS_PER_MINUTE
Definition: timestamp.h:93
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
static Snapshot CopySnapshot ( Snapshot  snapshot)
static

Definition at line 655 of file snapmgr.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, InvalidSnapshot, MemoryContextAlloc(), NULL, SnapshotData::regd_count, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TopTransactionContext, SnapshotData::xcnt, and SnapshotData::xip.

Referenced by ExportSnapshot(), GetTransactionSnapshot(), PushActiveSnapshot(), PushCopiedSnapshot(), RegisterSnapshotOnOwner(), and SetTransactionSnapshot().

656 {
657  Snapshot newsnap;
658  Size subxipoff;
659  Size size;
660 
661  Assert(snapshot != InvalidSnapshot);
662 
663  /* We allocate any XID arrays needed in the same palloc block. */
664  size = subxipoff = sizeof(SnapshotData) +
665  snapshot->xcnt * sizeof(TransactionId);
666  if (snapshot->subxcnt > 0)
667  size += snapshot->subxcnt * sizeof(TransactionId);
668 
670  memcpy(newsnap, snapshot, sizeof(SnapshotData));
671 
672  newsnap->regd_count = 0;
673  newsnap->active_count = 0;
674  newsnap->copied = true;
675 
676  /* setup XID array */
677  if (snapshot->xcnt > 0)
678  {
679  newsnap->xip = (TransactionId *) (newsnap + 1);
680  memcpy(newsnap->xip, snapshot->xip,
681  snapshot->xcnt * sizeof(TransactionId));
682  }
683  else
684  newsnap->xip = NULL;
685 
686  /*
687  * Setup subXID array. Don't bother to copy it if it had overflowed,
688  * though, because it's not used anywhere in that case. Except if it's a
689  * snapshot taken during recovery; all the top-level XIDs are in subxip as
690  * well in that case, so we mustn't lose them.
691  */
692  if (snapshot->subxcnt > 0 &&
693  (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
694  {
695  newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
696  memcpy(newsnap->subxip, snapshot->subxip,
697  snapshot->subxcnt * sizeof(TransactionId));
698  }
699  else
700  newsnap->subxip = NULL;
701 
702  return newsnap;
703 }
MemoryContext TopTransactionContext
Definition: mcxt.c:48
uint32 TransactionId
Definition: c.h:397
bool copied
Definition: snapshot.h:94
bool suboverflowed
Definition: snapshot.h:91
struct SnapshotData * Snapshot
Definition: snapshot.h:23
uint32 regd_count
Definition: snapshot.h:108
struct SnapshotData SnapshotData
TransactionId * xip
Definition: snapshot.h:77
#define InvalidSnapshot
Definition: snapshot.h:25
#define NULL
Definition: c.h:229
#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
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
TransactionId * subxip
Definition: snapshot.h:89
uint32 active_count
Definition: snapshot.h:107
int32 subxcnt
Definition: snapshot.h:90
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  snap)

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);
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 }
SnapshotSatisfiesFunc satisfies
Definition: snapshot.h:54
uint32 TransactionId
Definition: c.h:397
bool suboverflowed
Definition: snapshot.h:91
#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
bool takenDuringRecovery
Definition: snapshot.h:93
size_t Size
Definition: c.h:356
uint32 xcnt
Definition: snapshot.h:78
bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:963
int32 subxcnt
Definition: snapshot.h:90
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:1457
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
static void FreeSnapshot ( Snapshot  snapshot)
static

Definition at line 710 of file snapmgr.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, pfree(), and SnapshotData::regd_count.

Referenced by AtSubAbort_Snapshot(), PopActiveSnapshot(), and UnregisterSnapshotFromOwner().

711 {
712  Assert(snapshot->regd_count == 0);
713  Assert(snapshot->active_count == 0);
714  Assert(snapshot->copied);
715 
716  pfree(snapshot);
717 }
bool copied
Definition: snapshot.h:94
uint32 regd_count
Definition: snapshot.h:108
void pfree(void *pointer)
Definition: mcxt.c:950
#define Assert(condition)
Definition: c.h:675
uint32 active_count
Definition: snapshot.h:107
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:1498
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:1353
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:1330
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1498
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:1498
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
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:1446
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:1457
#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
static int parseIntFromText ( const char *  prefix,
char **  s,
const char *  filename 
)
static

Definition at line 1330 of file snapmgr.c.

References ereport, errcode(), errmsg(), ERROR, and val.

Referenced by ImportSnapshot().

1331 {
1332  char *ptr = *s;
1333  int prefixlen = strlen(prefix);
1334  int val;
1335 
1336  if (strncmp(ptr, prefix, prefixlen) != 0)
1337  ereport(ERROR,
1338  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1339  errmsg("invalid snapshot data in file \"%s\"", filename)));
1340  ptr += prefixlen;
1341  if (sscanf(ptr, "%d", &val) != 1)
1342  ereport(ERROR,
1343  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1344  errmsg("invalid snapshot data in file \"%s\"", filename)));
1345  ptr = strchr(ptr, '\n');
1346  if (!ptr)
1347  ereport(ERROR,
1348  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1349  errmsg("invalid snapshot data in file \"%s\"", filename)));
1350  *s = ptr + 1;
1351  return val;
1352 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static char * filename
Definition: pg_dumpall.c:87
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
static TransactionId parseXidFromText ( const char *  prefix,
char **  s,
const char *  filename 
)
static

Definition at line 1355 of file snapmgr.c.

References ereport, errcode(), errmsg(), ERROR, and val.

Referenced by ImportSnapshot().

1356 {
1357  char *ptr = *s;
1358  int prefixlen = strlen(prefix);
1360 
1361  if (strncmp(ptr, prefix, prefixlen) != 0)
1362  ereport(ERROR,
1363  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1364  errmsg("invalid snapshot data in file \"%s\"", filename)));
1365  ptr += prefixlen;
1366  if (sscanf(ptr, "%u", &val) != 1)
1367  ereport(ERROR,
1368  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1369  errmsg("invalid snapshot data in file \"%s\"", filename)));
1370  ptr = strchr(ptr, '\n');
1371  if (!ptr)
1372  ereport(ERROR,
1373  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1374  errmsg("invalid snapshot data in file \"%s\"", filename)));
1375  *s = ptr + 1;
1376  return val;
1377 }
uint32 TransactionId
Definition: c.h:397
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static char * filename
Definition: pg_dumpall.c:87
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
Datum pg_export_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 1315 of file snapmgr.c.

References cstring_to_text(), ExportSnapshot(), GetActiveSnapshot(), and PG_RETURN_TEXT_P.

1316 {
1317  char *snapshotName;
1318 
1319  snapshotName = ExportSnapshot(GetActiveSnapshot());
1320  PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1321 }
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1150
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:322
text * cstring_to_text(const char *s)
Definition: varlena.c:151
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  snap)

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
static void SetOldSnapshotThresholdTimestamp ( TimestampTz  ts,
TransactionId  xlimit 
)
static

Definition at line 1671 of file snapmgr.c.

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

Referenced by TransactionIdLimitedForOldSnapshots().

1672 {
1677 }
slock_t mutex_threshold
Definition: snapmgr.c:91
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: snapmgr.c:92
TransactionId threshold_xid
Definition: snapmgr.c:93
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64
static void SetTransactionSnapshot ( Snapshot  sourcesnap,
TransactionId  sourcexid,
PGPROC sourceproc 
)
static

Definition at line 561 of file snapmgr.c.

References Assert, CopySnapshot(), CurrentSnapshot, ereport, errcode(), errdetail(), errmsg(), ERROR, FirstSnapshotSet, GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotData(), HistoricSnapshotActive(), InvalidateCatalogSnapshot(), IsolationIsSerializable, IsolationUsesXactSnapshot, NULL, pairingheap_add(), pairingheap_is_empty, SnapshotData::ph_node, ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), SnapshotData::regd_count, SetSerializableTransactionSnapshot(), SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by ImportSnapshot(), and RestoreTransactionSnapshot().

563 {
564  /* Caller should have checked this already */
566 
567  /* Better do this to ensure following Assert succeeds. */
569 
573 
574  /*
575  * Even though we are not going to use the snapshot it computes, we must
576  * call GetSnapshotData, for two reasons: (1) to be sure that
577  * CurrentSnapshotData's XID arrays have been allocated, and (2) to update
578  * RecentXmin and RecentGlobalXmin. (We could alternatively include those
579  * two variables in exported snapshot files, but it seems better to have
580  * snapshot importers compute reasonably up-to-date values for them.)
581  */
583 
584  /*
585  * Now copy appropriate fields from the source snapshot.
586  */
587  CurrentSnapshot->xmin = sourcesnap->xmin;
588  CurrentSnapshot->xmax = sourcesnap->xmax;
589  CurrentSnapshot->xcnt = sourcesnap->xcnt;
590  Assert(sourcesnap->xcnt <= GetMaxSnapshotXidCount());
591  memcpy(CurrentSnapshot->xip, sourcesnap->xip,
592  sourcesnap->xcnt * sizeof(TransactionId));
593  CurrentSnapshot->subxcnt = sourcesnap->subxcnt;
594  Assert(sourcesnap->subxcnt <= GetMaxSnapshotSubxidCount());
595  memcpy(CurrentSnapshot->subxip, sourcesnap->subxip,
596  sourcesnap->subxcnt * sizeof(TransactionId));
599  /* NB: curcid should NOT be copied, it's a local matter */
600 
601  /*
602  * Now we have to fix what GetSnapshotData did with MyPgXact->xmin and
603  * TransactionXmin. There is a race condition: to make sure we are not
604  * causing the global xmin to go backwards, we have to test that the
605  * source transaction is still running, and that has to be done
606  * atomically. So let procarray.c do it.
607  *
608  * Note: in serializable mode, predicate.c will do this a second time. It
609  * doesn't seem worth contorting the logic here to avoid two calls,
610  * especially since it's not clear that predicate.c *must* do this.
611  */
612  if (sourceproc != NULL)
613  {
615  ereport(ERROR,
616  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
617  errmsg("could not import the requested snapshot"),
618  errdetail("The source transaction is not running anymore.")));
619  }
620  else if (!ProcArrayInstallImportedXmin(CurrentSnapshot->xmin, sourcexid))
621  ereport(ERROR,
622  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
623  errmsg("could not import the requested snapshot"),
624  errdetail("The source transaction %u is not running anymore.",
625  sourcexid)));
626 
627  /*
628  * In transaction-snapshot mode, the first snapshot must live until end of
629  * xact, so we must make a copy of it. Furthermore, if we're running in
630  * serializable mode, predicate.c needs to do its own processing.
631  */
633  {
636  /* Make a saved copy */
639  /* Mark it as "registered" in FirstXactSnapshot */
642  }
643 
644  FirstSnapshotSet = true;
645 }
bool ProcArrayInstallImportedXmin(TransactionId xmin, TransactionId sourcexid)
Definition: procarray.c:1786
uint32 TransactionId
Definition: c.h:397
void SetSerializableTransactionSnapshot(Snapshot snapshot, TransactionId sourcexid)
Definition: predicate.c:1603
#define IsolationUsesXactSnapshot()
Definition: xact.h:43
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
int errcode(int sqlerrcode)
Definition: elog.c:575
bool suboverflowed
Definition: snapshot.h:91
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
#define ERROR
Definition: elog.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
bool FirstSnapshotSet
Definition: snapmgr.c:203
int errdetail(const char *fmt,...)
Definition: elog.c:873
TransactionId xmax
Definition: snapshot.h:67
TransactionId xmin
Definition: snapshot.h:66
#define ereport(elevel, rest)
Definition: elog.h:122
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:506
TransactionId * xip
Definition: snapshot.h:77
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:655
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1446
pairingheap_node ph_node
Definition: snapshot.h:109
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool takenDuringRecovery
Definition: snapshot.h:93
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1498
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
Definition: procarray.c:1858
uint32 xcnt
Definition: snapshot.h:78
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1972
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1457
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
TransactionId * subxip
Definition: snapshot.h:89
int32 subxcnt
Definition: snapshot.h:90
void SetupHistoricSnapshot ( Snapshot  historic_snapshot,
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
static void SnapshotResetXmin ( void  )
static

Definition at line 973 of file snapmgr.c.

References InvalidTransactionId, MyPgXact, NULL, pairingheap_container, pairingheap_first(), pairingheap_is_empty, TransactionIdPrecedes(), SnapshotData::xmin, and PGXACT::xmin.

Referenced by AtEOXact_Snapshot(), AtSubAbort_Snapshot(), InvalidateCatalogSnapshot(), PopActiveSnapshot(), and UnregisterSnapshotFromOwner().

974 {
975  Snapshot minSnapshot;
976 
977  if (ActiveSnapshot != NULL)
978  return;
979 
981  {
983  return;
984  }
985 
986  minSnapshot = pairingheap_container(SnapshotData, ph_node,
988 
989  if (TransactionIdPrecedes(MyPgXact->xmin, minSnapshot->xmin))
990  MyPgXact->xmin = minSnapshot->xmin;
991 }
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
TransactionId xmin
Definition: proc.h:208
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
PGXACT * MyPgXact
Definition: proc.c:68
#define pairingheap_container(type, membername, ptr)
Definition: pairingheap.h:43
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
#define InvalidTransactionId
Definition: transam.h:31
TransactionId xmin
Definition: snapshot.h:66
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
#define NULL
Definition: c.h:229
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:208
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
static int xmin_cmp ( const pairingheap_node a,
const pairingheap_node b,
void *  arg 
)
static

Definition at line 939 of file snapmgr.c.

References pairingheap_const_container, TransactionIdFollows(), TransactionIdPrecedes(), and SnapshotData::xmin.

940 {
941  const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
942  const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
943 
944  if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
945  return 1;
946  else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
947  return -1;
948  else
949  return 0;
950 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
TransactionId xmin
Definition: snapshot.h:66
#define pairingheap_const_container(type, membername, ptr)
Definition: pairingheap.h:51
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300

Variable Documentation

ActiveSnapshotElt* ActiveSnapshot = NULL
static

Definition at line 188 of file snapmgr.c.

Referenced by PushActiveSnapshot().

Snapshot CatalogSnapshot = NULL
static

Definition at line 151 of file snapmgr.c.

Referenced by GetNonHistoricCatalogSnapshot().

SnapshotData CatalogSnapshotData = {HeapTupleSatisfiesMVCC}

Definition at line 146 of file snapmgr.c.

Snapshot CurrentSnapshot = NULL
static

Definition at line 149 of file snapmgr.c.

Referenced by GetTransactionSnapshot(), and SetTransactionSnapshot().

SnapshotData CurrentSnapshotData = {HeapTupleSatisfiesMVCC}
static

Definition at line 144 of file snapmgr.c.

List* exportedSnapshots = NIL
static

Definition at line 219 of file snapmgr.c.

Snapshot FirstXactSnapshot = NULL
static

Definition at line 210 of file snapmgr.c.

Snapshot HistoricSnapshot = NULL
static

Definition at line 152 of file snapmgr.c.

Referenced by GetCatalogSnapshot(), and GetTransactionSnapshot().

ActiveSnapshotElt* OldestActiveSnapshot = NULL
static

Definition at line 191 of file snapmgr.c.

volatile OldSnapshotControlData* oldSnapshotControl
static

Definition at line 129 of file snapmgr.c.

TransactionId RecentGlobalDataXmin = InvalidTransactionId

Definition at line 167 of file snapmgr.c.

Referenced by GetSnapshotData(), and heap_page_prune_opt().

pairingheap RegisteredSnapshots = {&xmin_cmp, NULL, NULL}
static

Definition at line 200 of file snapmgr.c.

Snapshot SecondarySnapshot = NULL
static

Definition at line 150 of file snapmgr.c.

Referenced by GetLatestSnapshot().

SnapshotData SecondarySnapshotData = {HeapTupleSatisfiesMVCC}
static

Definition at line 145 of file snapmgr.c.

HTAB* tuplecid_data = NULL
static

Definition at line 170 of file snapmgr.c.

Referenced by HistoricSnapshotGetTupleCids().