PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 1003 of file snapmgr.c.

1004{
1005 /*
1006 * In transaction-snapshot mode we must release our privately-managed
1007 * reference to the transaction snapshot. We must remove it from
1008 * RegisteredSnapshots to keep the check below happy. But we don't bother
1009 * to do FreeSnapshot, for two reasons: the memory will go away with
1010 * TopTransactionContext anyway, and if someone has left the snapshot
1011 * stacked as active, we don't want the code below to be chasing through a
1012 * dangling pointer.
1013 */
1014 if (FirstXactSnapshot != NULL)
1015 {
1019 }
1020 FirstXactSnapshot = NULL;
1021
1022 /*
1023 * If we exported any snapshots, clean them up.
1024 */
1025 if (exportedSnapshots != NIL)
1026 {
1027 ListCell *lc;
1028
1029 /*
1030 * Get rid of the files. Unlink failure is only a WARNING because (1)
1031 * it's too late to abort the transaction, and (2) leaving a leaked
1032 * file around has little real consequence anyway.
1033 *
1034 * We also need to remove the snapshots from RegisteredSnapshots to
1035 * prevent a warning below.
1036 *
1037 * As with the FirstXactSnapshot, we don't need to free resources of
1038 * the snapshot itself as it will go away with the memory context.
1039 */
1040 foreach(lc, exportedSnapshots)
1041 {
1042 ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1043
1044 if (unlink(esnap->snapfile))
1045 elog(WARNING, "could not unlink file \"%s\": %m",
1046 esnap->snapfile);
1047
1049 &esnap->snapshot->ph_node);
1050 }
1051
1053 }
1054
1055 /* Drop catalog snapshot if any */
1057
1058 /* On commit, complain about leftover snapshots */
1059 if (isCommit)
1060 {
1061 ActiveSnapshotElt *active;
1062
1064 elog(WARNING, "registered snapshots seem to remain after cleanup");
1065
1066 /* complain about unpopped active snapshots */
1067 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1068 elog(WARNING, "snapshot %p still active", active);
1069 }
1070
1071 /*
1072 * And reset our state. We don't need to free the memory explicitly --
1073 * it'll go away with TopTransactionContext.
1074 */
1075 ActiveSnapshot = NULL;
1077
1078 CurrentSnapshot = NULL;
1079 SecondarySnapshot = NULL;
1080
1081 FirstSnapshotSet = false;
1082
1083 /*
1084 * During normal commit processing, we call ProcArrayEndTransaction() to
1085 * reset the MyProc->xmin. That call happens prior to the call to
1086 * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1087 */
1088 if (resetXmin)
1090
1091 Assert(resetXmin || MyProc->xmin == 0);
1092}
#define WARNING
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:225
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:924
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:443
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:178
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 969 of file snapmgr.c.

970{
971 /* Forget the active snapshots set by this subtransaction */
972 while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
973 {
975
977
978 /*
979 * Decrement the snapshot's active count. If it's still registered or
980 * marked as active by an outer subtransaction, we can't free it yet.
981 */
984
988
989 /* and free the stack element */
991
993 }
994
996}
static int32 next
Definition: blutils.c:224
void pfree(void *pointer)
Definition: mcxt.c:1524
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:651
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 948 of file snapmgr.c.

949{
950 ActiveSnapshotElt *active;
951
952 /*
953 * Relabel the active snapshots set in this subtransaction as though they
954 * are owned by the parent subxact.
955 */
956 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
957 {
958 if (active->as_level < level)
959 break;
960 active->as_level = level - 1;
961 }
962}

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

Referenced by CommitSubTransaction().

◆ CopySnapshot()

static Snapshot CopySnapshot ( Snapshot  snapshot)
static

Definition at line 595 of file snapmgr.c.

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

1575{
1576 char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1577 DIR *s_dir;
1578 struct dirent *s_de;
1579
1580 /*
1581 * Problems in reading the directory, or unlinking files, are reported at
1582 * LOG level. Since we're running in the startup process, ERROR level
1583 * would prevent database start, and it's not important enough for that.
1584 */
1586
1587 while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1588 {
1589 if (strcmp(s_de->d_name, ".") == 0 ||
1590 strcmp(s_de->d_name, "..") == 0)
1591 continue;
1592
1593 snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1594
1595 if (unlink(buf) != 0)
1596 ereport(LOG,
1598 errmsg("could not remove file \"%s\": %m", buf)));
1599 }
1600
1601 FreeDir(s_dir);
1602}
int errcode_for_file_access(void)
Definition: elog.c:876
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:149
int FreeDir(DIR *dir)
Definition: fd.c:2985
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2948
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2867
#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 1699 of file snapmgr.c.

