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/sinvaladt.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  ExportedSnapshot
 
struct  SerializedSnapshotData
 

Macros

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"
 

Typedefs

typedef struct
OldSnapshotControlData 
OldSnapshotControlData
 
typedef struct ActiveSnapshotElt ActiveSnapshotElt
 
typedef struct ExportedSnapshot ExportedSnapshot
 
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, VirtualTransactionId *sourcevxid, int sourcepid, 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)
 
static void parseVxidFromText (const char *prefix, char **s, const char *filename, VirtualTransactionId *vxid)
 
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().

Typedef Documentation

Function Documentation

bool ActiveSnapshotSet ( void  )

Definition at line 851 of file snapmgr.c.

References NULL.

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

852 {
853  return ActiveSnapshot != NULL;
854 }
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
#define NULL
Definition: c.h:229
static TimestampTz AlignTimestampToMinuteBoundary ( TimestampTz  ts)
static

Definition at line 1666 of file snapmgr.c.

References USECS_PER_MINUTE.

Referenced by MaintainOldSnapshotTimeMapping(), and TransactionIdLimitedForOldSnapshots().

1667 {
1668  TimestampTz retval = ts + (USECS_PER_MINUTE - 1);
1669 
1670  return retval - (retval % USECS_PER_MINUTE);
1671 }
int64 TimestampTz
Definition: timestamp.h:39
#define USECS_PER_MINUTE
Definition: timestamp.h:93
void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1059 of file snapmgr.c.

References ActiveSnapshotElt::as_next, Assert, elog, FirstSnapshotSet, InvalidateCatalogSnapshot(), lfirst, MyPgXact, NIL, NULL, pairingheap_is_empty, pairingheap_remove(), pairingheap_reset, SnapshotData::ph_node, SnapshotData::regd_count, ExportedSnapshot::snapfile, ExportedSnapshot::snapshot, SnapshotResetXmin(), unlink(), WARNING, and PGXACT::xmin.

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

1060 {
1061  /*
1062  * In transaction-snapshot mode we must release our privately-managed
1063  * reference to the transaction snapshot. We must remove it from
1064  * RegisteredSnapshots to keep the check below happy. But we don't bother
1065  * to do FreeSnapshot, for two reasons: the memory will go away with
1066  * TopTransactionContext anyway, and if someone has left the snapshot
1067  * stacked as active, we don't want the code below to be chasing through a
1068  * dangling pointer.
1069  */
1070  if (FirstXactSnapshot != NULL)
1071  {
1075  }
1077 
1078  /*
1079  * If we exported any snapshots, clean them up.
1080  */
1081  if (exportedSnapshots != NIL)
1082  {
1083  ListCell *lc;
1084 
1085  /*
1086  * Get rid of the files. Unlink failure is only a WARNING because (1)
1087  * it's too late to abort the transaction, and (2) leaving a leaked
1088  * file around has little real consequence anyway.
1089  *
1090  * We also also need to remove the snapshots from RegisteredSnapshots
1091  * to prevent a warning below.
1092  *
1093  * As with the FirstXactSnapshot, we don't need to free resources of
1094  * the snapshot iself as it will go away with the memory context.
1095  */
1096  foreach(lc, exportedSnapshots)
1097  {
1098  ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1099 
1100  if (unlink(esnap->snapfile))
1101  elog(WARNING, "could not unlink file \"%s\": %m",
1102  esnap->snapfile);
1103 
1105  &esnap->snapshot->ph_node);
1106  }
1107 
1109  }
1110 
1111  /* Drop catalog snapshot if any */
1113 
1114  /* On commit, complain about leftover snapshots */
1115  if (isCommit)
1116  {
1117  ActiveSnapshotElt *active;
1118 
1120  elog(WARNING, "registered snapshots seem to remain after cleanup");
1121 
1122  /* complain about unpopped active snapshots */
1123  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1124  elog(WARNING, "snapshot %p still active", active);
1125  }
1126 
1127  /*
1128  * And reset our state. We don't need to free the memory explicitly --
1129  * it'll go away with TopTransactionContext.
1130  */
1131  ActiveSnapshot = NULL;
1134 
1137 
1138  FirstSnapshotSet = false;
1139 
1140  /*
1141  * During normal commit processing, we call ProcArrayEndTransaction() to
1142  * reset the PgXact->xmin. That call happens prior to the call to
1143  * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1144  */
1145  if (resetXmin)
1147 
1148  Assert(resetXmin || MyPgXact->xmin == 0);
1149 }
#define NIL
Definition: pg_list.h:69
#define pairingheap_reset(h)
Definition: pairingheap.h:93
TransactionId xmin
Definition: proc.h:213
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:210
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:223
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
bool FirstSnapshotSet
Definition: snapmgr.c:203
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:191
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:184
int unlink(const char *filename)
Snapshot snapshot
Definition: snapmgr.c:219
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:510
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:188
char * snapfile
Definition: snapmgr.c:218
#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:676
#define lfirst(lc)
Definition: pg_list.h:106
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
void AtSubAbort_Snapshot ( int  level)

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

