PostgreSQL Source Code git master
snapmgr.c File Reference
#include "postgres.h"
#include <sys/stat.h>
#include <unistd.h>
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/xact.h"
#include "datatype/timestamp.h"
#include "lib/pairingheap.h"
#include "miscadmin.h"
#include "port/pg_lfind.h"
#include "storage/fd.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/builtins.h"
#include "utils/injection_point.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for snapmgr.c:

Go to the source code of this file.

Data Structures

struct  ActiveSnapshotElt
 
struct  ExportedSnapshot
 
struct  SerializedSnapshotData
 

Macros

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"
 

Typedefs

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 Snapshot CopySnapshot (Snapshot snapshot)
 
static void UnregisterSnapshotNoOwner (Snapshot snapshot)
 
static void FreeSnapshot (Snapshot snapshot)
 
static void SnapshotResetXmin (void)
 
static void ResOwnerReleaseSnapshot (Datum res)
 
static void ResourceOwnerRememberSnapshot (ResourceOwner owner, Snapshot snap)
 
static void ResourceOwnerForgetSnapshot (ResourceOwner owner, Snapshot snap)
 
Snapshot GetTransactionSnapshot (void)
 
Snapshot GetLatestSnapshot (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 snapshot)
 
void PushActiveSnapshotWithLevel (Snapshot snapshot, int snap_level)
 
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)
 
bool HaveRegisteredOrActiveSnapshot (void)
 
void SetupHistoricSnapshot (Snapshot historic_snapshot, HTAB *tuplecids)
 
void TeardownHistoricSnapshot (bool is_error)
 
bool HistoricSnapshotActive (void)
 
HTABHistoricSnapshotGetTupleCids (void)
 
Size EstimateSnapshotSpace (Snapshot snapshot)
 
void SerializeSnapshot (Snapshot snapshot, char *start_address)
 
Snapshot RestoreSnapshot (char *start_address)
 
void RestoreTransactionSnapshot (Snapshot snapshot, void *source_pgproc)
 
bool XidInMVCCSnapshot (TransactionId xid, Snapshot snapshot)
 

Variables

static SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC}
 
static SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC}
 
static SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC}
 
SnapshotData SnapshotSelfData = {SNAPSHOT_SELF}
 
SnapshotData SnapshotAnyData = {SNAPSHOT_ANY}
 
SnapshotData SnapshotToastData = {SNAPSHOT_TOAST}
 
static Snapshot CurrentSnapshot = NULL
 
static Snapshot SecondarySnapshot = NULL
 
static Snapshot CatalogSnapshot = NULL
 
static Snapshot HistoricSnapshot = NULL
 
TransactionId TransactionXmin = FirstNormalTransactionId
 
TransactionId RecentXmin = FirstNormalTransactionId
 
static HTABtuplecid_data = NULL
 
static ActiveSnapshotEltActiveSnapshot = NULL
 
static pairingheap RegisteredSnapshots = {&xmin_cmp, NULL, NULL}
 
bool FirstSnapshotSet = false
 
static Snapshot FirstXactSnapshot = NULL
 
static ListexportedSnapshots = NIL
 
static const ResourceOwnerDesc snapshot_resowner_desc
 

Macro Definition Documentation

◆ SNAPSHOT_EXPORT_DIR

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"

Definition at line 203 of file snapmgr.c.

Typedef Documentation

◆ ActiveSnapshotElt

◆ ExportedSnapshot

◆ SerializedSnapshotData

Function Documentation

◆ ActiveSnapshotSet()

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1016 of file snapmgr.c.

1017{
1018 /*
1019 * In transaction-snapshot mode we must release our privately-managed
1020 * reference to the transaction snapshot. We must remove it from
1021 * RegisteredSnapshots to keep the check below happy. But we don't bother
1022 * to do FreeSnapshot, for two reasons: the memory will go away with
1023 * TopTransactionContext anyway, and if someone has left the snapshot
1024 * stacked as active, we don't want the code below to be chasing through a
1025 * dangling pointer.
1026 */
1027 if (FirstXactSnapshot != NULL)
1028 {
1032 }
1033 FirstXactSnapshot = NULL;
1034
1035 /*
1036 * If we exported any snapshots, clean them up.
1037 */
1038 if (exportedSnapshots != NIL)
1039 {
1040 ListCell *lc;
1041
1042 /*
1043 * Get rid of the files. Unlink failure is only a WARNING because (1)
1044 * it's too late to abort the transaction, and (2) leaving a leaked
1045 * file around has little real consequence anyway.
1046 *
1047 * We also need to remove the snapshots from RegisteredSnapshots to
1048 * prevent a warning below.
1049 *
1050 * As with the FirstXactSnapshot, we don't need to free resources of
1051 * the snapshot itself as it will go away with the memory context.
1052 */
1053 foreach(lc, exportedSnapshots)
1054 {
1055 ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1056
1057 if (unlink(esnap->snapfile))
1058 elog(WARNING, "could not unlink file \"%s\": %m",
1059 esnap->snapfile);
1060
1062 &esnap->snapshot->ph_node);
1063 }
1064
1066 }
1067
1068 /* Drop catalog snapshot if any */
1070
1071 /* On commit, complain about leftover snapshots */
1072 if (isCommit)
1073 {
1074 ActiveSnapshotElt *active;
1075
1077 elog(WARNING, "registered snapshots seem to remain after cleanup");
1078
1079 /* complain about unpopped active snapshots */
1080 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1081 elog(WARNING, "snapshot %p still active", active);
1082 }
1083
1084 /*
1085 * And reset our state. We don't need to free the memory explicitly --
1086 * it'll go away with TopTransactionContext.
1087 */
1088 ActiveSnapshot = NULL;
1090
1091 CurrentSnapshot = NULL;
1092 SecondarySnapshot = NULL;
1093
1094 FirstSnapshotSet = false;
1095
1096 /*
1097 * During normal commit processing, we call ProcArrayEndTransaction() to
1098 * reset the MyProc->xmin. That call happens prior to the call to
1099 * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1100 */
1101 if (resetXmin)
1103
1104 Assert(resetXmin || MyProc->xmin == 0);
1105}
#define WARNING
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:226
Assert(PointerIsAligned(start, uint64))
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:184
#define pairingheap_is_empty(h)
Definition: pairingheap.h:99
#define pairingheap_reset(h)
Definition: pairingheap.h:96
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:200
static Snapshot CurrentSnapshot
Definition: snapmgr.c:149
static Snapshot SecondarySnapshot
Definition: snapmgr.c:150
static List * exportedSnapshots
Definition: snapmgr.c:213
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:190
bool FirstSnapshotSet
Definition: snapmgr.c:193
static void SnapshotResetXmin(void)
Definition: snapmgr.c:937
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:455
PGPROC * MyProc
Definition: proc.c:67
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:177
char * snapfile
Definition: snapmgr.c:208
Snapshot snapshot
Definition: snapmgr.c:209
TransactionId xmin
Definition: proc.h:194
uint32 regd_count
Definition: snapshot.h:201
pairingheap_node ph_node
Definition: snapshot.h:202

References ActiveSnapshot, ActiveSnapshotElt::as_next, Assert(), CurrentSnapshot, elog, exportedSnapshots, FirstSnapshotSet, FirstXactSnapshot, InvalidateCatalogSnapshot(), lfirst, MyProc, NIL, pairingheap_is_empty, pairingheap_remove(), pairingheap_reset, SnapshotData::ph_node, SnapshotData::regd_count, RegisteredSnapshots, SecondarySnapshot, ExportedSnapshot::snapfile, ExportedSnapshot::snapshot, SnapshotResetXmin(), WARNING, and PGPROC::xmin.

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

