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

Go to the source code of this file.

Data Structures

struct  ActiveSnapshotElt
 
struct  ExportedSnapshot
 
struct  SerializedSnapshotData
 

Macros

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"
 

Typedefs

typedef struct ActiveSnapshotElt ActiveSnapshotElt
 
typedef struct ExportedSnapshot ExportedSnapshot
 
typedef struct SerializedSnapshotData SerializedSnapshotData
 

Functions

static int xmin_cmp (const pairingheap_node *a, const pairingheap_node *b, void *arg)
 
static Snapshot CopySnapshot (Snapshot snapshot)
 
static void UnregisterSnapshotNoOwner (Snapshot snapshot)
 
static void FreeSnapshot (Snapshot snapshot)
 
static void SnapshotResetXmin (void)
 
static void ResOwnerReleaseSnapshot (Datum res)
 
static void ResourceOwnerRememberSnapshot (ResourceOwner owner, Snapshot snap)
 
static void ResourceOwnerForgetSnapshot (ResourceOwner owner, Snapshot snap)
 
Snapshot GetTransactionSnapshot (void)
 
Snapshot GetLatestSnapshot (void)
 
Snapshot GetCatalogSnapshot (Oid relid)
 
Snapshot GetNonHistoricCatalogSnapshot (Oid relid)
 
void InvalidateCatalogSnapshot (void)
 
void InvalidateCatalogSnapshotConditionally (void)
 
void SnapshotSetCommandId (CommandId curcid)
 
static void SetTransactionSnapshot (Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
 
void PushActiveSnapshot (Snapshot snapshot)
 
void PushActiveSnapshotWithLevel (Snapshot snapshot, int snap_level)
 
void PushCopiedSnapshot (Snapshot snapshot)
 
void UpdateActiveSnapshotCommandId (void)
 
void PopActiveSnapshot (void)
 
Snapshot GetActiveSnapshot (void)
 
bool ActiveSnapshotSet (void)
 
Snapshot RegisterSnapshot (Snapshot snapshot)
 
Snapshot RegisterSnapshotOnOwner (Snapshot snapshot, ResourceOwner owner)
 
void UnregisterSnapshot (Snapshot snapshot)
 
void UnregisterSnapshotFromOwner (Snapshot snapshot, ResourceOwner owner)
 
void AtSubCommit_Snapshot (int level)
 
void AtSubAbort_Snapshot (int level)
 
void AtEOXact_Snapshot (bool isCommit, bool resetXmin)
 
charExportSnapshot (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, PGPROC *source_pgproc)
 
bool XidInMVCCSnapshot (TransactionId xid, Snapshot snapshot)
 

Variables

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

Macro Definition Documentation

◆ SNAPSHOT_EXPORT_DIR

#define SNAPSHOT_EXPORT_DIR   "pg_snapshots"

Definition at line 203 of file snapmgr.c.

Typedef Documentation

◆ ActiveSnapshotElt

◆ ExportedSnapshot

◆ SerializedSnapshotData

Function Documentation

◆ ActiveSnapshotSet()

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 1016 of file snapmgr.c.

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

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

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

◆ AtSubAbort_Snapshot()

void AtSubAbort_Snapshot ( int  level)

Definition at line 982 of file snapmgr.c.

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

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

Referenced by AbortSubTransaction().

◆ AtSubCommit_Snapshot()

void AtSubCommit_Snapshot ( int  level)

Definition at line 961 of file snapmgr.c.

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

References ActiveSnapshot, ActiveSnapshotElt::as_level, ActiveSnapshotElt::as_next, and fb().

Referenced by CommitSubTransaction().

◆ CopySnapshot()

static Snapshot CopySnapshot ( Snapshot  snapshot)
static

Definition at line 608 of file snapmgr.c.

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

References Assert, fb(), InvalidSnapshot, memcpy(), MemoryContextAlloc(), 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 1586 of file snapmgr.c.

1587{
1588 char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1589 DIR *s_dir;
1590 struct dirent *s_de;
1591
1592 /*
1593 * Problems in reading the directory, or unlinking files, are reported at
1594 * LOG level. Since we're running in the startup process, ERROR level
1595 * would prevent database start, and it's not important enough for that.
1596 */
1598
1600 {
1601 if (strcmp(s_de->d_name, ".") == 0 ||
1602 strcmp(s_de->d_name, "..") == 0)
1603 continue;
1604
1605 snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1606
1607 if (unlink(buf) != 0)
1608 ereport(LOG,
1610 errmsg("could not remove file \"%s\": %m", buf)));
1611 }
1612
1613 FreeDir(s_dir);
1614}
int errcode_for_file_access(void)
Definition elog.c:898
#define LOG
Definition elog.h:32
#define ereport(elevel,...)
Definition elog.h:152
int FreeDir(DIR *dir)
Definition fd.c:3009
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition fd.c:2972
DIR * AllocateDir(const char *dirname)
Definition fd.c:2891
static char * errmsg
#define MAXPGPATH
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:261
#define SNAPSHOT_EXPORT_DIR
Definition snapmgr.c:203
Definition dirent.c:26

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

