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

Typedef Documentation

◆ ActiveSnapshotElt

◆ ExportedSnapshot

◆ SerializedSnapshotData

Function Documentation

◆ ActiveSnapshotSet()

◆ AtEOXact_Snapshot()

void AtEOXact_Snapshot ( bool  isCommit,
bool  resetXmin 
)

Definition at line 944 of file snapmgr.c.

945{
946 /*
947 * In transaction-snapshot mode we must release our privately-managed
948 * reference to the transaction snapshot. We must remove it from
949 * RegisteredSnapshots to keep the check below happy. But we don't bother
950 * to do FreeSnapshot, for two reasons: the memory will go away with
951 * TopTransactionContext anyway, and if someone has left the snapshot
952 * stacked as active, we don't want the code below to be chasing through a
953 * dangling pointer.
954 */
955 if (FirstXactSnapshot != NULL)
956 {
960 }
961 FirstXactSnapshot = NULL;
962
963 /*
964 * If we exported any snapshots, clean them up.
965 */
966 if (exportedSnapshots != NIL)
967 {
968 ListCell *lc;
969
970 /*
971 * Get rid of the files. Unlink failure is only a WARNING because (1)
972 * it's too late to abort the transaction, and (2) leaving a leaked
973 * file around has little real consequence anyway.
974 *
975 * We also need to remove the snapshots from RegisteredSnapshots to
976 * prevent a warning below.
977 *
978 * As with the FirstXactSnapshot, we don't need to free resources of
979 * the snapshot itself as it will go away with the memory context.
980 */
981 foreach(lc, exportedSnapshots)
982 {
984
985 if (unlink(esnap->snapfile))
986 elog(WARNING, "could not unlink file \"%s\": %m",
987 esnap->snapfile);
988
990 &esnap->snapshot->ph_node);
991 }
992
994 }
995
996 /* Drop catalog snapshot if any */
998
999 /* On commit, complain about leftover snapshots */
1000 if (isCommit)
1001 {
1002 ActiveSnapshotElt *active;
1003
1005 elog(WARNING, "registered snapshots seem to remain after cleanup");
1006
1007 /* complain about unpopped active snapshots */
1008 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1009 elog(WARNING, "snapshot %p still active", active);
1010 }
1011
1012 /*
1013 * And reset our state. We don't need to free the memory explicitly --
1014 * it'll go away with TopTransactionContext.
1015 */
1016 ActiveSnapshot = NULL;
1018
1019 CurrentSnapshot = NULL;
1020 SecondarySnapshot = NULL;
1021
1022 FirstSnapshotSet = false;
1023
1024 /*
1025 * During normal commit processing, we call ProcArrayEndTransaction() to
1026 * reset the MyProc->xmin. That call happens prior to the call to
1027 * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1028 */
1029 if (resetXmin)
1031
1032 Assert(resetXmin || MyProc->xmin == 0);
1033}
#define Assert(condition)
Definition: c.h:812
#define WARNING
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:225
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:140
static Snapshot CurrentSnapshot
Definition: snapmgr.c:89
static Snapshot SecondarySnapshot
Definition: snapmgr.c:90
static List * exportedSnapshots
Definition: snapmgr.c:153
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:130
bool FirstSnapshotSet
Definition: snapmgr.c:133
static void SnapshotResetXmin(void)
Definition: snapmgr.c:865
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:384
PGPROC * MyProc
Definition: proc.c:66
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:117
char * snapfile
Definition: snapmgr.c:148
Snapshot snapshot
Definition: snapmgr.c:149
TransactionId xmin
Definition: proc.h:177
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 910 of file snapmgr.c.

911{
912 /* Forget the active snapshots set by this subtransaction */
913 while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
914 {
916
918
919 /*
920 * Decrement the snapshot's active count. If it's still registered or
921 * marked as active by an outer subtransaction, we can't free it yet.
922 */
925
929
930 /* and free the stack element */
932
934 }
935
937}
static int32 next
Definition: blutils.c:219
void pfree(void *pointer)
Definition: mcxt.c:1521
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:592
Snapshot as_snap
Definition: snapmgr.c:115
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 889 of file snapmgr.c.

890{
891 ActiveSnapshotElt *active;
892
893 /*
894 * Relabel the active snapshots set in this subtransaction as though they
895 * are owned by the parent subxact.
896 */
897 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
898 {
899 if (active->as_level < level)
900 break;
901 active->as_level = level - 1;
902 }
903}

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

Referenced by CommitSubTransaction().

◆ CopySnapshot()

static Snapshot CopySnapshot ( Snapshot  snapshot)
static

Definition at line 536 of file snapmgr.c.

537{
538 Snapshot newsnap;
539 Size subxipoff;
540 Size size;
541
542 Assert(snapshot != InvalidSnapshot);
543
544 /* We allocate any XID arrays needed in the same palloc block. */
545 size = subxipoff = sizeof(SnapshotData) +
546 snapshot->xcnt * sizeof(TransactionId);
547 if (snapshot->subxcnt > 0)
548 size += snapshot->subxcnt * sizeof(TransactionId);
549
551 memcpy(newsnap, snapshot, sizeof(SnapshotData));
552
553 newsnap->regd_count = 0;
554 newsnap->active_count = 0;
555 newsnap->copied = true;
556 newsnap->snapXactCompletionCount = 0;
557
558 /* setup XID array */
559 if (snapshot->xcnt > 0)
560 {
561 newsnap->xip = (TransactionId *) (newsnap + 1);
562 memcpy(newsnap->xip, snapshot->xip,
563 snapshot->xcnt * sizeof(TransactionId));
564 }
565 else
566 newsnap->xip = NULL;
567
568 /*
569 * Setup subXID array. Don't bother to copy it if it had overflowed,
570 * though, because it's not used anywhere in that case. Except if it's a
571 * snapshot taken during recovery; all the top-level XIDs are in subxip as
572 * well in that case, so we mustn't lose them.
573 */
574 if (snapshot->subxcnt > 0 &&
575 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
576 {
577 newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
578 memcpy(newsnap->subxip, snapshot->subxip,
579 snapshot->subxcnt * sizeof(TransactionId));
580 }
581 else
582 newsnap->subxip = NULL;
583
584 return newsnap;
585}
uint32 TransactionId
Definition: c.h:606
size_t Size
Definition: c.h:559
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
MemoryContext TopTransactionContext
Definition: mcxt.c:154
static pg_noinline void Size size
Definition: slab.c:607
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, size, 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 1515 of file snapmgr.c.

1516{
1517 char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1518 DIR *s_dir;
1519 struct dirent *s_de;
1520
1521 /*
1522 * Problems in reading the directory, or unlinking files, are reported at
1523 * LOG level. Since we're running in the startup process, ERROR level
1524 * would prevent database start, and it's not important enough for that.
1525 */
1527
1528 while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1529 {
1530 if (strcmp(s_de->d_name, ".") == 0 ||
1531 strcmp(s_de->d_name, "..") == 0)
1532 continue;
1533
1534 snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1535
1536 if (unlink(buf) != 0)
1537 ereport(LOG,
1539 errmsg("could not remove file \"%s\": %m", buf)));
1540 }
1541
1542 FreeDir(s_dir);
1543}
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:2983
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2946
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2865
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:238
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:143
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 1640 of file snapmgr.c.