1024 {
1025  /* Forget the active snapshots set by this subtransaction */
1026  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
1027  {
1029 
1030  next = ActiveSnapshot->as_next;
1031 
1032  /*
1033  * Decrement the snapshot's active count. If it's still registered or
1034  * marked as active by an outer subtransaction, we can't free it yet.
1035  */
1038 
1039  if (ActiveSnapshot->as_snap->active_count == 0 &&
1042 
1043  /* and free the stack element */
1045 
1046  ActiveSnapshot = next;
1047  if (ActiveSnapshot == NULL)
1049  }
1050 
1052 }
Snapshot as_snap
Definition: snapmgr.c:182
static int32 next
Definition: blutils.c:210
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:715
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
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:676
uint32 active_count
Definition: snapshot.h:107
void AtSubCommit_Snapshot ( int  level)

Definition at line 1002 of file snapmgr.c.

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

Referenced by CommitSubTransaction().

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

661 {
662  Snapshot newsnap;
663  Size subxipoff;
664  Size size;
665 
666  Assert(snapshot != InvalidSnapshot);
667 
668  /* We allocate any XID arrays needed in the same palloc block. */
669  size = subxipoff = sizeof(SnapshotData) +
670  snapshot->xcnt * sizeof(TransactionId);
671  if (snapshot->subxcnt > 0)
672  size += snapshot->subxcnt * sizeof(TransactionId);
673 
675  memcpy(newsnap, snapshot, sizeof(SnapshotData));
676 
677  newsnap->regd_count = 0;
678  newsnap->active_count = 0;
679  newsnap->copied = true;
680 
681  /* setup XID array */
682  if (snapshot->xcnt > 0)
683  {
684  newsnap->xip = (TransactionId *) (newsnap + 1);
685  memcpy(newsnap->xip, snapshot->xip,
686  snapshot->xcnt * sizeof(TransactionId));
687  }
688  else
689  newsnap->xip = NULL;
690 
691  /*
692  * Setup subXID array. Don't bother to copy it if it had overflowed,
693  * though, because it's not used anywhere in that case. Except if it's a
694  * snapshot taken during recovery; all the top-level XIDs are in subxip as
695  * well in that case, so we mustn't lose them.
696  */
697  if (snapshot->subxcnt > 0 &&
698  (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
699  {
700  newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
701  memcpy(newsnap->subxip, snapshot->subxip,
702  snapshot->subxcnt * sizeof(TransactionId));
703  }
704  else
705  newsnap->subxip = NULL;
706 
707  return newsnap;
708 }
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:676
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 1616 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().

1617 {
1618  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1619  DIR *s_dir;
1620  struct dirent *s_de;
1621 
1622  if (!(s_dir = AllocateDir(SNAPSHOT_EXPORT_DIR)))
1623  {
1624  /*
1625  * We really should have that directory in a sane cluster setup. But
1626  * then again if we don't, it's not fatal enough to make it FATAL.
1627  * Since we're running in the postmaster, LOG is our best bet.
1628  */
1629  elog(LOG, "could not open directory \"%s\": %m", SNAPSHOT_EXPORT_DIR);
1630  return;
1631  }
1632 
1633  while ((s_de = ReadDir(s_dir, SNAPSHOT_EXPORT_DIR)) != NULL)
1634  {
1635  if (strcmp(s_de->d_name, ".") == 0 ||
1636  strcmp(s_de->d_name, "..") == 0)
1637  continue;
1638 
1639  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1640  /* Again, unlink failure is not worthy of FATAL */
1641  if (unlink(buf))
1642  elog(LOG, "could not unlink file \"%s\": %m", buf);
1643  }
1644 
1645  FreeDir(s_dir);
1646 }
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 2038 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().

2039 {
2040  Size size;
2041 
2042  Assert(snap != InvalidSnapshot);
2044 
2045  /* We allocate any XID arrays needed in the same palloc block. */
2046  size = add_size(sizeof(SerializedSnapshotData),
2047  mul_size(snap->xcnt, sizeof(TransactionId)));
2048  if (snap->subxcnt > 0 &&
2049  (!snap->suboverflowed || snap->takenDuringRecovery))
2050  size = add_size(size,
2051  mul_size(snap->subxcnt, sizeof(TransactionId)));
2052 
2053  return size;
2054 }
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:676
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 1159 of file snapmgr.c.

References AllocateFile(), appendStringInfo(), appendStringInfoString(), PGPROC::backendId, buf, CopySnapshot(), StringInfoData::data, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, FreeFile(), GetMaxSnapshotSubxidCount(), GetTopTransactionIdIfAny(), i, initStringInfo(), IsSubTransaction(), lappend(), StringInfoData::len, list_length(), PGPROC::lxid, MAXPGPATH, MemoryContextSwitchTo(), MyDatabaseId, MyProc, MyProcPid, pairingheap_add(), palloc(), PG_BINARY_W, SnapshotData::ph_node, pstrdup(), SnapshotData::regd_count, ExportedSnapshot::snapfile, ExportedSnapshot::snapshot, SNAPSHOT_EXPORT_DIR, snprintf(), SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TopTransactionContext, TransactionIdIsValid, TransactionIdPrecedes(), xactGetCommittedChildren(), XactIsoLevel, XactReadOnly, SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by pg_export_snapshot(), and SnapBuildExportSnapshot().

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

Definition at line 715 of file snapmgr.c.

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

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

716 {
717  Assert(snapshot->regd_count == 0);
718  Assert(snapshot->active_count == 0);
719  Assert(snapshot->copied);
720 
721  pfree(snapshot);
722 }
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:676
uint32 active_count
Definition: snapshot.h:107
Snapshot GetCatalogSnapshot ( Oid  relid)

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

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

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

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

Definition at line 462 of file snapmgr.c.

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

Referenced by GetCatalogSnapshot(), and ScanPgRelation().

463 {
464  /*
465  * If the caller is trying to scan a relation that has no syscache, no
466  * catcache invalidations will be sent when it is updated. For a few key
467  * relations, snapshot invalidations are sent instead. If we're trying to
468  * scan a relation for which neither catcache nor snapshot invalidations
469  * are sent, we must refresh the snapshot every time.
470  */
471  if (CatalogSnapshot &&
473  !RelationHasSysCache(relid))
475 
476  if (CatalogSnapshot == NULL)
477  {
478  /* Get new snapshot. */
480 
481  /*
482  * Make sure the catalog snapshot will be accounted for in decisions
483  * about advancing PGXACT->xmin. We could apply RegisterSnapshot, but
484  * that would result in making a physical copy, which is overkill; and
485  * it would also create a dependency on some resource owner, which we
486  * do not want for reasons explained at the head of this file. Instead
487  * just shove the CatalogSnapshot into the pairing heap manually. This
488  * has to be reversed in InvalidateCatalogSnapshot, of course.
489  *
490  * NB: it had better be impossible for this to throw error, since the
491  * CatalogSnapshot pointer is already valid.
492  */
494  }
495 
496  return CatalogSnapshot;
497 }
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:510
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:1509
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
Snapshot GetOldestSnapshot ( void  )

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

412 {
413  Snapshot OldestRegisteredSnapshot = NULL;
414  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
415 
417  {
418  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
420  RegisteredLSN = OldestRegisteredSnapshot->lsn;
421  }
422 
423  if (OldestActiveSnapshot != NULL)
424  {
426 
427  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
429  }
430 
431  return OldestRegisteredSnapshot;
432 }
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 1705 of file snapmgr.c.

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

Referenced by TestForOldSnapshot_impl().

1706 {
1707  TimestampTz threshold_timestamp;
1708 
1710  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1712 
1713  return threshold_timestamp;
1714 }
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 1680 of file snapmgr.c.

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

Referenced by GetSnapshotData(), and TransactionIdLimitedForOldSnapshots().

1681 {
1683 
1684  /*
1685  * Don't let time move backward; if it hasn't advanced, use the old value.
1686  */
1688  if (now <= oldSnapshotControl->current_timestamp)
1690  else
1693 
1694  return now;
1695 }
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:87
static volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:129
#define SpinLockRelease(lock)
Definition: spin.h:64
slock_t mutex_current
Definition: snapmgr.c:86
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
Snapshot GetTransactionSnapshot ( void  )

Definition at line 304 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(), LogicalRepSyncTableStart(), pg_get_constraintdef_worker(), PortalRunMulti(), PortalRunUtility(), PortalStart(), ReindexMultipleTables(), RevalidateCachedQuery(), ri_PerformCheck(), SPI_cursor_open_internal(), vacuum(), vacuum_rel(), and XidIsConcurrent().

305 {
306  /*
307  * Return historic snapshot if doing logical decoding. We'll never need a
308  * non-historic transaction snapshot in this (sub-)transaction, so there's
309  * no need to be careful to set one up for later calls to
310  * GetTransactionSnapshot().
311  */
313  {
315  return HistoricSnapshot;
316  }
317 
318  /* First call in transaction? */
319  if (!FirstSnapshotSet)
320  {
321  /*
322  * Don't allow catalog snapshot to be older than xact snapshot. Must
323  * do this first to allow the empty-heap Assert to succeed.
324  */
326 
329 
330  if (IsInParallelMode())
331  elog(ERROR,
332  "cannot take query snapshot during a parallel operation");
333 
334  /*
335  * In transaction-snapshot mode, the first snapshot must live until
336  * end of xact regardless of what the caller does with it, so we must
337  * make a copy of it rather than returning CurrentSnapshotData
338  * directly. Furthermore, if we're running in serializable mode,
339  * predicate.c needs to wrap the snapshot fetch in its own processing.
340  */
342  {
343  /* First, create the snapshot in CurrentSnapshotData */
346  else
348  /* Make a saved copy */
351  /* Mark it as "registered" in FirstXactSnapshot */
354  }
355  else
357 
358  FirstSnapshotSet = true;
359  return CurrentSnapshot;
360  }
361 
363  return CurrentSnapshot;
364 
365  /* Don't allow catalog snapshot to be older than xact snapshot. */
367 
369 
370  return CurrentSnapshot;
371 }
#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:510
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:660
pairingheap_node ph_node
Definition: snapshot.h:109
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1634
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1509
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2018
#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 2018 of file snapmgr.c.

References NULL.

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

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

Definition at line 2024 of file snapmgr.c.

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

2025 {
2027  return tuplecid_data;
2028 }
static HTAB * tuplecid_data
Definition: snapmgr.c:170
#define Assert(condition)
Definition: c.h:676
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2018
void ImportSnapshot ( const char *  idstr)

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

Referenced by ExecSetVariableStmt().

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

511 {
512  if (CatalogSnapshot)
513  {
517  }
518 }
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
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 531 of file snapmgr.c.

References InvalidateCatalogSnapshot(), NULL, and pairingheap_is_singular.

Referenced by PostgresMain().

532 {
533  if (CatalogSnapshot &&
534  ActiveSnapshot == NULL &&
537 }
static Snapshot CatalogSnapshot
Definition: snapmgr.c:151
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:200
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:510
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 1842 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().

1843 {
1844  TimestampTz ts;
1845  TransactionId latest_xmin;
1846  TimestampTz update_ts;
1847  bool map_update_required = false;
1848 
1849  /* Never call this function when old snapshot checking is disabled. */
1851 
1852  ts = AlignTimestampToMinuteBoundary(whenTaken);
1853 
1854  /*
1855  * Keep track of the latest xmin seen by any process. Update mapping with
1856  * a new value when we have crossed a bucket boundary.
1857  */
1859  latest_xmin = oldSnapshotControl->latest_xmin;
1860  update_ts = oldSnapshotControl->next_map_update;
1861  if (ts > update_ts)
1862  {
1864  map_update_required = true;
1865  }
1866  if (TransactionIdFollows(xmin, latest_xmin))
1869 
1870  /* We only needed to update the most recent xmin value. */
1871  if (!map_update_required)
1872  return;
1873 
1874  /* No further tracking needed for 0 (used for testing). */
1875  if (old_snapshot_threshold == 0)
1876  return;
1877 
1878  /*
1879  * We don't want to do something stupid with unusual values, but we don't
1880  * want to litter the log with warnings or break otherwise normal
1881  * processing for this feature; so if something seems unreasonable, just
1882  * log at DEBUG level and return without doing anything.
1883  */
1884  if (whenTaken < 0)
1885  {
1886  elog(DEBUG1,
1887  "MaintainOldSnapshotTimeMapping called with negative whenTaken = %ld",
1888  (long) whenTaken);
1889  return;
1890  }
1891  if (!TransactionIdIsNormal(xmin))
1892  {
1893  elog(DEBUG1,
1894  "MaintainOldSnapshotTimeMapping called with xmin = %lu",
1895  (unsigned long) xmin);
1896  return;
1897  }
1898 
1899  LWLockAcquire(OldSnapshotTimeMapLock, LW_EXCLUSIVE);
1900 
1906 
1907  if (oldSnapshotControl->count_used == 0)
1908  {
1909  /* set up first entry for empty mapping */
1913  oldSnapshotControl->xid_by_minute[0] = xmin;
1914  }
1915  else if (ts < oldSnapshotControl->head_timestamp)
1916  {
1917  /* old ts; log it at DEBUG */
1918  LWLockRelease(OldSnapshotTimeMapLock);
1919  elog(DEBUG1,
1920  "MaintainOldSnapshotTimeMapping called with old whenTaken = %ld",
1921  (long) whenTaken);
1922  return;
1923  }
1924  else if (ts <= (oldSnapshotControl->head_timestamp +
1926  * USECS_PER_MINUTE)))
1927  {
1928  /* existing mapping; advance xid if possible */
1929  int bucket = (oldSnapshotControl->head_offset
1931  / USECS_PER_MINUTE))
1933 
1935  oldSnapshotControl->xid_by_minute[bucket] = xmin;
1936  }
1937  else
1938  {
1939  /* We need a new bucket, but it might not be the very next one. */
1940  int advance = ((ts - oldSnapshotControl->head_timestamp)
1941  / USECS_PER_MINUTE);
1942 
1944 
1945  if (advance >= OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1946  {
1947  /* Advance is so far that all old data is junk; start over. */
1950  oldSnapshotControl->xid_by_minute[0] = xmin;
1951  }
1952  else
1953  {
1954  /* Store the new value in one or more buckets. */
1955  int i;
1956 
1957  for (i = 0; i < advance; i++)
1958  {
1960  {
1961  /* Map full and new value replaces old head. */
1962  int old_head = oldSnapshotControl->head_offset;
1963 
1964  if (old_head == (OLD_SNAPSHOT_TIME_MAP_ENTRIES - 1))
1966  else
1967  oldSnapshotControl->head_offset = old_head + 1;
1968  oldSnapshotControl->xid_by_minute[old_head] = xmin;
1969  }
1970  else
1971  {
1972  /* Extend map to unused entry. */
1973  int new_tail = (oldSnapshotControl->head_offset
1976 
1978  oldSnapshotControl->xid_by_minute[new_tail] = xmin;
1979  }
1980  }
1981  }
1982  }
1983 
1984  LWLockRelease(OldSnapshotTimeMapLock);
1985 }
#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:88
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:676
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:1666
int old_snapshot_threshold
Definition: snapmgr.c:75
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 1350 of file snapmgr.c.

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

Referenced by ImportSnapshot().

1351 {
1352  char *ptr = *s;
1353  int prefixlen = strlen(prefix);
1354  int val;
1355 
1356  if (strncmp(ptr, prefix, prefixlen) != 0)
1357  ereport(ERROR,
1358  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1359  errmsg("invalid snapshot data in file \"%s\"", filename)));
1360  ptr += prefixlen;
1361  if (sscanf(ptr, "%d", &val) != 1)
1362  ereport(ERROR,
1363  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1364  errmsg("invalid snapshot data in file \"%s\"", filename)));
1365  ptr = strchr(ptr, '\n');
1366  if (!ptr)
1367  ereport(ERROR,
1368  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1369  errmsg("invalid snapshot data in file \"%s\"", filename)));
1370  *s = ptr + 1;
1371  return val;
1372 }
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:90
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
static void parseVxidFromText ( const char *  prefix,
char **  s,
const char *  filename,
VirtualTransactionId vxid 
)
static

Definition at line 1400 of file snapmgr.c.

References VirtualTransactionId::backendId, ereport, errcode(), errmsg(), ERROR, and VirtualTransactionId::localTransactionId.

Referenced by ImportSnapshot().

1402 {
1403  char *ptr = *s;
1404  int prefixlen = strlen(prefix);
1405 
1406  if (strncmp(ptr, prefix, prefixlen) != 0)
1407  ereport(ERROR,
1408  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1409  errmsg("invalid snapshot data in file \"%s\"", filename)));
1410  ptr += prefixlen;
1411  if (sscanf(ptr, "%d/%u", &vxid->backendId, &vxid->localTransactionId) != 2)
1412  ereport(ERROR,
1413  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1414  errmsg("invalid snapshot data in file \"%s\"", filename)));
1415  ptr = strchr(ptr, '\n');
1416  if (!ptr)
1417  ereport(ERROR,
1418  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1419  errmsg("invalid snapshot data in file \"%s\"", filename)));
1420  *s = ptr + 1;
1421 }
int errcode(int sqlerrcode)
Definition: elog.c:575
LocalTransactionId localTransactionId
Definition: lock.h:66
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
BackendId backendId
Definition: lock.h:65
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:797
static TransactionId parseXidFromText ( const char *  prefix,
char **  s,
const char *  filename 
)
static