◆ AtSubAbort_Snapshot()

void AtSubAbort_Snapshot ( int  level)

Definition at line 982 of file snapmgr.c.

983{
984 /* Forget the active snapshots set by this subtransaction */
985 while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
986 {
988
990
991 /*
992 * Decrement the snapshot's active count. If it's still registered or
993 * marked as active by an outer subtransaction, we can't free it yet.
994 */
997
1001
1002 /* and free the stack element */
1004
1006 }
1007
1009}
static int32 next
Definition: blutils.c:224
void pfree(void *pointer)
Definition: mcxt.c:1594
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:664
Snapshot as_snap
Definition: snapmgr.c:175
uint32 active_count
Definition: snapshot.h:200

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

Referenced by AbortSubTransaction().

◆ AtSubCommit_Snapshot()

void AtSubCommit_Snapshot ( int  level)

Definition at line 961 of file snapmgr.c.

962{
963 ActiveSnapshotElt *active;
964
965 /*
966 * Relabel the active snapshots set in this subtransaction as though they
967 * are owned by the parent subxact.
968 */
969 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
970 {
971 if (active->as_level < level)
972 break;
973 active->as_level = level - 1;
974 }
975}

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

Referenced by CommitSubTransaction().

◆ CopySnapshot()

static Snapshot CopySnapshot ( Snapshot  snapshot)
static

Definition at line 608 of file snapmgr.c.

609{
610 Snapshot newsnap;
611 Size subxipoff;
612 Size size;
613
614 Assert(snapshot != InvalidSnapshot);
615
616 /* We allocate any XID arrays needed in the same palloc block. */
617 size = subxipoff = sizeof(SnapshotData) +
618 snapshot->xcnt * sizeof(TransactionId);
619 if (snapshot->subxcnt > 0)
620 size += snapshot->subxcnt * sizeof(TransactionId);
621
623 memcpy(newsnap, snapshot, sizeof(SnapshotData));
624
625 newsnap->regd_count = 0;
626 newsnap->active_count = 0;
627 newsnap->copied = true;
628 newsnap->snapXactCompletionCount = 0;
629
630 /* setup XID array */
631 if (snapshot->xcnt > 0)
632 {
633 newsnap->xip = (TransactionId *) (newsnap + 1);
634 memcpy(newsnap->xip, snapshot->xip,
635 snapshot->xcnt * sizeof(TransactionId));
636 }
637 else
638 newsnap->xip = NULL;
639
640 /*
641 * Setup subXID array. Don't bother to copy it if it had overflowed,
642 * though, because it's not used anywhere in that case. Except if it's a
643 * snapshot taken during recovery; all the top-level XIDs are in subxip as
644 * well in that case, so we mustn't lose them.
645 */
646 if (snapshot->subxcnt > 0 &&
647 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
648 {
649 newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
650 memcpy(newsnap->subxip, snapshot->subxip,
651 snapshot->subxcnt * sizeof(TransactionId));
652 }
653 else
654 newsnap->subxip = NULL;
655
656 return newsnap;
657}
uint32 TransactionId
Definition: c.h:660
size_t Size
Definition: c.h:613
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
MemoryContext TopTransactionContext
Definition: mcxt.c:171
struct SnapshotData * Snapshot
Definition: snapshot.h:117
struct SnapshotData SnapshotData
#define InvalidSnapshot
Definition: snapshot.h:119
int32 subxcnt
Definition: snapshot.h:177
bool copied
Definition: snapshot.h:181
uint32 xcnt
Definition: snapshot.h:165
TransactionId * subxip
Definition: snapshot.h:176
uint64 snapXactCompletionCount
Definition: snapshot.h:209
TransactionId * xip
Definition: snapshot.h:164
bool suboverflowed
Definition: snapshot.h:178
bool takenDuringRecovery
Definition: snapshot.h:180

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

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

◆ DeleteAllExportedSnapshotFiles()

void DeleteAllExportedSnapshotFiles ( void  )

Definition at line 1587 of file snapmgr.c.

1588{
1589 char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1590 DIR *s_dir;
1591 struct dirent *s_de;
1592
1593 /*
1594 * Problems in reading the directory, or unlinking files, are reported at
1595 * LOG level. Since we're running in the startup process, ERROR level
1596 * would prevent database start, and it's not important enough for that.
1597 */
1599
1600 while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1601 {
1602 if (strcmp(s_de->d_name, ".") == 0 ||
1603 strcmp(s_de->d_name, "..") == 0)
1604 continue;
1605
1606 snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1607
1608 if (unlink(buf) != 0)
1609 ereport(LOG,
1611 errmsg("could not remove file \"%s\": %m", buf)));
1612 }
1613
1614 FreeDir(s_dir);
1615}
int errcode_for_file_access(void)
Definition: elog.c:886
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:150
int FreeDir(DIR *dir)
Definition: fd.c:3022
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2985
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2904
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:260
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:203
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

References AllocateDir(), buf, dirent::d_name, ereport, errcode_for_file_access(), errmsg(), FreeDir(), LOG, MAXPGPATH, ReadDirExtended(), SNAPSHOT_EXPORT_DIR, and snprintf.

Referenced by StartupXLOG().

◆ EstimateSnapshotSpace()

Size EstimateSnapshotSpace ( Snapshot  snapshot)

Definition at line 1712 of file snapmgr.c.