1641{
1642 Size size;
1643
1644 Assert(snapshot != InvalidSnapshot);
1645 Assert(snapshot->snapshot_type == SNAPSHOT_MVCC);
1646
1647 /* We allocate any XID arrays needed in the same palloc block. */
1649 mul_size(snapshot->xcnt, sizeof(TransactionId)));
1650 if (snapshot->subxcnt > 0 &&
1651 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
1652 size = add_size(size,
1653 mul_size(snapshot->subxcnt, sizeof(TransactionId)));
1654
1655 return size;
1656}
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(), 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 1043 of file snapmgr.c.

1044{
1045 TransactionId topXid;
1046 TransactionId *children;
1047 ExportedSnapshot *esnap;
1048 int nchildren;
1049 int addTopXid;
1051 FILE *f;
1052 int i;
1053 MemoryContext oldcxt;
1054 char path[MAXPGPATH];
1055 char pathtmp[MAXPGPATH];
1056
1057 /*
1058 * It's tempting to call RequireTransactionBlock here, since it's not very
1059 * useful to export a snapshot that will disappear immediately afterwards.
1060 * However, we haven't got enough information to do that, since we don't
1061 * know if we're at top level or not. For example, we could be inside a
1062 * plpgsql function that is going to fire off other transactions via
1063 * dblink. Rather than disallow perfectly legitimate usages, don't make a
1064 * check.
1065 *
1066 * Also note that we don't make any restriction on the transaction's
1067 * isolation level; however, importers must check the level if they are
1068 * serializable.
1069 */
1070
1071 /*
1072 * Get our transaction ID if there is one, to include in the snapshot.
1073 */
1074 topXid = GetTopTransactionIdIfAny();
1075
1076 /*
1077 * We cannot export a snapshot from a subtransaction because there's no
1078 * easy way for importers to verify that the same subtransaction is still
1079 * running.
1080 */
1081 if (IsSubTransaction())
1082 ereport(ERROR,
1083 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1084 errmsg("cannot export a snapshot from a subtransaction")));
1085
1086 /*
1087 * We do however allow previous committed subtransactions to exist.
1088 * Importers of the snapshot must see them as still running, so get their
1089 * XIDs to add them to the snapshot.
1090 */
1091 nchildren = xactGetCommittedChildren(&children);
1092
1093 /*
1094 * Generate file path for the snapshot. We start numbering of snapshots
1095 * inside the transaction from 1.
1096 */
1097 snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%08X-%d",
1100
1101 /*
1102 * Copy the snapshot into TopTransactionContext, add it to the
1103 * exportedSnapshots list, and mark it pseudo-registered. We do this to
1104 * ensure that the snapshot's xmin is honored for the rest of the
1105 * transaction.
1106 */
1107 snapshot = CopySnapshot(snapshot);
1108
1110 esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
1111 esnap->snapfile = pstrdup(path);
1112 esnap->snapshot = snapshot;
1114 MemoryContextSwitchTo(oldcxt);
1115
1116 snapshot->regd_count++;
1118
1119 /*
1120 * Fill buf with a text serialization of the snapshot, plus identification
1121 * data about this transaction. The format expected by ImportSnapshot is
1122 * pretty rigid: each line must be fieldname:value.
1123 */
1125
1126 appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->vxid.procNumber, MyProc->vxid.lxid);
1127 appendStringInfo(&buf, "pid:%d\n", MyProcPid);
1128 appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1129 appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1130 appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1131
1132 appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1133 appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1134
1135 /*
1136 * We must include our own top transaction ID in the top-xid data, since
1137 * by definition we will still be running when the importing transaction
1138 * adopts the snapshot, but GetSnapshotData never includes our own XID in
1139 * the snapshot. (There must, therefore, be enough room to add it.)
1140 *
1141 * However, it could be that our topXid is after the xmax, in which case
1142 * we shouldn't include it because xip[] members are expected to be before
1143 * xmax. (We need not make the same check for subxip[] members, see
1144 * snapshot.h.)
1145 */
1146 addTopXid = (TransactionIdIsValid(topXid) &&
1147 TransactionIdPrecedes(topXid, snapshot->xmax)) ? 1 : 0;
1148 appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1149 for (i = 0; i < snapshot->xcnt; i++)
1150 appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1151 if (addTopXid)
1152 appendStringInfo(&buf, "xip:%u\n", topXid);
1153
1154 /*
1155 * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1156 * we have to cope with possible overflow.
1157 */
1158 if (snapshot->suboverflowed ||
1159 snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1160 appendStringInfoString(&buf, "sof:1\n");
1161 else
1162 {
1163 appendStringInfoString(&buf, "sof:0\n");
1164 appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1165 for (i = 0; i < snapshot->subxcnt; i++)
1166 appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1167 for (i = 0; i < nchildren; i++)
1168 appendStringInfo(&buf, "sxp:%u\n", children[i]);
1169 }
1170 appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1171
1172 /*
1173 * Now write the text representation into a file. We first write to a
1174 * ".tmp" filename, and rename to final filename if no error. This
1175 * ensures that no other backend can read an incomplete file
1176 * (ImportSnapshot won't allow it because of its valid-characters check).
1177 */
1178 snprintf(pathtmp, sizeof(pathtmp), "%s.tmp", path);
1179 if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1180 ereport(ERROR,
1182 errmsg("could not create file \"%s\": %m", pathtmp)));
1183
1184 if (fwrite(buf.data, buf.len, 1, f) != 1)
1185 ereport(ERROR,
1187 errmsg("could not write to file \"%s\": %m", pathtmp)));
1188
1189 /* no fsync() since file need not survive a system crash */
1190
1191 if (FreeFile(f))
1192 ereport(ERROR,
1194 errmsg("could not write to file \"%s\": %m", pathtmp)));
1195
1196 /*
1197 * Now that we have written everything into a .tmp file, rename the file
1198 * to remove the .tmp suffix.
1199 */
1200 if (rename(pathtmp, path) < 0)
1201 ereport(ERROR,
1203 errmsg("could not rename file \"%s\" to \"%s\": %m",
1204 pathtmp, path)));
1205
1206 /*
1207 * The basename of the file is what we return from pg_export_snapshot().
1208 * It's already in path in a textual format and we know that the path
1209 * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1210 * and pstrdup it so as not to return the address of a local variable.
1211 */
1212 return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1213}
#define PG_BINARY_W
Definition: c.h:1230
int errcode(int sqlerrcode)
Definition: elog.c:853
#define ERROR
Definition: elog.h:39
int FreeFile(FILE *file)
Definition: fd.c:2803
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2605
int MyProcPid
Definition: globals.c:46
Oid MyDatabaseId
Definition: globals.c:93
int i
Definition: isn.c:72
List * lappend(List *list, void *datum)
Definition: list.c:339
char * pstrdup(const char *in)
Definition: mcxt.c:1696
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:536
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:94
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
LocalTransactionId lxid
Definition: proc.h:200
struct PGPROC::@123 vxid
ProcNumber procNumber
Definition: proc.h:195
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:81
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:440
int XactIsoLevel
Definition: xact.c:78
bool IsSubTransaction(void)
Definition: xact.c:5036
int xactGetCommittedChildren(TransactionId **ptr)
Definition: xact.c:5778

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