Definition at line 1375 of file snapmgr.c.

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

Referenced by ImportSnapshot().

1376 {
1377  char *ptr = *s;
1378  int prefixlen = strlen(prefix);
1380 
1381  if (strncmp(ptr, prefix, prefixlen) != 0)
1382  ereport(ERROR,
1383  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1384  errmsg("invalid snapshot data in file \"%s\"", filename)));
1385  ptr += prefixlen;
1386  if (sscanf(ptr, "%u", &val) != 1)
1387  ereport(ERROR,
1388  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1389  errmsg("invalid snapshot data in file \"%s\"", filename)));
1390  ptr = strchr(ptr, '\n');
1391  if (!ptr)
1392  ereport(ERROR,
1393  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1394  errmsg("invalid snapshot data in file \"%s\"", filename)));
1395  *s = ptr + 1;
1396  return val;
1397 }
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:90
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 1335 of file snapmgr.c.

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

1336 {
1337  char *snapshotName;
1338 
1339  snapshotName = ExportSnapshot(GetActiveSnapshot());
1340  PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1341 }
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:839
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1159
#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 812 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(), LogicalRepSyncTableStart(), movedb(), ParallelWorkerMain(), PersistHoldablePortal(), PortalRunMulti(), PortalRunSelect(), PortalRunUtility(), PortalStart(), refresh_matview_datafill(), ReindexMultipleTables(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RevalidateCachedQuery(), ShutdownSQLFunction(), vacuum(), vacuum_rel(), and wait_for_relation_state_change().