Referenced by StartupXLOG().

◆ EstimateSnapshotSpace()

Size EstimateSnapshotSpace ( Snapshot  snapshot)

Definition at line 1711 of file snapmgr.c.

1712{
1713 Size size;
1714
1715 Assert(snapshot != InvalidSnapshot);
1716 Assert(snapshot->snapshot_type == SNAPSHOT_MVCC);
1717
1718 /* We allocate any XID arrays needed in the same palloc block. */
1719 size = add_size(sizeof(SerializedSnapshotData),
1720 mul_size(snapshot->xcnt, sizeof(TransactionId)));
1721 if (snapshot->subxcnt > 0 &&
1722 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
1723 size = add_size(size,
1724 mul_size(snapshot->subxcnt, sizeof(TransactionId)));
1725
1726 return size;
1727}
Size add_size(Size s1, Size s2)
Definition mcxt.c:1733
Size mul_size(Size s1, Size s2)
Definition mcxt.c:1752
@ 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 export_initial_snapshot(), index_parallelscan_estimate(), index_parallelscan_initialize(), InitializeParallelDSM(), and table_parallelscan_estimate().

◆ ExportSnapshot()

char * ExportSnapshot ( Snapshot  snapshot)

Definition at line 1115 of file snapmgr.c.

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

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

Referenced by pg_export_snapshot(), and SnapBuildExportSnapshot().

◆ FreeSnapshot()

static void FreeSnapshot ( Snapshot  snapshot)
static

Definition at line 664 of file snapmgr.c.

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

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

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

◆ GetActiveSnapshot()

◆ GetCatalogSnapshot()

Snapshot GetCatalogSnapshot ( Oid  relid)

Definition at line 385 of file snapmgr.c.

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

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

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

◆ GetLatestSnapshot()

Snapshot GetLatestSnapshot ( void  )

Definition at line 354 of file snapmgr.c.

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

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

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

◆ GetNonHistoricCatalogSnapshot()

Snapshot GetNonHistoricCatalogSnapshot ( Oid  relid)

Definition at line 407 of file snapmgr.c.

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

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

Referenced by GetCatalogSnapshot(), and ScanPgRelation().

◆ GetTransactionSnapshot()

Snapshot GetTransactionSnapshot ( void  )

Definition at line 272 of file snapmgr.c.

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

References Assert, CopySnapshot(), CurrentSnapshot, CurrentSnapshotData, elog, ERROR, fb(), 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(), DefineIndex(), detachPartitionTable(), DisableSubscriptionAndExit(), do_autovacuum(), EnsurePortalSnapshotExists(), EventTriggerOnLogin(), exec_bind_message(), exec_eval_simple_expr(), exec_parse_message(), exec_simple_query(), ExecRepack(), 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(), process_single_relation(), ReindexMultipleInternal(), ReindexRelationConcurrently(), RemoveTempRelationsCallback(), RevalidateCachedQuery(), ri_FastPathBatchFlush(), ri_FastPathCheck(), 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 1643 of file snapmgr.c.

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

References ActiveSnapshot, CatalogSnapshot, fb(), pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

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

◆ HistoricSnapshotActive()

◆ HistoricSnapshotGetTupleCids()

HTAB * HistoricSnapshotGetTupleCids ( void  )

Definition at line 1697 of file snapmgr.c.

1698{
1700 return tuplecid_data;
1701}
static HTAB * tuplecid_data
Definition snapmgr.c:163

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

◆ ImportSnapshot()

void ImportSnapshot ( const char idstr)

Definition at line 1386 of file snapmgr.c.

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

References AllocateFile(), elog, ereport, errcode(), errcode_for_file_access(), errmsg, ERROR, fb(), 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, 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 1306 of file snapmgr.c.

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

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

Referenced by ImportSnapshot().

◆ parseVxidFromText()

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

Definition at line 1356 of file snapmgr.c.

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

References ereport, errcode(), errmsg, ERROR, fb(), 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 1331 of file snapmgr.c.

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

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

Referenced by ImportSnapshot().

◆ pg_export_snapshot()

Datum pg_export_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 1291 of file snapmgr.c.

1292{
1293 char *snapshotName;
1294
1297}
#define PG_RETURN_TEXT_P(x)
Definition fmgr.h:374
char * ExportSnapshot(Snapshot snapshot)
Definition snapmgr.c:1115
Snapshot GetActiveSnapshot(void)
Definition snapmgr.c:800
text * cstring_to_text(const char *s)
Definition varlena.c:184

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

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 775 of file snapmgr.c.

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

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

◆ PushActiveSnapshot()

void PushActiveSnapshot ( Snapshot  snapshot)

◆ PushActiveSnapshotWithLevel()

void PushActiveSnapshotWithLevel ( Snapshot  snapshot,
int  snap_level 
)

Definition at line 696 of file snapmgr.c.

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

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

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

◆ PushCopiedSnapshot()

void PushCopiedSnapshot ( Snapshot  snapshot)

Definition at line 732 of file snapmgr.c.

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

References CopySnapshot(), and PushActiveSnapshot().

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

◆ RegisterSnapshot()

◆ RegisterSnapshotOnOwner()

Snapshot RegisterSnapshotOnOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 837 of file snapmgr.c.

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

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

Referenced by be_lo_open(), and RegisterSnapshot().

◆ ResourceOwnerForgetSnapshot()

static void ResourceOwnerForgetSnapshot ( ResourceOwner  owner,
Snapshot  snap 
)
inlinestatic

Definition at line 240 of file snapmgr.c.

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

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

Referenced by UnregisterSnapshotFromOwner().

◆ ResourceOwnerRememberSnapshot()

static void ResourceOwnerRememberSnapshot ( ResourceOwner  owner,
Snapshot  snap 
)
inlinestatic

Definition at line 235 of file snapmgr.c.

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

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

Referenced by RegisterSnapshotOnOwner().

◆ ResOwnerReleaseSnapshot()

static void ResOwnerReleaseSnapshot ( Datum  res)
static

Definition at line 1967 of file snapmgr.c.

1968{
1970}
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static void UnregisterSnapshotNoOwner(Snapshot snapshot)
Definition snapmgr.c:889

References DatumGetPointer(), and UnregisterSnapshotNoOwner().

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char start_address)