593{
594 Assert(snapshot->regd_count == 0);
595 Assert(snapshot->active_count == 0);
596 Assert(snapshot->copied);
597
598 pfree(snapshot);
599}

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

315{
316 /*
317 * Return historic snapshot while we're doing logical decoding, so we can
318 * see the appropriate state of the catalog.
319 *
320 * This is the primary reason for needing to reset the system caches after
321 * finishing decoding.
322 */
324 return HistoricSnapshot;
325
326 return GetNonHistoricCatalogSnapshot(relid);
327}
static Snapshot HistoricSnapshot
Definition: snapmgr.c:92
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1620
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:336

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

284{
285 /*
286 * We might be able to relax this, but nothing that could otherwise work
287 * needs it.
288 */
289 if (IsInParallelMode())
290 elog(ERROR,
291 "cannot update SecondarySnapshot during a parallel operation");
292
293 /*
294 * So far there are no cases requiring support for GetLatestSnapshot()
295 * during logical decoding, but it wouldn't be hard to add if required.
296 */
298
299 /* If first call in transaction, go ahead and set the xact snapshot */
300 if (!FirstSnapshotSet)
301 return GetTransactionSnapshot();
302
304
305 return SecondarySnapshot;
306}
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2175
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:212
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:82
bool IsInParallelMode(void)
Definition: xact.c:1088

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

337{
338 /*
339 * If the caller is trying to scan a relation that has no syscache, no
340 * catcache invalidations will be sent when it is updated. For a few key
341 * relations, snapshot invalidations are sent instead. If we're trying to
342 * scan a relation for which neither catcache nor snapshot invalidations
343 * are sent, we must refresh the snapshot every time.
344 */
345 if (CatalogSnapshot &&
347 !RelationHasSysCache(relid))
349
350 if (CatalogSnapshot == NULL)
351 {
352 /* Get new snapshot. */
354
355 /*
356 * Make sure the catalog snapshot will be accounted for in decisions
357 * about advancing PGPROC->xmin. We could apply RegisterSnapshot, but
358 * that would result in making a physical copy, which is overkill; and
359 * it would also create a dependency on some resource owner, which we
360 * do not want for reasons explained at the head of this file. Instead
361 * just shove the CatalogSnapshot into the pairing heap manually. This
362 * has to be reversed in InvalidateCatalogSnapshot, of course.
363 *
364 * NB: it had better be impossible for this to throw error, since the
365 * CatalogSnapshot pointer is already valid.
366 */
368 }
369
370 return CatalogSnapshot;
371}
static SnapshotData CatalogSnapshotData
Definition: snapmgr.c:83
static Snapshot CatalogSnapshot
Definition: snapmgr.c:91
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 212 of file snapmgr.c.

213{
214 /*
215 * This should not be called while doing logical decoding. Historic
216 * snapshots are only usable for catalog access, not for general-purpose
217 * queries.
218 */
220 elog(ERROR, "cannot take query snapshot during logical decoding");
221
222 /* First call in transaction? */
223 if (!FirstSnapshotSet)
224 {
225 /*
226 * Don't allow catalog snapshot to be older than xact snapshot. Must
227 * do this first to allow the empty-heap Assert to succeed.
228 */
230
232 Assert(FirstXactSnapshot == NULL);
233
234 if (IsInParallelMode())
235 elog(ERROR,
236 "cannot take query snapshot during a parallel operation");
237
238 /*
239 * In transaction-snapshot mode, the first snapshot must live until
240 * end of xact regardless of what the caller does with it, so we must
241 * make a copy of it rather than returning CurrentSnapshotData
242 * directly. Furthermore, if we're running in serializable mode,
243 * predicate.c needs to wrap the snapshot fetch in its own processing.
244 */
246 {
247 /* First, create the snapshot in CurrentSnapshotData */
250 else
252 /* Make a saved copy */
255 /* Mark it as "registered" in FirstXactSnapshot */
258 }
259 else
261
262 FirstSnapshotSet = true;
263 return CurrentSnapshot;
264 }
265
267 return CurrentSnapshot;
268
269 /* Don't allow catalog snapshot to be older than xact snapshot. */
271
273
274 return CurrentSnapshot;
275}
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1672
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:81
#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(), _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 1572 of file snapmgr.c.