1713{
1714 Size size;
1715
1716 Assert(snapshot != InvalidSnapshot);
1717 Assert(snapshot->snapshot_type == SNAPSHOT_MVCC);
1718
1719 /* We allocate any XID arrays needed in the same palloc block. */
1720 size = add_size(sizeof(SerializedSnapshotData),
1721 mul_size(snapshot->xcnt, sizeof(TransactionId)));
1722 if (snapshot->subxcnt > 0 &&
1723 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
1724 size = add_size(size,
1725 mul_size(snapshot->subxcnt, sizeof(TransactionId)));
1726
1727 return size;
1728}
Size add_size(Size s1, Size s2)
Definition: shmem.c:495
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
@ SNAPSHOT_MVCC
Definition: snapshot.h:46
SnapshotType snapshot_type
Definition: snapshot.h:140

References add_size(), Assert(), InvalidSnapshot, mul_size(), SNAPSHOT_MVCC, SnapshotData::snapshot_type, SnapshotData::suboverflowed, SnapshotData::subxcnt, SnapshotData::takenDuringRecovery, and SnapshotData::xcnt.

Referenced by index_parallelscan_estimate(), index_parallelscan_initialize(), InitializeParallelDSM(), and table_parallelscan_estimate().

◆ ExportSnapshot()

char * ExportSnapshot ( Snapshot  snapshot)

Definition at line 1115 of file snapmgr.c.

1116{
1117 TransactionId topXid;
1118 TransactionId *children;
1119 ExportedSnapshot *esnap;
1120 int nchildren;
1121 int addTopXid;
1123 FILE *f;
1124 int i;
1125 MemoryContext oldcxt;
1126 char path[MAXPGPATH];
1127 char pathtmp[MAXPGPATH];
1128
1129 /*
1130 * It's tempting to call RequireTransactionBlock here, since it's not very
1131 * useful to export a snapshot that will disappear immediately afterwards.
1132 * However, we haven't got enough information to do that, since we don't
1133 * know if we're at top level or not. For example, we could be inside a
1134 * plpgsql function that is going to fire off other transactions via
1135 * dblink. Rather than disallow perfectly legitimate usages, don't make a
1136 * check.
1137 *
1138 * Also note that we don't make any restriction on the transaction's
1139 * isolation level; however, importers must check the level if they are
1140 * serializable.
1141 */
1142
1143 /*
1144 * Get our transaction ID if there is one, to include in the snapshot.
1145 */
1146 topXid = GetTopTransactionIdIfAny();
1147
1148 /*
1149 * We cannot export a snapshot from a subtransaction because there's no
1150 * easy way for importers to verify that the same subtransaction is still
1151 * running.
1152 */
1153 if (IsSubTransaction())
1154 ereport(ERROR,
1155 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1156 errmsg("cannot export a snapshot from a subtransaction")));
1157
1158 /*
1159 * We do however allow previous committed subtransactions to exist.
1160 * Importers of the snapshot must see them as still running, so get their
1161 * XIDs to add them to the snapshot.
1162 */
1163 nchildren = xactGetCommittedChildren(&children);
1164
1165 /*
1166 * Generate file path for the snapshot. We start numbering of snapshots
1167 * inside the transaction from 1.
1168 */
1169 snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%08X-%d",
1172
1173 /*
1174 * Copy the snapshot into TopTransactionContext, add it to the
1175 * exportedSnapshots list, and mark it pseudo-registered. We do this to
1176 * ensure that the snapshot's xmin is honored for the rest of the
1177 * transaction.
1178 */
1179 snapshot = CopySnapshot(snapshot);
1180
1182 esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
1183 esnap->snapfile = pstrdup(path);
1184 esnap->snapshot = snapshot;
1186 MemoryContextSwitchTo(oldcxt);
1187
1188 snapshot->regd_count++;
1190
1191 /*
1192 * Fill buf with a text serialization of the snapshot, plus identification
1193 * data about this transaction. The format expected by ImportSnapshot is
1194 * pretty rigid: each line must be fieldname:value.
1195 */
1197
1198 appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->vxid.procNumber, MyProc->vxid.lxid);
1199 appendStringInfo(&buf, "pid:%d\n", MyProcPid);
1200 appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1201 appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1202 appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1203
1204 appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1205 appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1206
1207 /*
1208 * We must include our own top transaction ID in the top-xid data, since
1209 * by definition we will still be running when the importing transaction
1210 * adopts the snapshot, but GetSnapshotData never includes our own XID in
1211 * the snapshot. (There must, therefore, be enough room to add it.)
1212 *
1213 * However, it could be that our topXid is after the xmax, in which case
1214 * we shouldn't include it because xip[] members are expected to be before
1215 * xmax. (We need not make the same check for subxip[] members, see
1216 * snapshot.h.)
1217 */
1218 addTopXid = (TransactionIdIsValid(topXid) &&
1219 TransactionIdPrecedes(topXid, snapshot->xmax)) ? 1 : 0;
1220 appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1221 for (i = 0; i < snapshot->xcnt; i++)
1222 appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1223 if (addTopXid)
1224 appendStringInfo(&buf, "xip:%u\n", topXid);
1225
1226 /*
1227 * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1228 * we have to cope with possible overflow.
1229 */
1230 if (snapshot->suboverflowed ||
1231 snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1232 appendStringInfoString(&buf, "sof:1\n");
1233 else
1234 {
1235 appendStringInfoString(&buf, "sof:0\n");
1236 appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1237 for (i = 0; i < snapshot->subxcnt; i++)
1238 appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1239 for (i = 0; i < nchildren; i++)
1240 appendStringInfo(&buf, "sxp:%u\n", children[i]);
1241 }
1242 appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1243
1244 /*
1245 * Now write the text representation into a file. We first write to a
1246 * ".tmp" filename, and rename to final filename if no error. This
1247 * ensures that no other backend can read an incomplete file
1248 * (ImportSnapshot won't allow it because of its valid-characters check).
1249 */
1250 snprintf(pathtmp, sizeof(pathtmp), "%s.tmp", path);
1251 if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1252 ereport(ERROR,
1254 errmsg("could not create file \"%s\": %m", pathtmp)));
1255
1256 if (fwrite(buf.data, buf.len, 1, f) != 1)
1257 ereport(ERROR,
1259 errmsg("could not write to file \"%s\": %m", pathtmp)));
1260
1261 /* no fsync() since file need not survive a system crash */
1262
1263 if (FreeFile(f))
1264 ereport(ERROR,
1266 errmsg("could not write to file \"%s\": %m", pathtmp)));
1267
1268 /*
1269 * Now that we have written everything into a .tmp file, rename the file
1270 * to remove the .tmp suffix.
1271 */
1272 if (rename(pathtmp, path) < 0)
1273 ereport(ERROR,
1275 errmsg("could not rename file \"%s\" to \"%s\": %m",
1276 pathtmp, path)));
1277
1278 /*
1279 * The basename of the file is what we return from pg_export_snapshot().
1280 * It's already in path in a textual format and we know that the path
1281 * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1282 * and pstrdup it so as not to return the address of a local variable.
1283 */
1284 return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1285}
#define PG_BINARY_W
Definition: c.h:1264
int errcode(int sqlerrcode)
Definition: elog.c:863
#define ERROR
Definition: elog.h:39
int FreeFile(FILE *file)
Definition: fd.c:2840
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2641
int MyProcPid
Definition: globals.c:47
Oid MyDatabaseId
Definition: globals.c:94
int i
Definition: isn.c:77
List * lappend(List *list, void *datum)
Definition: list.c:339
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void * palloc(Size size)
Definition: mcxt.c:1365
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:126
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static int list_length(const List *l)
Definition: pg_list.h:152
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:2028
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:608
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
LocalTransactionId lxid
Definition: proc.h:217
struct PGPROC::@130 vxid
ProcNumber procNumber
Definition: proc.h:212
TransactionId xmin
Definition: snapshot.h:153
TransactionId xmax
Definition: snapshot.h:154
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.h:263
bool XactReadOnly
Definition: xact.c:83
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:442
int XactIsoLevel
Definition: xact.c:80
bool IsSubTransaction(void)
Definition: xact.c:5062
int xactGetCommittedChildren(TransactionId **ptr)
Definition: xact.c:5808

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

Referenced by pg_export_snapshot(), and SnapBuildExportSnapshot().

◆ FreeSnapshot()

static void FreeSnapshot ( Snapshot  snapshot)
static

Definition at line 664 of file snapmgr.c.

665{
666 Assert(snapshot->regd_count == 0);
667 Assert(snapshot->active_count == 0);
668 Assert(snapshot->copied);
669
670 pfree(snapshot);
671}

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

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

◆ GetActiveSnapshot()

◆ GetCatalogSnapshot()

Snapshot GetCatalogSnapshot ( Oid  relid)

Definition at line 385 of file snapmgr.c.

386{
387 /*
388 * Return historic snapshot while we're doing logical decoding, so we can
389 * see the appropriate state of the catalog.
390 *
391 * This is the primary reason for needing to reset the system caches after
392 * finishing decoding.
393 */
395 return HistoricSnapshot;
396
397 return GetNonHistoricCatalogSnapshot(relid);
398}
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1692
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:407

References GetNonHistoricCatalogSnapshot(), HistoricSnapshot, and HistoricSnapshotActive().

Referenced by process_settings(), systable_beginscan(), systable_beginscan_ordered(), systable_recheck_tuple(), and table_beginscan_catalog().

◆ GetLatestSnapshot()

Snapshot GetLatestSnapshot ( void  )

Definition at line 354 of file snapmgr.c.