Definition at line 1792 of file snapmgr.c.

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

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

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

◆ RestoreTransactionSnapshot()

void RestoreTransactionSnapshot ( Snapshot  snapshot,
PGPROC source_pgproc 
)

Definition at line 1852 of file snapmgr.c.

1853{
1855}
#define InvalidPid
Definition miscadmin.h:32

References fb(), InvalidPid, and SetTransactionSnapshot().

Referenced by CreateReplicationSlot(), and ParallelWorkerMain().

◆ SerializeSnapshot()

void SerializeSnapshot ( Snapshot  snapshot,
char start_address 
)

Definition at line 1735 of file snapmgr.c.

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

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

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

◆ SetTransactionSnapshot()

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

Definition at line 511 of file snapmgr.c.

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

References Assert, CopySnapshot(), CurrentSnapshot, CurrentSnapshotData, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), FirstSnapshotSet, FirstXactSnapshot, GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotData(), HistoricSnapshotActive(), InvalidateCatalogSnapshot(), IsolationIsSerializable, IsolationUsesXactSnapshot, memcpy(), 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 1668 of file snapmgr.c.

1669{
1671
1672 /* setup the timetravel snapshot */
1674
1675 /* setup (cmin, cmax) lookup hash */
1676 tuplecid_data = tuplecids;
1677}

