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, bool resetXmin)
 
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 1628 of file snapmgr.c.

References USECS_PER_MINUTE.

Referenced by MaintainOldSnapshotTimeMapping(), and TransactionIdLimitedForOldSnapshots().

1629 {
1630  TimestampTz retval = ts + (USECS_PER_MINUTE - 1);
1631 
1632  return retval - (retval % USECS_PER_MINUTE);
1633 }
int64 TimestampTz
Definition: timestamp.h:39
#define USECS_PER_MINUTE
Definition: timestamp.h:93
void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1054 of file snapmgr.c.

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

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

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

Definition at line 1018 of file snapmgr.c.

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

Referenced by AbortSubTransaction().

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

Definition at line 997 of file snapmgr.c.

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

Referenced by CommitSubTransaction().

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

1579 {
1580  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1581  DIR *s_dir;
1582  struct dirent *s_de;
1583 
1584  if (!(s_dir = AllocateDir(SNAPSHOT_EXPORT_DIR)))
1585  {
1586  /*
1587  * We really should have that directory in a sane cluster setup. But
1588  * then again if we don't, it's not fatal enough to make it FATAL.
1589  * Since we're running in the postmaster, LOG is our best bet.
1590  */
1591  elog(LOG, "could not open directory \"%s\": %m", SNAPSHOT_EXPORT_DIR);
1592  return;
1593  }
1594 
1595  while ((s_de = ReadDir(s_dir, SNAPSHOT_EXPORT_DIR)) != NULL)
1596  {
1597  if (strcmp(s_de->d_name, ".") == 0 ||
1598  strcmp(s_de->d_name, "..") == 0)
1599  continue;
1600 
1601  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1602  /* Again, unlink failure is not worthy of FATAL */
1603  if (unlink(buf))
1604  elog(LOG, "could not unlink file \"%s\": %m", buf);
1605  }
1606 
1607  FreeDir(s_dir);
1608 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:213
Definition: dirent.c:25
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:66
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2335
int unlink(const char *filename)
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2444
Size EstimateSnapshotSpace ( Snapshot  snap)

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

2001 {
2002  Size size;
2003 
2004  Assert(snap != InvalidSnapshot);
2006 
2007  /* We allocate any XID arrays needed in the same palloc block. */
2008  size = add_size(sizeof(SerializedSnapshotData),
2009  mul_size(snap->xcnt, sizeof(TransactionId)));
2010  if (snap->subxcnt > 0 &&
2011  (!snap->suboverflowed || snap->takenDuringRecovery))
2012  size = add_size(size,
2013  mul_size(snap->subxcnt, sizeof(TransactionId)));
2014 
2015  return size;
2016 }
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 1158 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().

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

Definition at line 375 of file snapmgr.c.

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

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

376 {
377  /*
378  * We might be able to relax this, but nothing that could otherwise work
379  * needs it.
380  */
381  if (IsInParallelMode())
382  elog(ERROR,
383  "cannot update SecondarySnapshot during a parallel operation");
384 
385  /*
386  * So far there are no cases requiring support for GetLatestSnapshot()
387  * during logical decoding, but it wouldn't be hard to add if required.
388  */
390 
391  /* If first call in transaction, go ahead and set the xact snapshot */
392  if (!FirstSnapshotSet)
393  return GetTransactionSnapshot();
394 
396 
397  return SecondarySnapshot;
398 }
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
bool IsInParallelMode(void)
Definition: xact.c:913
#define ERROR
Definition: elog.h:43
bool FirstSnapshotSet
Definition: snapmgr.c:203
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:145
#define Assert(condition)
Definition: c.h:675
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1508
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1980
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:1398
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:1375
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1508
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
Snapshot GetOldestSnapshot ( void  )

Definition at line 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 1667 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1668 {
1669  TimestampTz threshold_timestamp;
1670 
1672  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1674 
1675  return threshold_timestamp;
1676 }
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 1642 of file snapmgr.c.

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

Referenced by GetSnapshotData(), and TransactionIdLimitedForOldSnapshots().

1643 {
1645 
1646  /*
1647  * Don't let time move backward; if it hasn't advanced, use the old value.
1648  */
1650  if (now <= oldSnapshotControl->current_timestamp)
1652  else
1655 
1656  return now;
1657 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
int64 TimestampTz
Definition: timestamp.h:39
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz current_timestamp
Definition: snapmgr.c:86
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64
slock_t mutex_current
Definition: snapmgr.c:85
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
Snapshot GetTransactionSnapshot ( void  )

Definition at line 300 of file snapmgr.c.

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

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

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

References NULL.

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

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

Definition at line 1986 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

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

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

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

Definition at line 506 of file snapmgr.c.

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

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

507 {
508  if (CatalogSnapshot)
509  {
513  }
514 }
static void SnapshotResetXmin(void)
Definition: snapmgr.c:973
static Snapshot CatalogSnapshot
Definition: snapmgr.c:151
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
pairingheap_node ph_node
Definition: snapshot.h:109
#define NULL
Definition: c.h:229
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170
void InvalidateCatalogSnapshotConditionally ( void  )

Definition at line 527 of file snapmgr.c.

References InvalidateCatalogSnapshot(), NULL, and pairingheap_is_singular.

Referenced by PostgresMain().

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

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

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

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

Referenced by ImportSnapshot().

1339 {
1340  char *ptr = *s;
1341  int prefixlen = strlen(prefix);
1342  int val;
1343 
1344  if (strncmp(ptr, prefix, prefixlen) != 0)
1345  ereport(ERROR,
1346  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1347  errmsg("invalid snapshot data in file \"%s\"", filename)));
1348  ptr += prefixlen;
1349  if (sscanf(ptr, "%d", &val) != 1)
1350  ereport(ERROR,
1351  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1352  errmsg("invalid snapshot data in file \"%s\"", filename)));
1353  ptr = strchr(ptr, '\n');
1354  if (!ptr)
1355  ereport(ERROR,
1356  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1357  errmsg("invalid snapshot data in file \"%s\"", filename)));
1358  *s = ptr + 1;
1359  return val;
1360 }
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:89
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 1363 of file snapmgr.c.

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