1573{
1574 if (ActiveSnapshot != NULL)
1575 return true;
1576
1577 /*
1578 * The catalog snapshot is in RegisteredSnapshots when valid, but can be
1579 * removed at any time due to invalidation processing. If explicitly
1580 * registered more than one snapshot has to be in RegisteredSnapshots.
1581 */
1582 if (CatalogSnapshot != NULL &&
1584 return false;
1585
1587}
#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 1626 of file snapmgr.c.

1627{
1629 return tuplecid_data;
1630}
static HTAB * tuplecid_data
Definition: snapmgr.c:103

References Assert, HistoricSnapshotActive(), and tuplecid_data.

Referenced by HeapTupleSatisfiesHistoricMVCC().

◆ ImportSnapshot()

void ImportSnapshot ( const char *  idstr)

Definition at line 1315 of file snapmgr.c.

1316{
1317 char path[MAXPGPATH];
1318 FILE *f;
1319 struct stat stat_buf;
1320 char *filebuf;
1321 int xcnt;
1322 int i;
1323 VirtualTransactionId src_vxid;
1324 int src_pid;
1325 Oid src_dbid;
1326 int src_isolevel;
1327 bool src_readonly;
1328 SnapshotData snapshot;
1329
1330 /*
1331 * Must be at top level of a fresh transaction. Note in particular that
1332 * we check we haven't acquired an XID --- if we have, it's conceivable
1333 * that the snapshot would show it as not running, making for very screwy
1334 * behavior.
1335 */
1336 if (FirstSnapshotSet ||
1339 ereport(ERROR,
1340 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1341 errmsg("SET TRANSACTION SNAPSHOT must be called before any query")));
1342
1343 /*
1344 * If we are in read committed mode then the next query would execute with
1345 * a new snapshot thus making this function call quite useless.
1346 */
1348 ereport(ERROR,
1349 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1350 errmsg("a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ")));
1351
1352 /*
1353 * Verify the identifier: only 0-9, A-F and hyphens are allowed. We do
1354 * this mainly to prevent reading arbitrary files.
1355 */
1356 if (strspn(idstr, "0123456789ABCDEF-") != strlen(idstr))
1357 ereport(ERROR,
1358 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1359 errmsg("invalid snapshot identifier: \"%s\"", idstr)));
1360
1361 /* OK, read the file */
1362 snprintf(path, MAXPGPATH, SNAPSHOT_EXPORT_DIR "/%s", idstr);
1363
1364 f = AllocateFile(path, PG_BINARY_R);
1365 if (!f)
1366 {
1367 /*
1368 * If file is missing while identifier has a correct format, avoid
1369 * system errors.
1370 */
1371 if (errno == ENOENT)
1372 ereport(ERROR,
1373 (errcode(ERRCODE_UNDEFINED_OBJECT),
1374 errmsg("snapshot \"%s\" does not exist", idstr)));
1375 else
1376 ereport(ERROR,
1378 errmsg("could not open file \"%s\" for reading: %m",
1379 path)));
1380 }
1381
1382 /* get the size of the file so that we know how much memory we need */
1383 if (fstat(fileno(f), &stat_buf))
1384 elog(ERROR, "could not stat file \"%s\": %m", path);
1385
1386 /* and read the file into a palloc'd string */
1387 filebuf = (char *) palloc(stat_buf.st_size + 1);
1388 if (fread(filebuf, stat_buf.st_size, 1, f) != 1)
1389 elog(ERROR, "could not read file \"%s\": %m", path);
1390
1391 filebuf[stat_buf.st_size] = '\0';
1392
1393 FreeFile(f);
1394
1395 /*
1396 * Construct a snapshot struct by parsing the file content.
1397 */
1398 memset(&snapshot, 0, sizeof(snapshot));
1399
1400 parseVxidFromText("vxid:", &filebuf, path, &src_vxid);
1401 src_pid = parseIntFromText("pid:", &filebuf, path);
1402 /* we abuse parseXidFromText a bit here ... */
1403 src_dbid = parseXidFromText("dbid:", &filebuf, path);
1404 src_isolevel = parseIntFromText("iso:", &filebuf, path);
1405 src_readonly = parseIntFromText("ro:", &filebuf, path);
1406
1407 snapshot.snapshot_type = SNAPSHOT_MVCC;
1408
1409 snapshot.xmin = parseXidFromText("xmin:", &filebuf, path);
1410 snapshot.xmax = parseXidFromText("xmax:", &filebuf, path);
1411
1412 snapshot.xcnt = xcnt = parseIntFromText("xcnt:", &filebuf, path);
1413
1414 /* sanity-check the xid count before palloc */
1415 if (xcnt < 0 || xcnt > GetMaxSnapshotXidCount())
1416 ereport(ERROR,
1417 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1418 errmsg("invalid snapshot data in file \"%s\"", path)));
1419
1420 snapshot.xip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1421 for (i = 0; i < xcnt; i++)
1422 snapshot.xip[i] = parseXidFromText("xip:", &filebuf, path);
1423
1424 snapshot.suboverflowed = parseIntFromText("sof:", &filebuf, path);
1425
1426 if (!snapshot.suboverflowed)
1427 {
1428 snapshot.subxcnt = xcnt = parseIntFromText("sxcnt:", &filebuf, path);
1429
1430 /* sanity-check the xid count before palloc */
1431 if (xcnt < 0 || xcnt > GetMaxSnapshotSubxidCount())
1432 ereport(ERROR,
1433 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1434 errmsg("invalid snapshot data in file \"%s\"", path)));
1435
1436 snapshot.subxip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1437 for (i = 0; i < xcnt; i++)
1438 snapshot.subxip[i] = parseXidFromText("sxp:", &filebuf, path);
1439 }
1440 else
1441 {
1442 snapshot.subxcnt = 0;
1443 snapshot.subxip = NULL;
1444 }
1445
1446 snapshot.takenDuringRecovery = parseIntFromText("rec:", &filebuf, path);
1447
1448 /*
1449 * Do some additional sanity checking, just to protect ourselves. We
1450 * don't trouble to check the array elements, just the most critical
1451 * fields.
1452 */
1453 if (!VirtualTransactionIdIsValid(src_vxid) ||
1454 !OidIsValid(src_dbid) ||
1455 !TransactionIdIsNormal(snapshot.xmin) ||
1456 !TransactionIdIsNormal(snapshot.xmax))
1457 ereport(ERROR,
1458 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1459 errmsg("invalid snapshot data in file \"%s\"", path)));
1460
1461 /*
1462 * If we're serializable, the source transaction must be too, otherwise
1463 * predicate.c has problems (SxactGlobalXmin could go backwards). Also, a
1464 * non-read-only transaction can't adopt a snapshot from a read-only
1465 * transaction, as predicate.c handles the cases very differently.
1466 */
1468 {
1469 if (src_isolevel != XACT_SERIALIZABLE)
1470 ereport(ERROR,
1471 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1472 errmsg("a serializable transaction cannot import a snapshot from a non-serializable transaction")));
1473 if (src_readonly && !XactReadOnly)
1474 ereport(ERROR,
1475 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1476 errmsg("a non-read-only serializable transaction cannot import a snapshot from a read-only transaction")));
1477 }
1478
1479 /*
1480 * We cannot import a snapshot that was taken in a different database,
1481 * because vacuum calculates OldestXmin on a per-database basis; so the
1482 * source transaction's xmin doesn't protect us from data loss. This
1483 * restriction could be removed if the source transaction were to mark its
1484 * xmin as being globally applicable. But that would require some
1485 * additional syntax, since that has to be known when the snapshot is
1486 * initially taken. (See pgsql-hackers discussion of 2011-10-21.)
1487 */
1488 if (src_dbid != MyDatabaseId)
1489 ereport(ERROR,
1490 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1491 errmsg("cannot import a snapshot from a different database")));
1492
1493 /* OK, install the snapshot */
1494 SetTransactionSnapshot(&snapshot, &src_vxid, src_pid, NULL);
1495}
#define PG_BINARY_R
Definition: c.h:1229
#define OidIsValid(objectId)
Definition: c.h:729
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:67
unsigned int Oid
Definition: postgres_ext.h:31
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:2069
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:439
static int parseIntFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1235
static void parseVxidFromText(const char *prefix, char **s, const char *filename, VirtualTransactionId *vxid)
Definition: snapmgr.c:1285
static TransactionId parseXidFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1260
#define InvalidTransactionId
Definition: transam.h:31
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define fstat
Definition: win32_port.h:281
#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 1235 of file snapmgr.c.