1700{
1701 Size size;
1702
1703 Assert(snapshot != InvalidSnapshot);
1704 Assert(snapshot->snapshot_type == SNAPSHOT_MVCC);
1705
1706 /* We allocate any XID arrays needed in the same palloc block. */
1707 size = add_size(sizeof(SerializedSnapshotData),
1708 mul_size(snapshot->xcnt, sizeof(TransactionId)));
1709 if (snapshot->subxcnt > 0 &&
1710 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
1711 size = add_size(size,
1712 mul_size(snapshot->subxcnt, sizeof(TransactionId)));
1713
1714 return size;
1715}
Size add_size(Size s1, Size s2)
Definition: shmem.c:488
Size mul_size(Size s1, Size s2)
Definition: shmem.c:505
@ 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 1102 of file snapmgr.c.

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

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

652{
653 Assert(snapshot->regd_count == 0);
654 Assert(snapshot->active_count == 0);
655 Assert(snapshot->copied);
656
657 pfree(snapshot);
658}

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

374{
375 /*
376 * Return historic snapshot while we're doing logical decoding, so we can
377 * see the appropriate state of the catalog.
378 *
379 * This is the primary reason for needing to reset the system caches after
380 * finishing decoding.
381 */
383 return HistoricSnapshot;
384
385 return GetNonHistoricCatalogSnapshot(relid);
386}
static Snapshot HistoricSnapshot
Definition: snapmgr.c:151
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1679
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:395

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

343{
344 /*
345 * We might be able to relax this, but nothing that could otherwise work
346 * needs it.
347 */
348 if (IsInParallelMode())
349 elog(ERROR,
350 "cannot update SecondarySnapshot during a parallel operation");
351
352 /*
353 * So far there are no cases requiring support for GetLatestSnapshot()
354 * during logical decoding, but it wouldn't be hard to add if required.
355 */
357
358 /* If first call in transaction, go ahead and set the xact snapshot */
359 if (!FirstSnapshotSet)
360 return GetTransactionSnapshot();
361
363
364 return SecondarySnapshot;
365}
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2175
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 395 of file snapmgr.c.

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

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 * This should not be called while doing logical decoding. Historic
275 * snapshots are only usable for catalog access, not for general-purpose
276 * queries.
277 */
279 elog(ERROR, "cannot take query snapshot during logical decoding");
280
281 /* First call in transaction? */
282 if (!FirstSnapshotSet)
283 {
284 /*
285 * Don't allow catalog snapshot to be older than xact snapshot. Must
286 * do this first to allow the empty-heap Assert to succeed.
287 */
289
291 Assert(FirstXactSnapshot == NULL);
292
293 if (IsInParallelMode())
294 elog(ERROR,
295 "cannot take query snapshot during a parallel operation");
296
297 /*
298 * In transaction-snapshot mode, the first snapshot must live until
299 * end of xact regardless of what the caller does with it, so we must
300 * make a copy of it rather than returning CurrentSnapshotData
301 * directly. Furthermore, if we're running in serializable mode,
302 * predicate.c needs to wrap the snapshot fetch in its own processing.
303 */
305 {
306 /* First, create the snapshot in CurrentSnapshotData */
309 else
311 /* Make a saved copy */
314 /* Mark it as "registered" in FirstXactSnapshot */
317 }
318 else
320
321 FirstSnapshotSet = true;
322 return CurrentSnapshot;
323 }
324
326 return CurrentSnapshot;
327
328 /* Don't allow catalog snapshot to be older than xact snapshot. */
330
332
333 return CurrentSnapshot;
334}
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1672
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:140
#define IsolationUsesXactSnapshot()
Definition: xact.h:51
#define IsolationIsSerializable()
Definition: xact.h:52

References Assert(), CopySnapshot(), CurrentSnapshot, CurrentSnapshotData, elog, ERROR, FirstSnapshotSet, FirstXactSnapshot, GetSerializableTransactionSnapshot(), GetSnapshotData(), 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(), begin_replication_step(), bt_check_every_level(), BuildCachedPlan(), CheckTargetForConflictsIn(), cluster_multiple_rels(), DefineIndex(), 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(), SPI_cursor_open_internal(), vacuum(), vacuum_rel(), verify_heapam(), worker_spi_main(), and XidIsConcurrent().

◆ HaveRegisteredOrActiveSnapshot()

bool HaveRegisteredOrActiveSnapshot ( void  )

Definition at line 1631 of file snapmgr.c.