813 {
814  ActiveSnapshotElt *newstack;
815 
816  newstack = ActiveSnapshot->as_next;
817 
819 
821 
822  if (ActiveSnapshot->as_snap->active_count == 0 &&
825 
827  ActiveSnapshot = newstack;
828  if (ActiveSnapshot == NULL)
830 
832 }
Snapshot as_snap
Definition: snapmgr.c:182
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:715
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
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:676
uint32 active_count
Definition: snapshot.h:107
void PushActiveSnapshot ( Snapshot  snap)

Definition at line 733 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(), LogicalRepSyncTableStart(), ParallelWorkerMain(), PersistHoldablePortal(), PortalRunSelect(), PortalRunUtility(), PortalStart(), PushCopiedSnapshot(), ReindexMultipleTables(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RevalidateCachedQuery(), ShutdownSQLFunction(), vacuum(), vacuum_rel(), and wait_for_relation_state_change().

734 {
735  ActiveSnapshotElt *newactive;
736 
737  Assert(snap != InvalidSnapshot);
738 
740 
741  /*
742  * Checking SecondarySnapshot is probably useless here, but it seems
743  * better to be sure.
744  */
745  if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
746  newactive->as_snap = CopySnapshot(snap);
747  else
748  newactive->as_snap = snap;
749 
750  newactive->as_next = ActiveSnapshot;
752 
753  newactive->as_snap->active_count++;
754 
755  ActiveSnapshot = newactive;
756  if (OldestActiveSnapshot == NULL)
758 }
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:660
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:761
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
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 769 of file snapmgr.c.

References CopySnapshot(), and PushActiveSnapshot().

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

770 {
771  PushActiveSnapshot(CopySnapshot(snapshot));
772 }
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:733
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:660
Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

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

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

2122 {
2123  SerializedSnapshotData serialized_snapshot;
2124  Size size;
2125  Snapshot snapshot;
2126  TransactionId *serialized_xids;
2127 
2128  memcpy(&serialized_snapshot, start_address,
2129  sizeof(SerializedSnapshotData));
2130  serialized_xids = (TransactionId *)
2131  (start_address + sizeof(SerializedSnapshotData));
2132 
2133  /* We allocate any XID arrays needed in the same palloc block. */
2134  size = sizeof(SnapshotData)
2135  + serialized_snapshot.xcnt * sizeof(TransactionId)
2136  + serialized_snapshot.subxcnt * sizeof(TransactionId);
2137 
2138  /* Copy all required fields */
2140  snapshot->satisfies = HeapTupleSatisfiesMVCC;
2141  snapshot->xmin = serialized_snapshot.xmin;
2142  snapshot->xmax = serialized_snapshot.xmax;
2143  snapshot->xip = NULL;
2144  snapshot->xcnt = serialized_snapshot.xcnt;
2145  snapshot->subxip = NULL;
2146  snapshot->subxcnt = serialized_snapshot.subxcnt;
2147  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
2148  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
2149  snapshot->curcid = serialized_snapshot.curcid;
2150  snapshot->whenTaken = serialized_snapshot.whenTaken;
2151  snapshot->lsn = serialized_snapshot.lsn;
2152 
2153  /* Copy XIDs, if present. */
2154  if (serialized_snapshot.xcnt > 0)
2155  {
2156  snapshot->xip = (TransactionId *) (snapshot + 1);
2157  memcpy(snapshot->xip, serialized_xids,
2158  serialized_snapshot.xcnt * sizeof(TransactionId));
2159  }
2160 
2161  /* Copy SubXIDs, if present. */
2162  if (serialized_snapshot.subxcnt > 0)
2163  {
2164  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2165  serialized_snapshot.xcnt;
2166  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
2167  serialized_snapshot.subxcnt * sizeof(TransactionId));
2168  }
2169 
2170  /* Set the copied flag so that the caller will set refcounts correctly. */
2171  snapshot->regd_count = 0;
2172  snapshot->active_count = 0;
2173  snapshot->copied = true;
2174 
2175  return snapshot;
2176 }
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:246
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:240
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:239
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 2185 of file snapmgr.c.

References InvalidPid, NULL, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

2186 {
2187  SetTransactionSnapshot(snapshot, NULL, InvalidPid, master_pgproc);
2188 }
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:565
#define NULL
Definition: c.h:229
#define InvalidPid
Definition: miscadmin.h:31
void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

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

2063 {
2064  SerializedSnapshotData serialized_snapshot;
2065 
2066  Assert(snapshot->subxcnt >= 0);
2067 
2068  /* Copy all required fields */
2069  serialized_snapshot.xmin = snapshot->xmin;
2070  serialized_snapshot.xmax = snapshot->xmax;
2071  serialized_snapshot.xcnt = snapshot->xcnt;
2072  serialized_snapshot.subxcnt = snapshot->subxcnt;
2073  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2074  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2075  serialized_snapshot.curcid = snapshot->curcid;
2076  serialized_snapshot.whenTaken = snapshot->whenTaken;
2077  serialized_snapshot.lsn = snapshot->lsn;
2078 
2079  /*
2080  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2081  * taken during recovery - in that case, top-level XIDs are in subxip as
2082  * well, and we mustn't lose them.
2083  */
2084  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
2085  serialized_snapshot.subxcnt = 0;
2086 
2087  /* Copy struct to possibly-unaligned buffer */
2088  memcpy(start_address,
2089  &serialized_snapshot, sizeof(SerializedSnapshotData));
2090 
2091  /* Copy XID array */
2092  if (snapshot->xcnt > 0)
2093  memcpy((TransactionId *) (start_address +
2094  sizeof(SerializedSnapshotData)),
2095  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2096 
2097  /*
2098  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2099  * though, because it's not used anywhere in that case. Except if it's a
2100  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2101  * well in that case, so we mustn't lose them.
2102  */
2103  if (serialized_snapshot.subxcnt > 0)
2104  {
2105  Size subxipoff = sizeof(SerializedSnapshotData) +
2106  snapshot->xcnt * sizeof(TransactionId);
2107 
2108  memcpy((TransactionId *) (start_address + subxipoff),
2109  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2110  }
2111 }
uint32 TransactionId
Definition: c.h:397
XLogRecPtr lsn
Definition: snapshot.h:112
TimestampTz whenTaken
Definition: snapmgr.c:246
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:240
CommandId curcid
Definition: snapshot.h:96
#define Assert(condition)
Definition: c.h:676
bool takenDuringRecovery
Definition: snapshot.h:93
size_t Size
Definition: c.h:356
uint32 xcnt
Definition: snapshot.h:78
TransactionId xmin
Definition: snapmgr.c:239
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 1717 of file snapmgr.c.

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

Referenced by TransactionIdLimitedForOldSnapshots().

1718 {
1723 }
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,
VirtualTransactionId sourcevxid,
int  sourcepid,
PGPROC sourceproc 
)
static

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

567 {
568  /* Caller should have checked this already */
570 
571  /* Better do this to ensure following Assert succeeds. */
573 
577 
578  /*
579  * Even though we are not going to use the snapshot it computes, we must
580  * call GetSnapshotData, for two reasons: (1) to be sure that
581  * CurrentSnapshotData's XID arrays have been allocated, and (2) to update
582  * RecentXmin and RecentGlobalXmin. (We could alternatively include those
583  * two variables in exported snapshot files, but it seems better to have
584  * snapshot importers compute reasonably up-to-date values for them.)
585  */
587 
588  /*
589  * Now copy appropriate fields from the source snapshot.
590  */
591  CurrentSnapshot->xmin = sourcesnap->xmin;
592  CurrentSnapshot->xmax = sourcesnap->xmax;
593  CurrentSnapshot->xcnt = sourcesnap->xcnt;
594  Assert(sourcesnap->xcnt <= GetMaxSnapshotXidCount());
595  memcpy(CurrentSnapshot->xip, sourcesnap->xip,
596  sourcesnap->xcnt * sizeof(TransactionId));
597  CurrentSnapshot->subxcnt = sourcesnap->subxcnt;
598  Assert(sourcesnap->subxcnt <= GetMaxSnapshotSubxidCount());
599  memcpy(CurrentSnapshot->subxip, sourcesnap->subxip,
600  sourcesnap->subxcnt * sizeof(TransactionId));
603  /* NB: curcid should NOT be copied, it's a local matter */
604 
605  /*
606  * Now we have to fix what GetSnapshotData did with MyPgXact->xmin and
607  * TransactionXmin. There is a race condition: to make sure we are not
608  * causing the global xmin to go backwards, we have to test that the
609  * source transaction is still running, and that has to be done
610  * atomically. So let procarray.c do it.
611  *
612  * Note: in serializable mode, predicate.c will do this a second time. It
613  * doesn't seem worth contorting the logic here to avoid two calls,
614  * especially since it's not clear that predicate.c *must* do this.
615  */
616  if (sourceproc != NULL)
617  {
619  ereport(ERROR,
620  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
621  errmsg("could not import the requested snapshot"),
622  errdetail("The source transaction is not running anymore.")));
623  }
624  else if (!ProcArrayInstallImportedXmin(CurrentSnapshot->xmin, sourcevxid))
625  ereport(ERROR,
626  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
627  errmsg("could not import the requested snapshot"),
628  errdetail("The source process with pid %d is not running anymore.",
629  sourcepid)));
630 
631  /*
632  * In transaction-snapshot mode, the first snapshot must live until end of
633  * xact, so we must make a copy of it. Furthermore, if we're running in
634  * serializable mode, predicate.c needs to do its own processing.
635  */
637  {
640  sourcepid);
641  /* Make a saved copy */
644  /* Mark it as "registered" in FirstXactSnapshot */
647  }
648 
649  FirstSnapshotSet = true;
650 }
void SetSerializableTransactionSnapshot(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1674
uint32 TransactionId
Definition: c.h:397
#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:510
TransactionId * xip
Definition: snapshot.h:77
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:660
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1456
pairingheap_node ph_node
Definition: snapshot.h:109
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
bool takenDuringRecovery
Definition: snapshot.h:93
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1509
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
Definition: procarray.c:1872
uint32 xcnt
Definition: snapshot.h:78
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2018
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1467
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
Definition: procarray.c:1797
TransactionId * subxip
Definition: snapshot.h:89
int32 subxcnt
Definition: snapshot.h:90
void SetupHistoricSnapshot ( Snapshot  historic_snapshot,
HTAB tuplecids 
)

Definition at line 1995 of file snapmgr.c.

References Assert, and NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

1996 {
1997  Assert(historic_snapshot != NULL);
1998 
1999  /* setup the timetravel snapshot */
2000  HistoricSnapshot = historic_snapshot;
2001 
2002  /* setup (cmin, cmax) lookup hash */
2003  tuplecid_data = tuplecids;
2004 }
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:676
void SnapMgrInit ( void  )

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

268 {
269  bool found;
270 
271  /*
272  * Create or attach to the OldSnapshotControlData structure.
273  */
275  ShmemInitStruct("OldSnapshotControlData",
276  SnapMgrShmemSize(), &found);
277 
278  if (!found)
279  {
291  }
292 }
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:88
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:87
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:86
TimestampTz head_timestamp
Definition: snapmgr.c:124
Size SnapMgrShmemSize(void)
Definition: snapmgr.c:251
Size SnapMgrShmemSize ( void  )

Definition at line 251 of file snapmgr.c.

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

Referenced by CreateSharedMemoryAndSemaphores(), and SnapMgrInit().

252 {
253  Size size;
254 
255  size = offsetof(OldSnapshotControlData, xid_by_minute);
256  if (old_snapshot_threshold > 0)
257  size = add_size(size, mul_size(sizeof(TransactionId),
259 
260  return size;
261 }
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:75
#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 978 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().

979 {
980  Snapshot minSnapshot;
981 
982  if (ActiveSnapshot != NULL)
983  return;
984 
986  {
988  return;
989  }
990 
991  minSnapshot = pairingheap_container(SnapshotData, ph_node,
993 
994  if (TransactionIdPrecedes(MyPgXact->xmin, minSnapshot->xmin))
995  MyPgXact->xmin = minSnapshot->xmin;
996 }
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 544 of file snapmgr.c.

References SnapshotData::curcid, and FirstSnapshotSet.

Referenced by CommandCounterIncrement().

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

References NULL.

Referenced by ReorderBufferCommit(), and ReorderBufferQueueMessage().

2012 {
2014  tuplecid_data = NULL;
2015 }
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 1649 of file snapmgr.c.

References pairingheap_is_empty, and pairingheap_is_singular.

Referenced by CopyFrom().

1650 {
1653  return true;
1654 
1655  return false;
1656 }
#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 1735 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().

1737 {
1738  if (TransactionIdIsNormal(recentXmin)
1739  && old_snapshot_threshold >= 0
1740  && RelationAllowsEarlyPruning(relation))
1741  {
1743  TransactionId xlimit = recentXmin;
1744  TransactionId latest_xmin;
1745  TimestampTz update_ts;
1746  bool same_ts_as_threshold = false;
1747 
1749  latest_xmin = oldSnapshotControl->latest_xmin;
1750  update_ts = oldSnapshotControl->next_map_update;
1752 
1753  /*
1754  * Zero threshold always overrides to latest xmin, if valid. Without
1755  * some heuristic it will find its own snapshot too old on, for
1756  * example, a simple UPDATE -- which would make it useless for most
1757  * testing, but there is no principled way to ensure that it doesn't
1758  * fail in this way. Use a five-second delay to try to get useful
1759  * testing behavior, but this may need adjustment.
1760  */
1761  if (old_snapshot_threshold == 0)
1762  {
1763  if (TransactionIdPrecedes(latest_xmin, MyPgXact->xmin)
1764  && TransactionIdFollows(latest_xmin, xlimit))
1765  xlimit = latest_xmin;
1766 
1767  ts -= 5 * USECS_PER_SEC;
1769 
1770  return xlimit;
1771  }
1772 
1775 
1776  /* Check for fast exit without LW locking. */
1779  {
1781  same_ts_as_threshold = true;
1782  }
1784 
1785  if (!same_ts_as_threshold)
1786  {
1787  if (ts == update_ts)
1788  {
1789  xlimit = latest_xmin;
1790  if (NormalTransactionIdFollows(xlimit, recentXmin))
1792  }
1793  else
1794  {
1795  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1796 
1799  {
1800  int offset;
1801 
1802  offset = ((ts - oldSnapshotControl->head_timestamp)
1803  / USECS_PER_MINUTE);
1804  if (offset > oldSnapshotControl->count_used - 1)
1805  offset = oldSnapshotControl->count_used - 1;
1806  offset = (oldSnapshotControl->head_offset + offset)
1808  xlimit = oldSnapshotControl->xid_by_minute[offset];
1809 
1810  if (NormalTransactionIdFollows(xlimit, recentXmin))
1812  }
1813 
1814  LWLockRelease(OldSnapshotTimeMapLock);
1815  }
1816  }
1817 
1818  /*
1819  * Failsafe protection against vacuuming work of active transaction.
1820  *
1821  * This is not an assertion because we avoid the spinlock for
1822  * performance, leaving open the possibility that xlimit could advance
1823  * and be more current; but it seems prudent to apply this limit. It
1824  * might make pruning a tiny bit less aggressive than it could be, but
1825  * protects against data loss bugs.
1826  */
1827  if (TransactionIdIsNormal(latest_xmin)
1828  && TransactionIdPrecedes(latest_xmin, xlimit))
1829  xlimit = latest_xmin;
1830 
1831  if (NormalTransactionIdFollows(xlimit, recentXmin))
1832  return xlimit;
1833  }
1834 
1835  return recentXmin;
1836 }
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:1680
slock_t mutex_latest_xmin
Definition: snapmgr.c:88
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:1717
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:1666
int old_snapshot_threshold
Definition: snapmgr.c:75
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 918 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().

919 {
920  if (snapshot == NULL)
921  return;
922 
923  Assert(snapshot->regd_count > 0);
925 
926  ResourceOwnerForgetSnapshot(owner, snapshot);
927 
928  snapshot->regd_count--;
929  if (snapshot->regd_count == 0)
931 
932  if (snapshot->regd_count == 0 && snapshot->active_count == 0)
933  {
934  FreeSnapshot(snapshot);
936  }
937 }
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:715
static void SnapshotResetXmin(void)
Definition: snapmgr.c:978
#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:676
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 781 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().

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

References NIL.

Referenced by PrepareTransaction().

1604 {
1605  return (exportedSnapshots != NIL);
1606 }
#define NIL
Definition: pg_list.h:69
static List * exportedSnapshots
Definition: snapmgr.c:223
static int xmin_cmp ( const pairingheap_node a,
const pairingheap_node b,
void *  arg 
)
static

Definition at line 944 of file snapmgr.c.

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

945 {
946  const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
947  const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
948 
949  if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
950  return 1;
951  else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
952  return -1;
953  else
954  return 0;
955 }
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 223 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().