1236{
1237 char *ptr = *s;
1238 int prefixlen = strlen(prefix);
1239 int val;
1240
1241 if (strncmp(ptr, prefix, prefixlen) != 0)
1242 ereport(ERROR,
1243 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1244 errmsg("invalid snapshot data in file \"%s\"", filename)));
1245 ptr += prefixlen;
1246 if (sscanf(ptr, "%d", &val) != 1)
1247 ereport(ERROR,
1248 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1249 errmsg("invalid snapshot data in file \"%s\"", filename)));
1250 ptr = strchr(ptr, '\n');
1251 if (!ptr)
1252 ereport(ERROR,
1253 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1254 errmsg("invalid snapshot data in file \"%s\"", filename)));
1255 *s = ptr + 1;
1256 return val;
1257}
long val
Definition: informix.c:689
static char * filename
Definition: pg_dumpall.c:119

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

1287{
1288 char *ptr = *s;
1289 int prefixlen = strlen(prefix);
1290
1291 if (strncmp(ptr, prefix, prefixlen) != 0)
1292 ereport(ERROR,
1293 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1294 errmsg("invalid snapshot data in file \"%s\"", filename)));
1295 ptr += prefixlen;
1296 if (sscanf(ptr, "%d/%u", &vxid->procNumber, &vxid->localTransactionId) != 2)
1297 ereport(ERROR,
1298 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1299 errmsg("invalid snapshot data in file \"%s\"", filename)));
1300 ptr = strchr(ptr, '\n');
1301 if (!ptr)
1302 ereport(ERROR,
1303 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1304 errmsg("invalid snapshot data in file \"%s\"", filename)));
1305 *s = ptr + 1;
1306}
LocalTransactionId localTransactionId
Definition: lock.h:62
ProcNumber procNumber
Definition: lock.h:61

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

1261{
1262 char *ptr = *s;
1263 int prefixlen = strlen(prefix);
1265
1266 if (strncmp(ptr, prefix, prefixlen) != 0)
1267 ereport(ERROR,
1268 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1269 errmsg("invalid snapshot data in file \"%s\"", filename)));
1270 ptr += prefixlen;
1271 if (sscanf(ptr, "%u", &val) != 1)
1272 ereport(ERROR,
1273 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1274 errmsg("invalid snapshot data in file \"%s\"", filename)));
1275 ptr = strchr(ptr, '\n');
1276 if (!ptr)
1277 ereport(ERROR,
1278 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1279 errmsg("invalid snapshot data in file \"%s\"", filename)));
1280 *s = ptr + 1;
1281 return val;
1282}

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

Referenced by ImportSnapshot().

◆ pg_export_snapshot()

Datum pg_export_snapshot ( PG_FUNCTION_ARGS  )

Definition at line 1220 of file snapmgr.c.

1221{
1222 char *snapshotName;
1223
1224 snapshotName = ExportSnapshot(GetActiveSnapshot());
1225 PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1226}
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1043
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:728
text * cstring_to_text(const char *s)
Definition: varlena.c:184

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

◆ PopActiveSnapshot()

void PopActiveSnapshot ( void  )

Definition at line 703 of file snapmgr.c.