References Assert, fb(), HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ SnapshotResetXmin()

static void SnapshotResetXmin ( void  )
static

◆ SnapshotSetCommandId()

void SnapshotSetCommandId ( CommandId  curcid)

Definition at line 490 of file snapmgr.c.

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

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

Referenced by CommandCounterIncrement().

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 1684 of file snapmgr.c.

1685{
1688}

References fb(), HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1625 of file snapmgr.c.

1626{
1629 return true;
1630
1631 return false;
1632}

References pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by CopyFrom().

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 879 of file snapmgr.c.

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

References fb(), ResourceOwnerForgetSnapshot(), and UnregisterSnapshotNoOwner().

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

◆ UnregisterSnapshotNoOwner()

static void UnregisterSnapshotNoOwner ( Snapshot  snapshot)
static

Definition at line 889 of file snapmgr.c.

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

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

Referenced by ResOwnerReleaseSnapshot(), and UnregisterSnapshotFromOwner().

◆ UpdateActiveSnapshotCommandId()

void UpdateActiveSnapshotCommandId ( void  )

Definition at line 744 of file snapmgr.c.

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

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

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

◆ XactHasExportedSnapshots()

bool XactHasExportedSnapshots ( void  )

Definition at line 1573 of file snapmgr.c.

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

References exportedSnapshots, and NIL.

Referenced by PrepareTransaction().

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 1868 of file snapmgr.c.

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

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

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

◆ xmin_cmp()

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

Definition at line 910 of file snapmgr.c.

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

References a, b, fb(), pairingheap_const_container, TransactionIdFollows(), and TransactionIdPrecedes().

Variable Documentation

◆ ActiveSnapshot

◆ CatalogSnapshot

◆ CatalogSnapshotData

SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 143 of file snapmgr.c.

Referenced by GetNonHistoricCatalogSnapshot().

◆ CurrentSnapshot

◆ CurrentSnapshotData

SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 141 of file snapmgr.c.

Referenced by GetTransactionSnapshot(), and SetTransactionSnapshot().

◆ exportedSnapshots

List* exportedSnapshots = NIL
static

Definition at line 213 of file snapmgr.c.

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

◆ FirstSnapshotSet

◆ FirstXactSnapshot

Snapshot FirstXactSnapshot = NULL
static

Definition at line 200 of file snapmgr.c.

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

◆ HistoricSnapshot

◆ RecentXmin

◆ RegisteredSnapshots

◆ SecondarySnapshot

Snapshot SecondarySnapshot = NULL
static

◆ SecondarySnapshotData

SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 142 of file snapmgr.c.

Referenced by GetLatestSnapshot().

◆ snapshot_resowner_desc

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

Definition at line 224 of file snapmgr.c.

225{
226 .name = "snapshot reference",
227 .release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
228 .release_priority = RELEASE_PRIO_SNAPSHOT_REFS,
229 .ReleaseResource = ResOwnerReleaseSnapshot,
230 .DebugPrint = NULL /* the default message is fine */
231};

Referenced by ResourceOwnerForgetSnapshot(), and ResourceOwnerRememberSnapshot().

◆ SnapshotAnyData

SnapshotData SnapshotAnyData = {SNAPSHOT_ANY}

Definition at line 145 of file snapmgr.c.

@ SNAPSHOT_ANY
Definition snapshot.h:65

◆ SnapshotSelfData

SnapshotData SnapshotSelfData = {SNAPSHOT_SELF}

Definition at line 144 of file snapmgr.c.

@ SNAPSHOT_SELF
Definition snapshot.h:60

◆ SnapshotToastData

SnapshotData SnapshotToastData = {SNAPSHOT_TOAST}

Definition at line 146 of file snapmgr.c.

@ SNAPSHOT_TOAST
Definition snapshot.h:70

Referenced by get_toast_snapshot().

◆ TransactionXmin

◆ tuplecid_data