355{
356 /*
357 * We might be able to relax this, but nothing that could otherwise work
358 * needs it.
359 */
360 if (IsInParallelMode())
361 elog(ERROR,
362 "cannot update SecondarySnapshot during a parallel operation");
363
364 /*
365 * So far there are no cases requiring support for GetLatestSnapshot()
366 * during logical decoding, but it wouldn't be hard to add if required.
367 */
369
370 /* If first call in transaction, go ahead and set the xact snapshot */
371 if (!FirstSnapshotSet)
372 return GetTransactionSnapshot();
373
375
376 return SecondarySnapshot;
377}
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2123
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:272
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:142
bool IsInParallelMode(void)
Definition: xact.c:1090

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

Referenced by asyncQueueReadAllNotifications(), ATRewriteTable(), check_default_partition_contents(), currtid_internal(), FindConflictTuple(), IndexCheckExclusion(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RI_Initial_Check(), RI_PartitionRemove_Check(), ri_PerformCheck(), ScanSourceDatabasePgClass(), validateDomainCheckConstraint(), validateDomainNotNullConstraint(), and validateForeignKeyConstraint().

◆ GetNonHistoricCatalogSnapshot()

Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 407 of file snapmgr.c.

408{
409 /*
410 * If the caller is trying to scan a relation that has no syscache, no
411 * catcache invalidations will be sent when it is updated. For a few key
412 * relations, snapshot invalidations are sent instead. If we're trying to
413 * scan a relation for which neither catcache nor snapshot invalidations
414 * are sent, we must refresh the snapshot every time.
415 */
416 if (CatalogSnapshot &&
418 !RelationHasSysCache(relid))
420
421 if (CatalogSnapshot == NULL)
422 {
423 /* Get new snapshot. */
425
426 /*
427 * Make sure the catalog snapshot will be accounted for in decisions
428 * about advancing PGPROC->xmin. We could apply RegisterSnapshot, but
429 * that would result in making a physical copy, which is overkill; and
430 * it would also create a dependency on some resource owner, which we
431 * do not want for reasons explained at the head of this file. Instead
432 * just shove the CatalogSnapshot into the pairing heap manually. This
433 * has to be reversed in InvalidateCatalogSnapshot, of course.
434 *
435 * NB: it had better be impossible for this to throw error, since the
436 * CatalogSnapshot pointer is already valid.
437 */
439 }
440
441 return CatalogSnapshot;
442}
static SnapshotData CatalogSnapshotData
Definition: snapmgr.c:143
static Snapshot CatalogSnapshot
Definition: snapmgr.c:151
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:737
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:714

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

Referenced by GetCatalogSnapshot(), and ScanPgRelation().

◆ GetTransactionSnapshot()

Snapshot GetTransactionSnapshot ( void  )

Definition at line 272 of file snapmgr.c.

273{
274 /*
275 * Return historic snapshot if doing logical decoding.
276 *
277 * Historic snapshots are only usable for catalog access, not for
278 * general-purpose queries. The caller is responsible for ensuring that
279 * the snapshot is used correctly! (PostgreSQL code never calls this
280 * during logical decoding, but extensions can do it.)
281 */
283 {
284 /*
285 * We'll never need a non-historic transaction snapshot in this
286 * (sub-)transaction, so there's no need to be careful to set one up
287 * for later calls to GetTransactionSnapshot().
288 */
290 return HistoricSnapshot;
291 }
292
293 /* First call in transaction? */
294 if (!FirstSnapshotSet)
295 {
296 /*
297 * Don't allow catalog snapshot to be older than xact snapshot. Must
298 * do this first to allow the empty-heap Assert to succeed.
299 */
301
303 Assert(FirstXactSnapshot == NULL);
304
305 if (IsInParallelMode())
306 elog(ERROR,
307 "cannot take query snapshot during a parallel operation");
308
309 /*
310 * In transaction-snapshot mode, the first snapshot must live until
311 * end of xact regardless of what the caller does with it, so we must
312 * make a copy of it rather than returning CurrentSnapshotData
313 * directly. Furthermore, if we're running in serializable mode,
314 * predicate.c needs to wrap the snapshot fetch in its own processing.
315 */
317 {
318 /* First, create the snapshot in CurrentSnapshotData */
321 else
323 /* Make a saved copy */
326 /* Mark it as "registered" in FirstXactSnapshot */
329 }
330 else
332
333 FirstSnapshotSet = true;
334 return CurrentSnapshot;
335 }
336
338 return CurrentSnapshot;
339
340 /* Don't allow catalog snapshot to be older than xact snapshot. */
342
344
345 return CurrentSnapshot;
346}
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1682
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:141
#define IsolationUsesXactSnapshot()
Definition: xact.h:52
#define IsolationIsSerializable()
Definition: xact.h:53

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

Referenced by _brin_begin_parallel(), _bt_begin_parallel(), _gin_begin_parallel(), _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), ATExecDetachPartition(), begin_replication_step(), bt_check_every_level(), BuildCachedPlan(), CheckTargetForConflictsIn(), clear_subscription_skip_lsn(), cluster_multiple_rels(), DefineIndex(), DisableSubscriptionAndExit(), do_autovacuum(), EnsurePortalSnapshotExists(), EventTriggerOnLogin(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), execute_sql_string(), ExecuteCallStmt(), fmgr_sql(), GetLatestSnapshot(), HandleFunctionRequest(), heapam_index_build_range_scan(), index_drop(), initialize_worker_spi(), InitializeParallelDSM(), LogicalRepSyncTableStart(), pg_get_constraintdef_worker(), PortalRunMulti(), PortalRunUtility(), PortalStart(), PreCommit_on_commit_actions(), ReindexMultipleInternal(), ReindexRelationConcurrently(), RemoveTempRelationsCallback(), RevalidateCachedQuery(), ri_PerformCheck(), run_apply_worker(), SPI_cursor_open_internal(), update_retention_status(), vacuum(), vacuum_rel(), verify_heapam(), worker_spi_main(), and XidIsConcurrent().

◆ HaveRegisteredOrActiveSnapshot()

bool HaveRegisteredOrActiveSnapshot ( void  )

Definition at line 1644 of file snapmgr.c.

1645{
1646 if (ActiveSnapshot != NULL)
1647 return true;
1648
1649 /*
1650 * The catalog snapshot is in RegisteredSnapshots when valid, but can be
1651 * removed at any time due to invalidation processing. If explicitly
1652 * registered more than one snapshot has to be in RegisteredSnapshots.
1653 */
1654 if (CatalogSnapshot != NULL &&
1656 return false;
1657
1659}
#define pairingheap_is_singular(h)
Definition: pairingheap.h:102

References ActiveSnapshot, CatalogSnapshot, pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by AssertHasSnapshotForToast(), ExecWaitStmt(), get_toast_snapshot(), and SnapBuildInitialSnapshot().

◆ HistoricSnapshotActive()

◆ HistoricSnapshotGetTupleCids()

HTAB * HistoricSnapshotGetTupleCids ( void  )

Definition at line 1698 of file snapmgr.c.

1699{
1701 return tuplecid_data;
1702}
static HTAB * tuplecid_data
Definition: snapmgr.c:163

References Assert(), HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1387 of file snapmgr.c.

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

References AllocateFile(), elog, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, FirstSnapshotSet, FreeFile(), fstat, GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetTopTransactionIdIfAny(), i, InvalidTransactionId, IsolationIsSerializable, IsolationUsesXactSnapshot, IsSubTransaction(), MAXPGPATH, MyDatabaseId, OidIsValid, palloc(), parseIntFromText(), parseVxidFromText(), parseXidFromText(), PG_BINARY_R, SetTransactionSnapshot(), SNAPSHOT_EXPORT_DIR, SNAPSHOT_MVCC, SnapshotData::snapshot_type, snprintf, stat::st_size, 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().

◆ InvalidateCatalogSnapshot()

◆ InvalidateCatalogSnapshotConditionally()

void InvalidateCatalogSnapshotConditionally ( void  )

◆ parseIntFromText()

static int parseIntFromText ( const char *  prefix,
char **  s,
const char *  filename 
)
static

Definition at line 1307 of file snapmgr.c.

1308{
1309 char *ptr = *s;
1310 int prefixlen = strlen(prefix);
1311 int val;
1312
1313 if (strncmp(ptr, prefix, prefixlen) != 0)
1314 ereport(ERROR,
1315 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1316 errmsg("invalid snapshot data in file \"%s\"", filename)));
1317 ptr += prefixlen;
1318 if (sscanf(ptr, "%d", &val) != 1)
1319 ereport(ERROR,
1320 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1321 errmsg("invalid snapshot data in file \"%s\"", filename)));
1322 ptr = strchr(ptr, '\n');
1323 if (!ptr)
1324 ereport(ERROR,
1325 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1326 errmsg("invalid snapshot data in file \"%s\"", filename)));
1327 *s = ptr + 1;
1328 return val;
1329}
long val
Definition: informix.c:689
static char * filename
Definition: pg_dumpall.c:120

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