1632{
1633 if (ActiveSnapshot != NULL)
1634 return true;
1635
1636 /*
1637 * The catalog snapshot is in RegisteredSnapshots when valid, but can be
1638 * removed at any time due to invalidation processing. If explicitly
1639 * registered more than one snapshot has to be in RegisteredSnapshots.
1640 */
1641 if (CatalogSnapshot != NULL &&
1643 return false;
1644
1646}
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99

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

Referenced by get_toast_snapshot(), and SnapBuildInitialSnapshot().

◆ HistoricSnapshotActive()

◆ HistoricSnapshotGetTupleCids()

HTAB * HistoricSnapshotGetTupleCids ( void  )

Definition at line 1685 of file snapmgr.c.

1686{
1688 return tuplecid_data;
1689}
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 1374 of file snapmgr.c.

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

1295{
1296 char *ptr = *s;
1297 int prefixlen = strlen(prefix);
1298 int val;
1299
1300 if (strncmp(ptr, prefix, prefixlen) != 0)
1301 ereport(ERROR,
1302 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1303 errmsg("invalid snapshot data in file \"%s\"", filename)));
1304 ptr += prefixlen;
1305 if (sscanf(ptr, "%d", &val) != 1)
1306 ereport(ERROR,
1307 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1308 errmsg("invalid snapshot data in file \"%s\"", filename)));
1309 ptr = strchr(ptr, '\n');
1310 if (!ptr)
1311 ereport(ERROR,
1312 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1313 errmsg("invalid snapshot data in file \"%s\"", filename)));
1314 *s = ptr + 1;
1315 return val;
1316}
long val
Definition: informix.c:689
static char * filename
Definition: pg_dumpall.c:127

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

1346{
1347 char *ptr = *s;
1348 int prefixlen = strlen(prefix);
1349
1350 if (strncmp(ptr, prefix, prefixlen) != 0)
1351 ereport(ERROR,
1352 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1353 errmsg("invalid snapshot data in file \"%s\"", filename)));
1354 ptr += prefixlen;
1355 if (sscanf(ptr, "%d/%u", &vxid->procNumber, &vxid->localTransactionId) != 2)
1356 ereport(ERROR,
1357 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1358 errmsg("invalid snapshot data in file \"%s\"", filename)));
1359 ptr = strchr(ptr, '\n');
1360 if (!ptr)
1361 ereport(ERROR,
1362 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1363 errmsg("invalid snapshot data in file \"%s\"", filename)));
1364 *s = ptr + 1;
1365}
LocalTransactionId localTransactionId
Definition: lock.h:63
ProcNumber procNumber
Definition: lock.h:62

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

1320{
1321 char *ptr = *s;
1322 int prefixlen = strlen(prefix);
1324
1325 if (strncmp(ptr, prefix, prefixlen) != 0)
1326 ereport(ERROR,
1327 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1328 errmsg("invalid snapshot data in file \"%s\"", filename)));
1329 ptr += prefixlen;
1330 if (sscanf(ptr, "%u", &val) != 1)
1331 ereport(ERROR,
1332 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1333 errmsg("invalid snapshot data in file \"%s\"", filename)));
1334 ptr = strchr(ptr, '\n');
1335 if (!ptr)
1336 ereport(ERROR,
1337 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1338 errmsg("invalid snapshot data in file \"%s\"", filename)));
1339 *s = ptr + 1;
1340 return val;
1341}

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

Referenced by ImportSnapshot().

◆ pg_export_snapshot()

Datum pg_export_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 1279 of file snapmgr.c.

1280{
1281 char *snapshotName;
1282
1283 snapshotName = ExportSnapshot(GetActiveSnapshot());
1284 PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1285}
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1102
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:787
text * cstring_to_text(const char *s)
Definition: varlena.c:192

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

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 762 of file snapmgr.c.

763{
764 ActiveSnapshotElt *newstack;
765
766 newstack = ActiveSnapshot->as_next;
767
769
771
775
777 ActiveSnapshot = newstack;
778
780}

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(), cluster_multiple_rels(), DefineIndex(), 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(), ShutdownSQLFunction(), vacuum(), vacuum_rel(), and worker_spi_main().

◆ PushActiveSnapshot()

◆ PushActiveSnapshotWithLevel()

void PushActiveSnapshotWithLevel ( Snapshot  snapshot,
int  snap_level 
)

Definition at line 683 of file snapmgr.c.