Referenced by ImportSnapshot().

1364 {
1365  char *ptr = *s;
1366  int prefixlen = strlen(prefix);
1368 
1369  if (strncmp(ptr, prefix, prefixlen) != 0)
1370  ereport(ERROR,
1371  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1372  errmsg("invalid snapshot data in file \"%s\"", filename)));
1373  ptr += prefixlen;
1374  if (sscanf(ptr, "%u", &val) != 1)
1375  ereport(ERROR,
1376  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1377  errmsg("invalid snapshot data in file \"%s\"", filename)));
1378  ptr = strchr(ptr, '\n');
1379  if (!ptr)
1380  ereport(ERROR,
1381  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1382  errmsg("invalid snapshot data in file \"%s\"", filename)));
1383  *s = ptr + 1;
1384  return val;
1385 }
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:89
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 1323 of file snapmgr.c.

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

1324 {
1325  char *snapshotName;
1326 
1327  snapshotName = ExportSnapshot(GetActiveSnapshot());
1328  PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1329 }
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1158
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
text * cstring_to_text(const char *s)
Definition: varlena.c:149
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 2078 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().

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

References InvalidTransactionId, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2143 {
2144  SetTransactionSnapshot(snapshot, InvalidTransactionId, master_pgproc);
2145 }
#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 2024 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().

2025 {
2026  SerializedSnapshotData serialized_snapshot;
2027 
2028  Assert(snapshot->subxcnt >= 0);
2029 
2030  /* Copy all required fields */
2031  serialized_snapshot.xmin = snapshot->xmin;
2032  serialized_snapshot.xmax = snapshot->xmax;
2033  serialized_snapshot.xcnt = snapshot->xcnt;
2034  serialized_snapshot.subxcnt = snapshot->subxcnt;
2035  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2036  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2037  serialized_snapshot.curcid = snapshot->curcid;
2038  serialized_snapshot.whenTaken = snapshot->whenTaken;
2039  serialized_snapshot.lsn = snapshot->lsn;
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.suboverflowed && !snapshot->takenDuringRecovery)
2058  serialized_snapshot.subxcnt = 0;
2059 
2060  if (serialized_snapshot.subxcnt > 0)
2061  {
2062  Size subxipoff = sizeof(SerializedSnapshotData) +
2063  snapshot->xcnt * sizeof(TransactionId);
2064 
2065  memcpy((TransactionId *) (start_address + subxipoff),
2066  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2067  }
2068 }
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 1679 of file snapmgr.c.

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

Referenced by TransactionIdLimitedForOldSnapshots().

1680 {
1685 }
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:1796
uint32 TransactionId
Definition: c.h:397
void SetSerializableTransactionSnapshot(Snapshot snapshot, TransactionId sourcexid)
Definition: predicate.c:1660
#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:1455
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:1508
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
Definition: procarray.c:1868
uint32 xcnt
Definition: snapshot.h:78
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1980
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1466
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 1957 of file snapmgr.c.