Referenced by ImportSnapshot().

◆ parseVxidFromText()

static void parseVxidFromText ( const char *  prefix,
char **  s,
const char *  filename,
VirtualTransactionId vxid 
)
static

Definition at line 1357 of file snapmgr.c.

1359{
1360 char *ptr = *s;
1361 int prefixlen = strlen(prefix);
1362
1363 if (strncmp(ptr, prefix, prefixlen) != 0)
1364 ereport(ERROR,
1365 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1366 errmsg("invalid snapshot data in file \"%s\"", filename)));
1367 ptr += prefixlen;
1368 if (sscanf(ptr, "%d/%u", &vxid->procNumber, &vxid->localTransactionId) != 2)
1369 ereport(ERROR,
1370 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1371 errmsg("invalid snapshot data in file \"%s\"", filename)));
1372 ptr = strchr(ptr, '\n');
1373 if (!ptr)
1374 ereport(ERROR,
1375 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1376 errmsg("invalid snapshot data in file \"%s\"", filename)));
1377 *s = ptr + 1;
1378}
LocalTransactionId localTransactionId
Definition: lock.h:64
ProcNumber procNumber
Definition: lock.h:63

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

Referenced by ImportSnapshot().

◆ parseXidFromText()

static TransactionId parseXidFromText ( const char *  prefix,
char **  s,
const char *  filename 
)
static

Definition at line 1332 of file snapmgr.c.

1333{
1334 char *ptr = *s;
1335 int prefixlen = strlen(prefix);
1337
1338 if (strncmp(ptr, prefix, prefixlen) != 0)
1339 ereport(ERROR,
1340 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1341 errmsg("invalid snapshot data in file \"%s\"", filename)));
1342 ptr += prefixlen;
1343 if (sscanf(ptr, "%u", &val) != 1)
1344 ereport(ERROR,
1345 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1346 errmsg("invalid snapshot data in file \"%s\"", filename)));
1347 ptr = strchr(ptr, '\n');
1348 if (!ptr)
1349 ereport(ERROR,
1350 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1351 errmsg("invalid snapshot data in file \"%s\"", filename)));
1352 *s = ptr + 1;
1353 return val;
1354}

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

Referenced by ImportSnapshot().

◆ pg_export_snapshot()

Datum pg_export_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 1292 of file snapmgr.c.

1293{
1294 char *snapshotName;
1295
1296 snapshotName = ExportSnapshot(GetActiveSnapshot());
1297 PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1298}
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1115
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:800
text * cstring_to_text(const char *s)
Definition: varlena.c:181

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

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 775 of file snapmgr.c.

776{
777 ActiveSnapshotElt *newstack;
778
779 newstack = ActiveSnapshot->as_next;
780
782
784
788
790 ActiveSnapshot = newstack;
791
793}

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

Referenced by _SPI_execute_plan(), AfterTriggerFireDeferred(), AfterTriggerSetState(), ATExecDetachPartition(), BuildCachedPlan(), clear_subscription_skip_lsn(), cluster_multiple_rels(), DefineIndex(), DisableSubscriptionAndExit(), do_autovacuum(), DoPortalRewind(), end_replication_step(), EndCopyTo(), EventTriggerOnLogin(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), ExecCreateTableAs(), execute_sql_string(), ExecuteCallStmt(), ExecWaitStmt(), ExplainOnePlan(), FindConflictTuple(), fmgr_sql(), ForgetPortalSnapshots(), HandleFunctionRequest(), index_drop(), initialize_worker_spi(), LogicalRepSyncTableStart(), movedb(), ParallelWorkerMain(), PersistHoldablePortal(), PortalRunMulti(), PortalRunSelect(), PortalRunUtility(), PortalStart(), PreCommit_on_commit_actions(), refresh_matview_datafill(), ReindexMultipleInternal(), ReindexRelationConcurrently(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), RemoveTempRelationsCallback(), RevalidateCachedQuery(), run_apply_worker(), ShutdownSQLFunction(), update_retention_status(), vacuum(), vacuum_rel(), and worker_spi_main().

◆ PushActiveSnapshot()

◆ PushActiveSnapshotWithLevel()

void PushActiveSnapshotWithLevel ( Snapshot  snapshot,
int  snap_level 
)

Definition at line 696 of file snapmgr.c.

697{
698 ActiveSnapshotElt *newactive;
699
700 Assert(snapshot != InvalidSnapshot);
701 Assert(ActiveSnapshot == NULL || snap_level >= ActiveSnapshot->as_level);
702
704
705 /*
706 * Checking SecondarySnapshot is probably useless here, but it seems
707 * better to be sure.
708 */
709 if (snapshot == CurrentSnapshot || snapshot == SecondarySnapshot ||
710 !snapshot->copied)
711 newactive->as_snap = CopySnapshot(snapshot);
712 else
713 newactive->as_snap = snapshot;
714
715 newactive->as_next = ActiveSnapshot;
716 newactive->as_level = snap_level;
717
718 newactive->as_snap->active_count++;
719
720 ActiveSnapshot = newactive;
721}

References SnapshotData::active_count, ActiveSnapshot, ActiveSnapshotElt::as_level, ActiveSnapshotElt::as_next, ActiveSnapshotElt::as_snap, Assert(), SnapshotData::copied, CopySnapshot(), CurrentSnapshot, InvalidSnapshot, MemoryContextAlloc(), SecondarySnapshot, and TopTransactionContext.

Referenced by EnsurePortalSnapshotExists(), PortalRunUtility(), and PushActiveSnapshot().

◆ PushCopiedSnapshot()

void PushCopiedSnapshot ( Snapshot  snapshot)

Definition at line 732 of file snapmgr.c.

733{
735}
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:682

References CopySnapshot(), and PushActiveSnapshot().

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

◆ RegisterSnapshot()

◆ RegisterSnapshotOnOwner()

Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 837 of file snapmgr.c.

838{
839 Snapshot snap;
840
841 if (snapshot == InvalidSnapshot)
842 return InvalidSnapshot;
843
844 /* Static snapshot? Create a persistent copy */
845 snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
846
847 /* and tell resowner.c about it */
849 snap->regd_count++;
851
852 if (snap->regd_count == 1)
854
855 return snap;
856}
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:449
static void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snap)
Definition: snapmgr.c:235