704{
705 ActiveSnapshotElt *newstack;
706
707 newstack = ActiveSnapshot->as_next;
708
710
712
716
718 ActiveSnapshot = newstack;
719
721}

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

625{
626 ActiveSnapshotElt *newactive;
627
628 Assert(snapshot != InvalidSnapshot);
629 Assert(ActiveSnapshot == NULL || snap_level >= ActiveSnapshot->as_level);
630
632
633 /*
634 * Checking SecondarySnapshot is probably useless here, but it seems
635 * better to be sure.
636 */
637 if (snapshot == CurrentSnapshot || snapshot == SecondarySnapshot ||
638 !snapshot->copied)
639 newactive->as_snap = CopySnapshot(snapshot);
640 else
641 newactive->as_snap = snapshot;
642
643 newactive->as_next = ActiveSnapshot;
644 newactive->as_level = snap_level;
645
646 newactive->as_snap->active_count++;
647
648 ActiveSnapshot = newactive;
649}

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

661{
663}
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:610

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

766{
767 Snapshot snap;
768
769 if (snapshot == InvalidSnapshot)
770 return InvalidSnapshot;
771
772 /* Static snapshot? Create a persistent copy */
773 snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
774
775 /* and tell resowner.c about it */
777 snap->regd_count++;
779
780 if (snap->regd_count == 1)
782
783 return snap;
784}
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442
static void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snap)
Definition: snapmgr.c:175

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

181{
183}
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:554
static const ResourceOwnerDesc snapshot_resowner_desc
Definition: snapmgr.c:164

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

Referenced by UnregisterSnapshotFromOwner().

◆ ResourceOwnerRememberSnapshot()

static void ResourceOwnerRememberSnapshot ( ResourceOwner  owner,
Snapshot  snap 
)
inlinestatic

Definition at line 175 of file snapmgr.c.

176{
178}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:514

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

Referenced by RegisterSnapshotOnOwner().

◆ ResOwnerReleaseSnapshot()

static void ResOwnerReleaseSnapshot ( Datum  res)
static

Definition at line 1899 of file snapmgr.c.

1900{
1902}
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static void UnregisterSnapshotNoOwner(Snapshot snapshot)
Definition: snapmgr.c:817

References DatumGetPointer(), res, and UnregisterSnapshotNoOwner().

◆ RestoreSnapshot()

Snapshot RestoreSnapshot ( char *  start_address)

Definition at line 1721 of file snapmgr.c.

1722{
1723 SerializedSnapshotData serialized_snapshot;
1724 Size size;
1725 Snapshot snapshot;
1726 TransactionId *serialized_xids;
1727
1728 memcpy(&serialized_snapshot, start_address,
1729 sizeof(SerializedSnapshotData));
1730 serialized_xids = (TransactionId *)
1731 (start_address + sizeof(SerializedSnapshotData));
1732
1733 /* We allocate any XID arrays needed in the same palloc block. */
1734 size = sizeof(SnapshotData)
1735 + serialized_snapshot.xcnt * sizeof(TransactionId)
1736 + serialized_snapshot.subxcnt * sizeof(TransactionId);
1737
1738 /* Copy all required fields */
1740 snapshot->snapshot_type = SNAPSHOT_MVCC;
1741 snapshot->xmin = serialized_snapshot.xmin;
1742 snapshot->xmax = serialized_snapshot.xmax;
1743 snapshot->xip = NULL;
1744 snapshot->xcnt = serialized_snapshot.xcnt;
1745 snapshot->subxip = NULL;
1746 snapshot->subxcnt = serialized_snapshot.subxcnt;
1747 snapshot->suboverflowed = serialized_snapshot.suboverflowed;
1748 snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
1749 snapshot->curcid = serialized_snapshot.curcid;
1750 snapshot->snapXactCompletionCount = 0;
1751
1752 /* Copy XIDs, if present. */
1753 if (serialized_snapshot.xcnt > 0)
1754 {
1755 snapshot->xip = (TransactionId *) (snapshot + 1);
1756 memcpy(snapshot->xip, serialized_xids,
1757 serialized_snapshot.xcnt * sizeof(TransactionId));
1758 }
1759
1760 /* Copy SubXIDs, if present. */
1761 if (serialized_snapshot.subxcnt > 0)
1762 {
1763 snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
1764 serialized_snapshot.xcnt;
1765 memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
1766 serialized_snapshot.subxcnt * sizeof(TransactionId));
1767 }
1768
1769 /* Set the copied flag so that the caller will set refcounts correctly. */
1770 snapshot->regd_count = 0;
1771 snapshot->active_count = 0;
1772 snapshot->copied = true;
1773
1774 return snapshot;
1775}
TransactionId xmax
Definition: snapmgr.c:194
TransactionId xmin
Definition: snapmgr.c:193
CommandId curcid
Definition: snapshot.h:183

References SnapshotData::active_count, SnapshotData::copied, SerializedSnapshotData::curcid, SnapshotData::curcid, MemoryContextAlloc(), SnapshotData::regd_count, size, 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 1784 of file snapmgr.c.

1785{
1786 SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
1787}
#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 1664 of file snapmgr.c.