684{
685 ActiveSnapshotElt *newactive;
686
687 Assert(snapshot != InvalidSnapshot);
688 Assert(ActiveSnapshot == NULL || snap_level >= ActiveSnapshot->as_level);
689
691
692 /*
693 * Checking SecondarySnapshot is probably useless here, but it seems
694 * better to be sure.
695 */
696 if (snapshot == CurrentSnapshot || snapshot == SecondarySnapshot ||
697 !snapshot->copied)
698 newactive->as_snap = CopySnapshot(snapshot);
699 else
700 newactive->as_snap = snapshot;
701
702 newactive->as_next = ActiveSnapshot;
703 newactive->as_level = snap_level;
704
705 newactive->as_snap->active_count++;
706
707 ActiveSnapshot = newactive;
708}

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

720{
722}
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:669

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

825{
826 Snapshot snap;
827
828 if (snapshot == InvalidSnapshot)
829 return InvalidSnapshot;
830
831 /* Static snapshot? Create a persistent copy */
832 snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
833
834 /* and tell resowner.c about it */
836 snap->regd_count++;
838
839 if (snap->regd_count == 1)
841
842 return snap;
843}
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:452
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:327
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:564
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:524

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

Referenced by RegisterSnapshotOnOwner().

◆ ResOwnerReleaseSnapshot()

static void ResOwnerReleaseSnapshot ( Datum  res)
static

Definition at line 1958 of file snapmgr.c.

1959{
1961}
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
static void UnregisterSnapshotNoOwner(Snapshot snapshot)
Definition: snapmgr.c:876

References DatumGetPointer(), and UnregisterSnapshotNoOwner().

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 1780 of file snapmgr.c.

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

1844{
1845 SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
1846}
#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 1723 of file snapmgr.c.

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

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

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

1657{
1658 Assert(historic_snapshot != NULL);
1659
1660 /* setup the timetravel snapshot */
1661 HistoricSnapshot = historic_snapshot;
1662
1663 /* setup (cmin, cmax) lookup hash */
1664 tuplecid_data = tuplecids;
1665}

References Assert(), HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ SnapshotResetXmin()

static void SnapshotResetXmin ( void  )
static

Definition at line 924 of file snapmgr.c.

925{
926 Snapshot minSnapshot;
927
928 if (ActiveSnapshot != NULL)
929 return;
930
932 {
934 return;
935 }
936
937 minSnapshot = pairingheap_container(SnapshotData, ph_node,
939
940 if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin))
941 MyProc->xmin = TransactionXmin = minSnapshot->xmin;
942}
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 477 of file snapmgr.c.

478{
479 if (!FirstSnapshotSet)
480 return;
481
482 if (CurrentSnapshot)
483 CurrentSnapshot->curcid = curcid;
485 SecondarySnapshot->curcid = curcid;
486 /* Should we do the same with CatalogSnapshot? */
487}

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

Referenced by CommandCounterIncrement().

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 1672 of file snapmgr.c.

1673{
1674 HistoricSnapshot = NULL;
1675 tuplecid_data = NULL;
1676}

References HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1613 of file snapmgr.c.

1614{
1617 return true;
1618
1619 return false;
1620}

References pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by CopyFrom().

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 866 of file snapmgr.c.

867{
868 if (snapshot == NULL)
869 return;
870
871 ResourceOwnerForgetSnapshot(owner, snapshot);
873}
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 876 of file snapmgr.c.

877{
878 Assert(snapshot->regd_count > 0);
880
881 snapshot->regd_count--;
882 if (snapshot->regd_count == 0)
884
885 if (snapshot->regd_count == 0 && snapshot->active_count == 0)
886 {
887 FreeSnapshot(snapshot);
889 }
890}

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

732{
733 CommandId save_curcid,
734 curcid;
735
736 Assert(ActiveSnapshot != NULL);
739
740 /*
741 * Don't allow modification of the active snapshot during parallel
742 * operation. We share the snapshot to worker backends at the beginning
743 * of parallel operation, so any change to the snapshot can lead to
744 * inconsistencies. We have other defenses against
745 * CommandCounterIncrement, but there are a few places that call this
746 * directly, so we put an additional guard here.
747 */
748 save_curcid = ActiveSnapshot->as_snap->curcid;
749 curcid = GetCurrentCommandId(false);
750 if (IsInParallelMode() && save_curcid != curcid)
751 elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
752 ActiveSnapshot->as_snap->curcid = curcid;
753}
uint32 CommandId
Definition: c.h:637
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 1561 of file snapmgr.c.

1562{
1563 return (exportedSnapshots != NIL);
1564}

References exportedSnapshots, and NIL.

Referenced by PrepareTransaction().

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 1859 of file snapmgr.c.

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

898{
899 const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
900 const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
901
902 if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
903 return 1;
904 else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
905 return -1;
906 else
907 return 0;
908}
int b
Definition: isn.c:71
int a
Definition: isn.c:70
#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

Snapshot HistoricSnapshot = NULL
static

◆ 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:1958

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