References SnapshotData::copied, CopySnapshot(), InvalidSnapshot, pairingheap_add(), SnapshotData::ph_node, SnapshotData::regd_count, RegisteredSnapshots, ResourceOwnerEnlarge(), and ResourceOwnerRememberSnapshot().

Referenced by be_lo_open(), and RegisterSnapshot().

◆ ResourceOwnerForgetSnapshot()

static void ResourceOwnerForgetSnapshot ( ResourceOwner  owner,
Snapshot  snap 
)
inlinestatic

Definition at line 240 of file snapmgr.c.

241{
243}
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:561
static const ResourceOwnerDesc snapshot_resowner_desc
Definition: snapmgr.c:224

References PointerGetDatum(), ResourceOwnerForget(), and snapshot_resowner_desc.

Referenced by UnregisterSnapshotFromOwner().

◆ ResourceOwnerRememberSnapshot()

static void ResourceOwnerRememberSnapshot ( ResourceOwner  owner,
Snapshot  snap 
)
inlinestatic

Definition at line 235 of file snapmgr.c.

236{
238}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:521

References PointerGetDatum(), ResourceOwnerRemember(), and snapshot_resowner_desc.

Referenced by RegisterSnapshotOnOwner().

◆ ResOwnerReleaseSnapshot()

static void ResOwnerReleaseSnapshot ( Datum  res)
static

Definition at line 1971 of file snapmgr.c.

1972{
1974}
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
static void UnregisterSnapshotNoOwner(Snapshot snapshot)
Definition: snapmgr.c:889

References DatumGetPointer(), and UnregisterSnapshotNoOwner().

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 1793 of file snapmgr.c.

1794{
1795 SerializedSnapshotData serialized_snapshot;
1796 Size size;
1797 Snapshot snapshot;
1798 TransactionId *serialized_xids;
1799
1800 memcpy(&serialized_snapshot, start_address,
1801 sizeof(SerializedSnapshotData));
1802 serialized_xids = (TransactionId *)
1803 (start_address + sizeof(SerializedSnapshotData));
1804
1805 /* We allocate any XID arrays needed in the same palloc block. */
1806 size = sizeof(SnapshotData)
1807 + serialized_snapshot.xcnt * sizeof(TransactionId)
1808 + serialized_snapshot.subxcnt * sizeof(TransactionId);
1809
1810 /* Copy all required fields */
1812 snapshot->snapshot_type = SNAPSHOT_MVCC;
1813 snapshot->xmin = serialized_snapshot.xmin;
1814 snapshot->xmax = serialized_snapshot.xmax;
1815 snapshot->xip = NULL;
1816 snapshot->xcnt = serialized_snapshot.xcnt;
1817 snapshot->subxip = NULL;
1818 snapshot->subxcnt = serialized_snapshot.subxcnt;
1819 snapshot->suboverflowed = serialized_snapshot.suboverflowed;
1820 snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
1821 snapshot->curcid = serialized_snapshot.curcid;
1822 snapshot->snapXactCompletionCount = 0;
1823
1824 /* Copy XIDs, if present. */
1825 if (serialized_snapshot.xcnt > 0)
1826 {
1827 snapshot->xip = (TransactionId *) (snapshot + 1);
1828 memcpy(snapshot->xip, serialized_xids,
1829 serialized_snapshot.xcnt * sizeof(TransactionId));
1830 }
1831
1832 /* Copy SubXIDs, if present. */
1833 if (serialized_snapshot.subxcnt > 0)
1834 {
1835 snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
1836 serialized_snapshot.xcnt;
1837 memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
1838 serialized_snapshot.subxcnt * sizeof(TransactionId));
1839 }
1840
1841 /* Set the copied flag so that the caller will set refcounts correctly. */
1842 snapshot->regd_count = 0;
1843 snapshot->active_count = 0;
1844 snapshot->copied = true;
1845
1846 return snapshot;
1847}
TransactionId xmax
Definition: snapmgr.c:254
TransactionId xmin
Definition: snapmgr.c:253
CommandId curcid
Definition: snapshot.h:183

References SnapshotData::active_count, SnapshotData::copied, SerializedSnapshotData::curcid, SnapshotData::curcid, MemoryContextAlloc(), SnapshotData::regd_count, SNAPSHOT_MVCC, SnapshotData::snapshot_type, SnapshotData::snapXactCompletionCount, SerializedSnapshotData::suboverflowed, SnapshotData::suboverflowed, SerializedSnapshotData::subxcnt, SnapshotData::subxcnt, SnapshotData::subxip, SerializedSnapshotData::takenDuringRecovery, SnapshotData::takenDuringRecovery, TopTransactionContext, SerializedSnapshotData::xcnt, SnapshotData::xcnt, SnapshotData::xip, SerializedSnapshotData::xmax, SnapshotData::xmax, SerializedSnapshotData::xmin, and SnapshotData::xmin.

Referenced by index_beginscan_parallel(), ParallelWorkerMain(), table_beginscan_parallel(), and table_beginscan_parallel_tidrange().

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  source_pgproc 
)

Definition at line 1856 of file snapmgr.c.

1857{
1858 SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
1859}
#define InvalidPid
Definition: miscadmin.h:32

References InvalidPid, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

◆ SerializeSnapshot()

void SerializeSnapshot ( Snapshot  snapshot,
char *  start_address 
)

Definition at line 1736 of file snapmgr.c.