1665{
1666 SerializedSnapshotData serialized_snapshot;
1667
1668 Assert(snapshot->subxcnt >= 0);
1669
1670 /* Copy all required fields */
1671 serialized_snapshot.xmin = snapshot->xmin;
1672 serialized_snapshot.xmax = snapshot->xmax;
1673 serialized_snapshot.xcnt = snapshot->xcnt;
1674 serialized_snapshot.subxcnt = snapshot->subxcnt;
1675 serialized_snapshot.suboverflowed = snapshot->suboverflowed;
1676 serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
1677 serialized_snapshot.curcid = snapshot->curcid;
1678
1679 /*
1680 * Ignore the SubXID array if it has overflowed, unless the snapshot was
1681 * taken during recovery - in that case, top-level XIDs are in subxip as
1682 * well, and we mustn't lose them.
1683 */
1684 if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
1685 serialized_snapshot.subxcnt = 0;
1686
1687 /* Copy struct to possibly-unaligned buffer */
1688 memcpy(start_address,
1689 &serialized_snapshot, sizeof(SerializedSnapshotData));
1690
1691 /* Copy XID array */
1692 if (snapshot->xcnt > 0)
1693 memcpy((TransactionId *) (start_address +
1694 sizeof(SerializedSnapshotData)),
1695 snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
1696
1697 /*
1698 * Copy SubXID array. Don't bother to copy it if it had overflowed,
1699 * though, because it's not used anywhere in that case. Except if it's a
1700 * snapshot taken during recovery; all the top-level XIDs are in subxip as
1701 * well in that case, so we mustn't lose them.
1702 */
1703 if (serialized_snapshot.subxcnt > 0)
1704 {
1705 Size subxipoff = sizeof(SerializedSnapshotData) +
1706 snapshot->xcnt * sizeof(TransactionId);
1707
1708 memcpy((TransactionId *) (start_address + subxipoff),
1709 snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
1710 }
1711}
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 439 of file snapmgr.c.

441{
442 /* Caller should have checked this already */
444
445 /* Better do this to ensure following Assert succeeds. */
447
449 Assert(FirstXactSnapshot == NULL);
451
452 /*
453 * Even though we are not going to use the snapshot it computes, we must
454 * call GetSnapshotData, for two reasons: (1) to be sure that
455 * CurrentSnapshotData's XID arrays have been allocated, and (2) to update
456 * the state for GlobalVis*.
457 */
459
460 /*
461 * Now copy appropriate fields from the source snapshot.
462 */
463 CurrentSnapshot->xmin = sourcesnap->xmin;
464 CurrentSnapshot->xmax = sourcesnap->xmax;
465 CurrentSnapshot->xcnt = sourcesnap->xcnt;
466 Assert(sourcesnap->xcnt <= GetMaxSnapshotXidCount());
467 if (sourcesnap->xcnt > 0)
468 memcpy(CurrentSnapshot->xip, sourcesnap->xip,
469 sourcesnap->xcnt * sizeof(TransactionId));
470 CurrentSnapshot->subxcnt = sourcesnap->subxcnt;
471 Assert(sourcesnap->subxcnt <= GetMaxSnapshotSubxidCount());
472 if (sourcesnap->subxcnt > 0)
473 memcpy(CurrentSnapshot->subxip, sourcesnap->subxip,
474 sourcesnap->subxcnt * sizeof(TransactionId));
477 /* NB: curcid should NOT be copied, it's a local matter */
478
480
481 /*
482 * Now we have to fix what GetSnapshotData did with MyProc->xmin and
483 * TransactionXmin. There is a race condition: to make sure we are not
484 * causing the global xmin to go backwards, we have to test that the
485 * source transaction is still running, and that has to be done
486 * atomically. So let procarray.c do it.
487 *
488 * Note: in serializable mode, predicate.c will do this a second time. It
489 * doesn't seem worth contorting the logic here to avoid two calls,
490 * especially since it's not clear that predicate.c *must* do this.
491 */
492 if (sourceproc != NULL)
493 {
496 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
497 errmsg("could not import the requested snapshot"),
498 errdetail("The source transaction is not running anymore.")));
499 }
500 else if (!ProcArrayInstallImportedXmin(CurrentSnapshot->xmin, sourcevxid))
502 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
503 errmsg("could not import the requested snapshot"),
504 errdetail("The source process with PID %d is not running anymore.",
505 sourcepid)));
506
507 /*
508 * In transaction-snapshot mode, the first snapshot must live until end of
509 * xact, so we must make a copy of it. Furthermore, if we're running in
510 * serializable mode, predicate.c needs to do its own processing.
511 */
513 {
516 sourcepid);
517 /* Make a saved copy */
520 /* Mark it as "registered" in FirstXactSnapshot */
523 }
524
525 FirstSnapshotSet = true;
526}
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 1597 of file snapmgr.c.

1598{
1599 Assert(historic_snapshot != NULL);
1600
1601 /* setup the timetravel snapshot */
1602 HistoricSnapshot = historic_snapshot;
1603
1604 /* setup (cmin, cmax) lookup hash */
1605 tuplecid_data = tuplecids;
1606}

References Assert, HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ SnapshotResetXmin()

static void SnapshotResetXmin ( void  )
static

Definition at line 865 of file snapmgr.c.

866{
867 Snapshot minSnapshot;
868
869 if (ActiveSnapshot != NULL)
870 return;
871
873 {
875 return;
876 }
877
878 minSnapshot = pairingheap_container(SnapshotData, ph_node,
880
881 if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin))
882 MyProc->xmin = TransactionXmin = minSnapshot->xmin;
883}
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:99

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

419{
420 if (!FirstSnapshotSet)
421 return;
422
423 if (CurrentSnapshot)
424 CurrentSnapshot->curcid = curcid;
426 SecondarySnapshot->curcid = curcid;
427 /* Should we do the same with CatalogSnapshot? */
428}

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

Referenced by CommandCounterIncrement().

◆ TeardownHistoricSnapshot()

void TeardownHistoricSnapshot ( bool  is_error)

Definition at line 1613 of file snapmgr.c.

1614{
1615 HistoricSnapshot = NULL;
1616 tuplecid_data = NULL;
1617}

References HistoricSnapshot, and tuplecid_data.

Referenced by ReorderBufferProcessTXN(), and ReorderBufferQueueMessage().

◆ ThereAreNoPriorRegisteredSnapshots()

bool ThereAreNoPriorRegisteredSnapshots ( void  )

Definition at line 1554 of file snapmgr.c.

1555{
1558 return true;
1559
1560 return false;
1561}

References pairingheap_is_empty, pairingheap_is_singular, and RegisteredSnapshots.

Referenced by CopyFrom().

◆ UnregisterSnapshot()

◆ UnregisterSnapshotFromOwner()

void UnregisterSnapshotFromOwner ( Snapshot  snapshot,
ResourceOwner  owner 
)

Definition at line 807 of file snapmgr.c.

808{
809 if (snapshot == NULL)
810 return;
811
812 ResourceOwnerForgetSnapshot(owner, snapshot);
814}
static void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snap)
Definition: snapmgr.c:180

References ResourceOwnerForgetSnapshot(), and UnregisterSnapshotNoOwner().

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

