Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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/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 202 of file snapmgr.c.

Typedef Documentation

◆ ActiveSnapshotElt

◆ ExportedSnapshot

◆ SerializedSnapshotData

Function Documentation

◆ ActiveSnapshotSet()

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1014 of file snapmgr.c.

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

981{
982 /* Forget the active snapshots set by this subtransaction */
983 while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
984 {
986
988
989 /*
990 * Decrement the snapshot's active count. If it's still registered or
991 * marked as active by an outer subtransaction, we can't free it yet.
992 */
995
999
1000 /* and free the stack element */
1002
1004 }
1005
1007}
static int32 next
Definition: blutils.c:224
void pfree(void *pointer)
Definition: mcxt.c:1594
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
Snapshot as_snap
Definition: snapmgr.c:174
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 959 of file snapmgr.c.

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

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

Referenced by CommitSubTransaction().

◆ CopySnapshot()

static Snapshot CopySnapshot ( Snapshot  snapshot)
static

Definition at line 606 of file snapmgr.c.

607{
608 Snapshot newsnap;
609 Size subxipoff;
610 Size size;
611
612 Assert(snapshot != InvalidSnapshot);
613
614 /* We allocate any XID arrays needed in the same palloc block. */
615 size = subxipoff = sizeof(SnapshotData) +
616 snapshot->xcnt * sizeof(TransactionId);
617 if (snapshot->subxcnt > 0)
618 size += snapshot->subxcnt * sizeof(TransactionId);
619
621 memcpy(newsnap, snapshot, sizeof(SnapshotData));
622
623 newsnap->regd_count = 0;
624 newsnap->active_count = 0;
625 newsnap->copied = true;
626 newsnap->snapXactCompletionCount = 0;
627
628 /* setup XID array */
629 if (snapshot->xcnt > 0)
630 {
631 newsnap->xip = (TransactionId *) (newsnap + 1);
632 memcpy(newsnap->xip, snapshot->xip,
633 snapshot->xcnt * sizeof(TransactionId));
634 }
635 else
636 newsnap->xip = NULL;
637
638 /*
639 * Setup subXID array. Don't bother to copy it if it had overflowed,
640 * though, because it's not used anywhere in that case. Except if it's a
641 * snapshot taken during recovery; all the top-level XIDs are in subxip as
642 * well in that case, so we mustn't lose them.
643 */
644 if (snapshot->subxcnt > 0 &&
645 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
646 {
647 newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
648 memcpy(newsnap->subxip, snapshot->subxip,
649 snapshot->subxcnt * sizeof(TransactionId));
650 }
651 else
652 newsnap->subxip = NULL;
653
654 return newsnap;
655}
uint32 TransactionId
Definition: c.h:658
size_t Size
Definition: c.h:611
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 1585 of file snapmgr.c.

1586{
1587 char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1588 DIR *s_dir;
1589 struct dirent *s_de;
1590
1591 /*
1592 * Problems in reading the directory, or unlinking files, are reported at
1593 * LOG level. Since we're running in the startup process, ERROR level
1594 * would prevent database start, and it's not important enough for that.
1595 */
1597
1598 while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1599 {
1600 if (strcmp(s_de->d_name, ".") == 0 ||
1601 strcmp(s_de->d_name, "..") == 0)
1602 continue;
1603
1604 snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1605
1606 if (unlink(buf) != 0)
1607 ereport(LOG,
1609 errmsg("could not remove file \"%s\": %m", buf)));
1610 }
1611
1612 FreeDir(s_dir);
1613}
int errcode_for_file_access(void)
Definition: elog.c:877
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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:239
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:202
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 1710 of file snapmgr.c.

1711{
1712 Size size;
1713
1714 Assert(snapshot != InvalidSnapshot);
1715 Assert(snapshot->snapshot_type == SNAPSHOT_MVCC);
1716
1717 /* We allocate any XID arrays needed in the same palloc block. */
1718 size = add_size(sizeof(SerializedSnapshotData),
1719 mul_size(snapshot->xcnt, sizeof(TransactionId)));
1720 if (snapshot->subxcnt > 0 &&
1721 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
1722 size = add_size(size,
1723 mul_size(snapshot->subxcnt, sizeof(TransactionId)));
1724
1725 return size;
1726}
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
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 1113 of file snapmgr.c.

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

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 662 of file snapmgr.c.

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

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 384 of file snapmgr.c.

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

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 353 of file snapmgr.c.

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

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 406 of file snapmgr.c.

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

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

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

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

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

◆ HistoricSnapshotActive()

◆ HistoricSnapshotGetTupleCids()

HTAB * HistoricSnapshotGetTupleCids ( void  )

Definition at line 1696 of file snapmgr.c.

1697{
1699 return tuplecid_data;
1700}
static HTAB * tuplecid_data
Definition: snapmgr.c:162

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

Referenced by HeapTupleSatisfiesHistoricMVCC().

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1385 of file snapmgr.c.

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

1306{
1307 char *ptr = *s;
1308 int prefixlen = strlen(prefix);
1309 int val;
1310
1311 if (strncmp(ptr, prefix, prefixlen) != 0)
1312 ereport(ERROR,
1313 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1314 errmsg("invalid snapshot data in file \"%s\"", filename)));
1315 ptr += prefixlen;
1316 if (sscanf(ptr, "%d", &val) != 1)
1317 ereport(ERROR,
1318 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1319 errmsg("invalid snapshot data in file \"%s\"", filename)));
1320 ptr = strchr(ptr, '\n');
1321 if (!ptr)
1322 ereport(ERROR,
1323 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1324 errmsg("invalid snapshot data in file \"%s\"", filename)));
1325 *s = ptr + 1;
1326 return val;
1327}
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 1355 of file snapmgr.c.