1737{
1738 SerializedSnapshotData serialized_snapshot;
1739
1740 Assert(snapshot->subxcnt >= 0);
1741
1742 /* Copy all required fields */
1743 serialized_snapshot.xmin = snapshot->xmin;
1744 serialized_snapshot.xmax = snapshot->xmax;
1745 serialized_snapshot.xcnt = snapshot->xcnt;
1746 serialized_snapshot.subxcnt = snapshot->subxcnt;
1747 serialized_snapshot.suboverflowed = snapshot->suboverflowed;
1748 serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
1749 serialized_snapshot.curcid = snapshot->curcid;
1750
1751 /*
1752 * Ignore the SubXID array if it has overflowed, unless the snapshot was
1753 * taken during recovery - in that case, top-level XIDs are in subxip as
1754 * well, and we mustn't lose them.
1755 */
1756 if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
1757 serialized_snapshot.subxcnt = 0;
1758
1759 /* Copy struct to possibly-unaligned buffer */
1760 memcpy(start_address,
1761 &serialized_snapshot, sizeof(SerializedSnapshotData));
1762
1763 /* Copy XID array */
1764 if (snapshot->xcnt > 0)
1765 memcpy((TransactionId *) (start_address +
1766 sizeof(SerializedSnapshotData)),
1767 snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
1768
1769 /*
1770 * Copy SubXID array. Don't bother to copy it if it had overflowed,
1771 * though, because it's not used anywhere in that case. Except if it's a
1772 * snapshot taken during recovery; all the top-level XIDs are in subxip as
1773 * well in that case, so we mustn't lose them.
1774 */
1775 if (serialized_snapshot.subxcnt > 0)
1776 {
1777 Size subxipoff = sizeof(SerializedSnapshotData) +
1778 snapshot->xcnt * sizeof(TransactionId);
1779
1780 memcpy((TransactionId *) (start_address + subxipoff),
1781 snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
1782 }
1783}
struct SerializedSnapshotData SerializedSnapshotData

References Assert(), SerializedSnapshotData::curcid, SnapshotData::curcid, SerializedSnapshotData::suboverflowed, SnapshotData::suboverflowed, SerializedSnapshotData::subxcnt, SnapshotData::subxcnt, SnapshotData::subxip, SerializedSnapshotData::takenDuringRecovery, SnapshotData::takenDuringRecovery, SerializedSnapshotData::xcnt, SnapshotData::xcnt, SnapshotData::xip, SerializedSnapshotData::xmax, SnapshotData::xmax, SerializedSnapshotData::xmin, and SnapshotData::xmin.

Referenced by index_parallelscan_initialize(), InitializeParallelDSM(), and table_parallelscan_initialize().

◆ SetTransactionSnapshot()

static void SetTransactionSnapshot ( Snapshot  sourcesnap,
VirtualTransactionId sourcevxid,
int  sourcepid,
PGPROC sourceproc 
)
static

Definition at line 511 of file snapmgr.c.

513{
514 /* Caller should have checked this already */
516
517 /* Better do this to ensure following Assert succeeds. */
519
521 Assert(FirstXactSnapshot == NULL);
523
524 /*
525 * Even though we are not going to use the snapshot it computes, we must
526 * call GetSnapshotData, for two reasons: (1) to be sure that
527 * CurrentSnapshotData's XID arrays have been allocated, and (2) to update
528 * the state for GlobalVis*.
529 */
531
532 /*
533 * Now copy appropriate fields from the source snapshot.
534 */
535 CurrentSnapshot->xmin = sourcesnap->xmin;
536 CurrentSnapshot->xmax = sourcesnap->xmax;
537 CurrentSnapshot->xcnt = sourcesnap->xcnt;
538 Assert(sourcesnap->xcnt <= GetMaxSnapshotXidCount());
539 if (sourcesnap->xcnt > 0)
540 memcpy(CurrentSnapshot->xip, sourcesnap->xip,
541 sourcesnap->xcnt * sizeof(TransactionId));
542 CurrentSnapshot->subxcnt = sourcesnap->subxcnt;
543 Assert(sourcesnap->subxcnt <= GetMaxSnapshotSubxidCount());
544 if (sourcesnap->subxcnt > 0)
545 memcpy(CurrentSnapshot->subxip, sourcesnap->subxip,
546 sourcesnap->subxcnt * sizeof(TransactionId));
549 /* NB: curcid should NOT be copied, it's a local matter */
550
552
553 /*
554 * Now we have to fix what GetSnapshotData did with MyProc->xmin and
555 * TransactionXmin. There is a race condition: to make sure we are not
556 * causing the global xmin to go backwards, we have to test that the
557 * source transaction is still running, and that has to be done
558 * atomically. So let procarray.c do it.
559 *
560 * Note: in serializable mode, predicate.c will do this a second time. It
561 * doesn't seem worth contorting the logic here to avoid two calls,
562 * especially since it's not clear that predicate.c *must* do this.
563 */
564 if (sourceproc != NULL)
565 {
568 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
569 errmsg("could not import the requested snapshot"),
570 errdetail("The source transaction is not running anymore.")));
571 }
572 else if (!ProcArrayInstallImportedXmin(CurrentSnapshot->xmin, sourcevxid))
574 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
575 errmsg("could not import the requested snapshot"),
576 errdetail("The source process with PID %d is not running anymore.",
577 sourcepid)));
578
579 /*
580 * In transaction-snapshot mode, the first snapshot must live until end of
581 * xact, so we must make a copy of it. Furthermore, if we're running in
582 * serializable mode, predicate.c needs to do its own processing.
583 */
585 {
588 sourcepid);
589 /* Make a saved copy */
592 /* Mark it as "registered" in FirstXactSnapshot */
595 }
596
597 FirstSnapshotSet = true;
598}
int errdetail(const char *fmt,...)
Definition: elog.c:1216
void SetSerializableTransactionSnapshot(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1722
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
Definition: procarray.c:2564
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
Definition: procarray.c:2480

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

Referenced by ImportSnapshot(), and RestoreTransactionSnapshot().

◆ SetupHistoricSnapshot()

void SetupHistoricSnapshot ( Snapshot  historic_snapshot,
HTAB tuplecids 
)

Definition at line 1669 of file snapmgr.c.

1670{
1671 Assert(historic_snapshot != NULL);
1672
1673 /* setup the timetravel snapshot */
1674 HistoricSnapshot = historic_snapshot;
1675
1676 /* setup (cmin, cmax) lookup hash */
1677 tuplecid_data = tuplecids;
1678}

References Assert(), HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ SnapshotResetXmin()

static void SnapshotResetXmin ( void  )
static

Definition at line 937 of file snapmgr.c.

938{
939 Snapshot minSnapshot;
940
941 if (ActiveSnapshot != NULL)
942 return;
943
945 {
947 return;
948 }
949
950 minSnapshot = pairingheap_container(SnapshotData, ph_node,
952
953 if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin))
954 MyProc->xmin = TransactionXmin = minSnapshot->xmin;
955}
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:144
#define pairingheap_container(type, membername, ptr)
Definition: pairingheap.h:43
TransactionId TransactionXmin
Definition: snapmgr.c:159

References ActiveSnapshot, InvalidTransactionId, MyProc, pairingheap_container, pairingheap_first(), pairingheap_is_empty, RegisteredSnapshots, TransactionIdPrecedes(), TransactionXmin, PGPROC::xmin, and SnapshotData::xmin.

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

◆ SnapshotSetCommandId()

void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 490 of file snapmgr.c.

491{
492 if (!FirstSnapshotSet)
493 return;
494
495 if (CurrentSnapshot)
496 CurrentSnapshot->curcid = curcid;
498 SecondarySnapshot->curcid = curcid;
499 /* Should we do the same with CatalogSnapshot? */
500}

References SnapshotData::curcid, CurrentSnapshot, FirstSnapshotSet, and SecondarySnapshot.

Referenced by CommandCounterIncrement().

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 1685 of file snapmgr.c.

1686{
1687 HistoricSnapshot = NULL;
1688 tuplecid_data = NULL;
1689}

References HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1626 of file snapmgr.c.

1627{
1630 return true;
1631
1632 return false;
1633}

References pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by CopyFrom().

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 879 of file snapmgr.c.

880{
881 if (snapshot == NULL)
882 return;
883
884 ResourceOwnerForgetSnapshot(owner, snapshot);
886}
static void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snap)
Definition: snapmgr.c:240

References ResourceOwnerForgetSnapshot(), and UnregisterSnapshotNoOwner().

Referenced by closeLOfd(), PortalDrop(), PreCommit_Portals(), and UnregisterSnapshot().

◆ UnregisterSnapshotNoOwner()

static void UnregisterSnapshotNoOwner ( Snapshot  snapshot)
static

Definition at line 889 of file snapmgr.c.

890{
891 Assert(snapshot->regd_count > 0);
893
894 snapshot->regd_count--;
895 if (snapshot->regd_count == 0)
897
898 if (snapshot->regd_count == 0 && snapshot->active_count == 0)
899 {
900 FreeSnapshot(snapshot);
902 }
903}

References SnapshotData::active_count, Assert(), FreeSnapshot(), pairingheap_is_empty, pairingheap_remove(), SnapshotData::ph_node, SnapshotData::regd_count, RegisteredSnapshots, and SnapshotResetXmin().

Referenced by ResOwnerReleaseSnapshot(), and UnregisterSnapshotFromOwner().

◆ UpdateActiveSnapshotCommandId()

void UpdateActiveSnapshotCommandId ( void  )

Definition at line 744 of file snapmgr.c.