◆ UnregisterSnapshotNoOwner()

static void UnregisterSnapshotNoOwner ( Snapshot  snapshot)
static

Definition at line 817 of file snapmgr.c.

818{
819 Assert(snapshot->regd_count > 0);
821
822 snapshot->regd_count--;
823 if (snapshot->regd_count == 0)
825
826 if (snapshot->regd_count == 0 && snapshot->active_count == 0)
827 {
828 FreeSnapshot(snapshot);
830 }
831}

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

673{
674 CommandId save_curcid,
675 curcid;
676
677 Assert(ActiveSnapshot != NULL);
680
681 /*
682 * Don't allow modification of the active snapshot during parallel
683 * operation. We share the snapshot to worker backends at the beginning
684 * of parallel operation, so any change to the snapshot can lead to
685 * inconsistencies. We have other defenses against
686 * CommandCounterIncrement, but there are a few places that call this
687 * directly, so we put an additional guard here.
688 */
689 save_curcid = ActiveSnapshot->as_snap->curcid;
690 curcid = GetCurrentCommandId(false);
691 if (IsInParallelMode() && save_curcid != curcid)
692 elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
693 ActiveSnapshot->as_snap->curcid = curcid;
694}
uint32 CommandId
Definition: c.h:620
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:828

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

1503{
1504 return (exportedSnapshots != NIL);
1505}

References exportedSnapshots, and NIL.

Referenced by PrepareTransaction().

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 1800 of file snapmgr.c.

1801{
1802 /*
1803 * Make a quick range check to eliminate most XIDs without looking at the
1804 * xip arrays. Note that this is OK even if we convert a subxact XID to
1805 * its parent below, because a subxact with XID < xmin has surely also got
1806 * a parent with XID < xmin, while one with XID >= xmax must belong to a
1807 * parent that was not yet committed at the time of this snapshot.
1808 */
1809
1810 /* Any xid < xmin is not in-progress */
1811 if (TransactionIdPrecedes(xid, snapshot->xmin))
1812 return false;
1813 /* Any xid >= xmax is in-progress */
1814 if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
1815 return true;
1816
1817 /*
1818 * Snapshot information is stored slightly differently in snapshots taken
1819 * during recovery.
1820 */
1821 if (!snapshot->takenDuringRecovery)
1822 {
1823 /*
1824 * If the snapshot contains full subxact data, the fastest way to
1825 * check things is just to compare the given XID against both subxact
1826 * XIDs and top-level XIDs. If the snapshot overflowed, we have to
1827 * use pg_subtrans to convert a subxact XID to its parent XID, but
1828 * then we need only look at top-level XIDs not subxacts.
1829 */
1830 if (!snapshot->suboverflowed)
1831 {
1832 /* we have full data, so search subxip */
1833 if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1834 return true;
1835
1836 /* not there, fall through to search xip[] */
1837 }
1838 else
1839 {
1840 /*
1841 * Snapshot overflowed, so convert xid to top-level. This is safe
1842 * because we eliminated too-old XIDs above.
1843 */
1845
1846 /*
1847 * If xid was indeed a subxact, we might now have an xid < xmin,
1848 * so recheck to avoid an array scan. No point in rechecking
1849 * xmax.
1850 */
1851 if (TransactionIdPrecedes(xid, snapshot->xmin))
1852 return false;
1853 }
1854
1855 if (pg_lfind32(xid, snapshot->xip, snapshot->xcnt))
1856 return true;
1857 }
1858 else
1859 {
1860 /*
1861 * In recovery we store all xids in the subxip array because it is by
1862 * far the bigger array, and we mostly don't know which xids are
1863 * top-level and which are subxacts. The xip array is empty.
1864 *
1865 * We start by searching subtrans, if we overflowed.
1866 */
1867 if (snapshot->suboverflowed)
1868 {
1869 /*
1870 * Snapshot overflowed, so convert xid to top-level. This is safe
1871 * because we eliminated too-old XIDs above.
1872 */
1874
1875 /*
1876 * If xid was indeed a subxact, we might now have an xid < xmin,
1877 * so recheck to avoid an array scan. No point in rechecking
1878 * xmax.
1879 */
1880 if (TransactionIdPrecedes(xid, snapshot->xmin))
1881 return false;
1882 }
1883
1884 /*
1885 * We now have either a top-level xid higher than xmin or an
1886 * indeterminate xid. We don't know whether it's top level or subxact
1887 * but it doesn't matter. If it's present, the xid is visible.
1888 */
1889 if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1890 return true;
1891 }
1892
1893 return false;
1894}
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 838 of file snapmgr.c.

839{
840 const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
841 const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
842
843 if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
844 return 1;
845 else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
846 return -1;
847 else
848 return 0;
849}
int b
Definition: isn.c:69
int a
Definition: isn.c:68
#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 83 of file snapmgr.c.

Referenced by GetNonHistoricCatalogSnapshot().

◆ CurrentSnapshot

◆ CurrentSnapshotData

SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC}
static

Definition at line 81 of file snapmgr.c.

Referenced by GetTransactionSnapshot(), and SetTransactionSnapshot().

◆ exportedSnapshots

List* exportedSnapshots = NIL
static

Definition at line 153 of file snapmgr.c.

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

◆ FirstSnapshotSet

◆ FirstXactSnapshot

Snapshot FirstXactSnapshot = NULL
static

Definition at line 140 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 82 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:1899

Definition at line 164 of file snapmgr.c.

Referenced by ResourceOwnerForgetSnapshot(), and ResourceOwnerRememberSnapshot().

◆ SnapshotAnyData

SnapshotData SnapshotAnyData = {SNAPSHOT_ANY}

Definition at line 85 of file snapmgr.c.

◆ SnapshotSelfData

SnapshotData SnapshotSelfData = {SNAPSHOT_SELF}

Definition at line 84 of file snapmgr.c.

◆ SnapshotToastData

SnapshotData SnapshotToastData = {SNAPSHOT_TOAST}

Definition at line 86 of file snapmgr.c.

Referenced by get_toast_snapshot().

◆ TransactionXmin

◆ tuplecid_data