References Assert, and NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1958 {
1959  Assert(historic_snapshot != NULL);
1960 
1961  /* setup the timetravel snapshot */
1962  HistoricSnapshot = historic_snapshot;
1963 
1964  /* setup (cmin, cmax) lookup hash */
1965  tuplecid_data = tuplecids;
1966 }
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:213
#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 1973 of file snapmgr.c.

References NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1974 {
1976  tuplecid_data = NULL;
1977 }
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 1611 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom().

1612 {
1615  return true;
1616 
1617  return false;
1618 }
#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 1697 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().

1699 {
1700  if (TransactionIdIsNormal(recentXmin)
1701  && old_snapshot_threshold >= 0
1702  && RelationAllowsEarlyPruning(relation))
1703  {
1705  TransactionId xlimit = recentXmin;
1706  TransactionId latest_xmin;
1707  TimestampTz update_ts;
1708  bool same_ts_as_threshold = false;
1709 
1711  latest_xmin = oldSnapshotControl->latest_xmin;
1712  update_ts = oldSnapshotControl->next_map_update;
1714 
1715  /*
1716  * Zero threshold always overrides to latest xmin, if valid. Without
1717  * some heuristic it will find its own snapshot too old on, for
1718  * example, a simple UPDATE -- which would make it useless for most
1719  * testing, but there is no principled way to ensure that it doesn't
1720  * fail in this way. Use a five-second delay to try to get useful
1721  * testing behavior, but this may need adjustment.
1722  */
1723  if (old_snapshot_threshold == 0)
1724  {
1725  if (TransactionIdPrecedes(latest_xmin, MyPgXact->xmin)
1726  && TransactionIdFollows(latest_xmin, xlimit))
1727  xlimit = latest_xmin;
1728 
1729  ts -= 5 * USECS_PER_SEC;
1731 
1732  return xlimit;
1733  }
1734 
1737 
1738  /* Check for fast exit without LW locking. */
1741  {
1743  same_ts_as_threshold = true;
1744  }
1746 
1747  if (!same_ts_as_threshold)
1748  {
1749  if (ts == update_ts)
1750  {
1751  xlimit = latest_xmin;
1752  if (NormalTransactionIdFollows(xlimit, recentXmin))
1754  }
1755  else
1756  {
1757  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1758 
1761  {
1762  int offset;
1763 
1764  offset = ((ts - oldSnapshotControl->head_timestamp)
1765  / USECS_PER_MINUTE);
1766  if (offset > oldSnapshotControl->count_used - 1)
1767  offset = oldSnapshotControl->count_used - 1;
1768  offset = (oldSnapshotControl->head_offset + offset)
1770  xlimit = oldSnapshotControl->xid_by_minute[offset];
1771 
1772  if (NormalTransactionIdFollows(xlimit, recentXmin))
1774  }
1775 
1776  LWLockRelease(OldSnapshotTimeMapLock);
1777  }
1778  }
1779 
1780  /*
1781  * Failsafe protection against vacuuming work of active transaction.
1782  *
1783  * This is not an assertion because we avoid the spinlock for
1784  * performance, leaving open the possibility that xlimit could advance
1785  * and be more current; but it seems prudent to apply this limit. It
1786  * might make pruning a tiny bit less aggressive than it could be, but
1787  * protects against data loss bugs.
1788  */
1789  if (TransactionIdIsNormal(latest_xmin)
1790  && TransactionIdPrecedes(latest_xmin, xlimit))
1791  xlimit = latest_xmin;
1792 
1793  if (NormalTransactionIdFollows(xlimit, recentXmin))
1794  return xlimit;
1795  }
1796 
1797  return recentXmin;
1798 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:397
#define USECS_PER_SEC
Definition: timestamp.h:94
TransactionId xmin
Definition: proc.h:213
int64 TimestampTz
Definition: timestamp.h:39
slock_t mutex_threshold
Definition: snapmgr.c:91
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38
#define USECS_PER_MINUTE
Definition: timestamp.h:93
PGXACT * MyPgXact
Definition: proc.c:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimestampTz threshold_timestamp
Definition: snapmgr.c:92
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1642
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:1679
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:1628
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 1565 of file snapmgr.c.

References NIL.

Referenced by PrepareTransaction().

1566 {
1567  return (exportedSnapshots != NIL);
1568 }
#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().