745{
746 CommandId save_curcid,
747 curcid;
748
749 Assert(ActiveSnapshot != NULL);
752
753 /*
754 * Don't allow modification of the active snapshot during parallel
755 * operation. We share the snapshot to worker backends at the beginning
756 * of parallel operation, so any change to the snapshot can lead to
757 * inconsistencies. We have other defenses against
758 * CommandCounterIncrement, but there are a few places that call this
759 * directly, so we put an additional guard here.
760 */
761 save_curcid = ActiveSnapshot->as_snap->curcid;
762 curcid = GetCurrentCommandId(false);
763 if (IsInParallelMode() && save_curcid != curcid)
764 elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
765 ActiveSnapshot->as_snap->curcid = curcid;
766}
uint32 CommandId
Definition: c.h:674
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:830

References SnapshotData::active_count, ActiveSnapshot, ActiveSnapshotElt::as_snap, Assert(), SnapshotData::curcid, elog, ERROR, GetCurrentCommandId(), IsInParallelMode(), and SnapshotData::regd_count.

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

◆ XactHasExportedSnapshots()

bool XactHasExportedSnapshots ( void  )

Definition at line 1574 of file snapmgr.c.

1575{
1576 return (exportedSnapshots != NIL);
1577}

References exportedSnapshots, and NIL.

Referenced by PrepareTransaction().

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 1872 of file snapmgr.c.

1873{
1874 /*
1875 * Make a quick range check to eliminate most XIDs without looking at the
1876 * xip arrays. Note that this is OK even if we convert a subxact XID to
1877 * its parent below, because a subxact with XID < xmin has surely also got
1878 * a parent with XID < xmin, while one with XID >= xmax must belong to a
1879 * parent that was not yet committed at the time of this snapshot.
1880 */
1881
1882 /* Any xid < xmin is not in-progress */
1883 if (TransactionIdPrecedes(xid, snapshot->xmin))
1884 return false;
1885 /* Any xid >= xmax is in-progress */
1886 if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
1887 return true;
1888
1889 /*
1890 * Snapshot information is stored slightly differently in snapshots taken
1891 * during recovery.
1892 */
1893 if (!snapshot->takenDuringRecovery)
1894 {
1895 /*
1896 * If the snapshot contains full subxact data, the fastest way to
1897 * check things is just to compare the given XID against both subxact
1898 * XIDs and top-level XIDs. If the snapshot overflowed, we have to
1899 * use pg_subtrans to convert a subxact XID to its parent XID, but
1900 * then we need only look at top-level XIDs not subxacts.
1901 */
1902 if (!snapshot->suboverflowed)
1903 {
1904 /* we have full data, so search subxip */
1905 if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1906 return true;
1907
1908 /* not there, fall through to search xip[] */
1909 }
1910 else
1911 {
1912 /*
1913 * Snapshot overflowed, so convert xid to top-level. This is safe
1914 * because we eliminated too-old XIDs above.
1915 */
1917
1918 /*
1919 * If xid was indeed a subxact, we might now have an xid < xmin,
1920 * so recheck to avoid an array scan. No point in rechecking
1921 * xmax.
1922 */
1923 if (TransactionIdPrecedes(xid, snapshot->xmin))
1924 return false;
1925 }
1926
1927 if (pg_lfind32(xid, snapshot->xip, snapshot->xcnt))
1928 return true;
1929 }
1930 else
1931 {
1932 /*
1933 * In recovery we store all xids in the subxip array because it is by
1934 * far the bigger array, and we mostly don't know which xids are
1935 * top-level and which are subxacts. The xip array is empty.
1936 *
1937 * We start by searching subtrans, if we overflowed.
1938 */
1939 if (snapshot->suboverflowed)
1940 {
1941 /*
1942 * Snapshot overflowed, so convert xid to top-level. This is safe
1943 * because we eliminated too-old XIDs above.
1944 */
1946
1947 /*
1948 * If xid was indeed a subxact, we might now have an xid < xmin,
1949 * so recheck to avoid an array scan. No point in rechecking
1950 * xmax.
1951 */
1952 if (TransactionIdPrecedes(xid, snapshot->xmin))
1953 return false;
1954 }
1955
1956 /*
1957 * We now have either a top-level xid higher than xmin or an
1958 * indeterminate xid. We don't know whether it's top level or subxact
1959 * but it doesn't matter. If it's present, the xid is visible.
1960 */
1961 if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1962 return true;
1963 }
1964
1965 return false;
1966}
static bool pg_lfind32(uint32 key, const uint32 *base, uint32 nelem)
Definition: pg_lfind.h:153
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:162
static bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.h:312

References pg_lfind32(), SnapshotData::suboverflowed, SubTransGetTopmostTransaction(), SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdFollowsOrEquals(), TransactionIdPrecedes(), SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by asyncQueueProcessPageEntries(), find_inheritance_children_extended(), HeapTupleSatisfiesMVCC(), and RelationGetPartitionDesc().

◆ xmin_cmp()

static int xmin_cmp ( const pairingheap_node a,
const pairingheap_node b,
void *  arg 
)
static

Definition at line 910 of file snapmgr.c.

911{
912 const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
913 const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
914
915 if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
916 return 1;
917 else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
918 return -1;
919 else
920 return 0;
921}
int b
Definition: isn.c:74
int a
Definition: isn.c:73
#define pairingheap_const_container(type, membername, ptr)
Definition: pairingheap.h:51
static bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.h:297

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

Variable Documentation

◆ ActiveSnapshot

◆ CatalogSnapshot

◆ CatalogSnapshotData

SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 143 of file snapmgr.c.

Referenced by GetNonHistoricCatalogSnapshot().

◆ CurrentSnapshot

◆ CurrentSnapshotData

SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 141 of file snapmgr.c.

Referenced by GetTransactionSnapshot(), and SetTransactionSnapshot().

◆ exportedSnapshots

List* exportedSnapshots = NIL
static

Definition at line 213 of file snapmgr.c.

Referenced by AtEOXact_Snapshot(), ExportSnapshot(), and XactHasExportedSnapshots().

◆ FirstSnapshotSet

◆ FirstXactSnapshot

Snapshot FirstXactSnapshot = NULL
static

Definition at line 200 of file snapmgr.c.

Referenced by AtEOXact_Snapshot(), GetTransactionSnapshot(), and SetTransactionSnapshot().

◆ HistoricSnapshot

◆ RecentXmin

◆ RegisteredSnapshots

◆ SecondarySnapshot

Snapshot SecondarySnapshot = NULL
static

◆ SecondarySnapshotData

SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 142 of file snapmgr.c.

Referenced by GetLatestSnapshot().

◆ snapshot_resowner_desc

const ResourceOwnerDesc snapshot_resowner_desc
static
Initial value:
=
{
.name = "snapshot reference",
.release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
.release_priority = RELEASE_PRIO_SNAPSHOT_REFS,
.ReleaseResource = ResOwnerReleaseSnapshot,
.DebugPrint = NULL
}
#define RELEASE_PRIO_SNAPSHOT_REFS
Definition: resowner.h:75
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56
static void ResOwnerReleaseSnapshot(Datum res)
Definition: snapmgr.c:1971

Definition at line 224 of file snapmgr.c.

Referenced by ResourceOwnerForgetSnapshot(), and ResourceOwnerRememberSnapshot().

◆ SnapshotAnyData

SnapshotData SnapshotAnyData = {SNAPSHOT_ANY}

Definition at line 145 of file snapmgr.c.

◆ SnapshotSelfData

SnapshotData SnapshotSelfData = {SNAPSHOT_SELF}

Definition at line 144 of file snapmgr.c.

◆ SnapshotToastData

SnapshotData SnapshotToastData = {SNAPSHOT_TOAST}

Definition at line 146 of file snapmgr.c.

Referenced by get_toast_snapshot().

◆ TransactionXmin

◆ tuplecid_data