1357{
1358 char *ptr = *s;
1359 int prefixlen = strlen(prefix);
1360
1361 if (strncmp(ptr, prefix, prefixlen) != 0)
1362 ereport(ERROR,
1363 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1364 errmsg("invalid snapshot data in file \"%s\"", filename)));
1365 ptr += prefixlen;
1366 if (sscanf(ptr, "%d/%u", &vxid->procNumber, &vxid->localTransactionId) != 2)
1367 ereport(ERROR,
1368 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1369 errmsg("invalid snapshot data in file \"%s\"", filename)));
1370 ptr = strchr(ptr, '\n');
1371 if (!ptr)
1372 ereport(ERROR,
1373 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1374 errmsg("invalid snapshot data in file \"%s\"", filename)));
1375 *s = ptr + 1;
1376}
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 1330 of file snapmgr.c.

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

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

Referenced by ImportSnapshot().

◆ pg_export_snapshot()

Datum pg_export_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 1290 of file snapmgr.c.

1291{
1292 char *snapshotName;
1293
1294 snapshotName = ExportSnapshot(GetActiveSnapshot());
1295 PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1296}
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1113
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:798
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 773 of file snapmgr.c.

774{
775 ActiveSnapshotElt *newstack;
776
777 newstack = ActiveSnapshot->as_next;
778
780
782
786
788 ActiveSnapshot = newstack;
789
791}

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(), 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 694 of file snapmgr.c.

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

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 730 of file snapmgr.c.

731{
733}
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:680

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 835 of file snapmgr.c.

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

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 239 of file snapmgr.c.

240{
242}
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:223

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

Referenced by UnregisterSnapshotFromOwner().

◆ ResourceOwnerRememberSnapshot()

static void ResourceOwnerRememberSnapshot ( ResourceOwner  owner,
Snapshot  snap 
)
inlinestatic

Definition at line 234 of file snapmgr.c.

235{
237}
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 1969 of file snapmgr.c.

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

References DatumGetPointer(), and UnregisterSnapshotNoOwner().

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 1791 of file snapmgr.c.

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

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
void *  source_pgproc 
)

Definition at line 1854 of file snapmgr.c.

1855{
1856 SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
1857}
#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 1734 of file snapmgr.c.

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

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

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

References Assert(), HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ SnapshotResetXmin()

static void SnapshotResetXmin ( void  )
static

Definition at line 935 of file snapmgr.c.

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

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 488 of file snapmgr.c.

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

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

Referenced by CommandCounterIncrement().

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 1683 of file snapmgr.c.

1684{
1685 HistoricSnapshot = NULL;
1686 tuplecid_data = NULL;
1687}

References HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1624 of file snapmgr.c.

1625{
1628 return true;
1629
1630 return false;
1631}

References pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by CopyFrom().

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 877 of file snapmgr.c.

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

References ResourceOwnerForgetSnapshot(), and UnregisterSnapshotNoOwner().

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

◆ UnregisterSnapshotNoOwner()

static void UnregisterSnapshotNoOwner ( Snapshot  snapshot)
static

Definition at line 887 of file snapmgr.c.

888{
889 Assert(snapshot->regd_count > 0);
891
892 snapshot->regd_count--;
893 if (snapshot->regd_count == 0)
895
896 if (snapshot->regd_count == 0 && snapshot->active_count == 0)
897 {
898 FreeSnapshot(snapshot);
900 }
901}

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 742 of file snapmgr.c.

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

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 1572 of file snapmgr.c.

1573{
1574 return (exportedSnapshots != NIL);
1575}

References exportedSnapshots, and NIL.

Referenced by PrepareTransaction().

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 1870 of file snapmgr.c.

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

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 908 of file snapmgr.c.

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

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

Variable Documentation

◆ ActiveSnapshot

◆ CatalogSnapshot

◆ CatalogSnapshotData

SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 142 of file snapmgr.c.

Referenced by GetNonHistoricCatalogSnapshot().

◆ CurrentSnapshot

◆ CurrentSnapshotData

SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 140 of file snapmgr.c.

Referenced by GetTransactionSnapshot(), and SetTransactionSnapshot().

◆ exportedSnapshots

List* exportedSnapshots = NIL
static

Definition at line 212 of file snapmgr.c.

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

◆ FirstSnapshotSet

◆ FirstXactSnapshot

Snapshot FirstXactSnapshot = NULL
static

Definition at line 199 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 141 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:1969

Definition at line 223 of file snapmgr.c.

Referenced by ResourceOwnerForgetSnapshot(), and ResourceOwnerRememberSnapshot().

◆ SnapshotAnyData

SnapshotData SnapshotAnyData = {SNAPSHOT_ANY}

Definition at line 144 of file snapmgr.c.

◆ SnapshotSelfData

SnapshotData SnapshotSelfData = {SNAPSHOT_SELF}

Definition at line 143 of file snapmgr.c.

◆ SnapshotToastData

SnapshotData SnapshotToastData = {SNAPSHOT_TOAST}

Definition at line 145 of file snapmgr.c.

Referenced by get_toast_snapshot().

◆ TransactionXmin

◆ tuplecid_data