145 #define SNAPSHOT_EXPORT_DIR "pg_snapshots"
168 .
name =
"snapshot reference",
244 "cannot take query snapshot during a parallel operation");
299 "cannot update SecondarySnapshot during a parallel operation");
325 Snapshot OldestRegisteredSnapshot = NULL;
332 RegisteredLSN = OldestRegisteredSnapshot->
lsn;
343 return OldestRegisteredSnapshot;
478 int sourcepid,
PGPROC *sourceproc)
505 if (sourcesnap->
xcnt > 0)
530 if (sourceproc != NULL)
534 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
535 errmsg(
"could not import the requested snapshot"),
536 errdetail(
"The source transaction is not running anymore.")));
540 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
541 errmsg(
"could not import the requested snapshot"),
542 errdetail(
"The source process with PID %d is not running anymore.",
597 if (snapshot->
xcnt > 0)
600 memcpy(newsnap->
xip, snapshot->
xip,
732 elog(
ERROR,
"cannot modify commandid in active snapshot during a parallel operation");
838 if (snapshot == NULL)
851 if (snapshot == NULL)
1056 elog(
WARNING,
"registered snapshots seem to remain after cleanup");
1060 elog(
WARNING,
"snapshot %p still active", active);
1135 (
errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1136 errmsg(
"cannot export a snapshot from a subtransaction")));
1201 for (
i = 0;
i < snapshot->
xcnt;
i++)
1219 for (
i = 0;
i < nchildren;
i++)
1230 snprintf(pathtmp,
sizeof(pathtmp),
"%s.tmp", path);
1234 errmsg(
"could not create file \"%s\": %m", pathtmp)));
1236 if (fwrite(
buf.data,
buf.len, 1, f) != 1)
1239 errmsg(
"could not write to file \"%s\": %m", pathtmp)));
1246 errmsg(
"could not write to file \"%s\": %m", pathtmp)));
1252 if (rename(pathtmp, path) < 0)
1255 errmsg(
"could not rename file \"%s\" to \"%s\": %m",
1290 int prefixlen = strlen(prefix);
1293 if (strncmp(ptr, prefix, prefixlen) != 0)
1295 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1298 if (sscanf(ptr,
"%d", &
val) != 1)
1300 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1302 ptr = strchr(ptr,
'\n');
1305 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1315 int prefixlen = strlen(prefix);
1318 if (strncmp(ptr, prefix, prefixlen) != 0)
1320 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1323 if (sscanf(ptr,
"%u", &
val) != 1)
1325 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1327 ptr = strchr(ptr,
'\n');
1330 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1341 int prefixlen = strlen(prefix);
1343 if (strncmp(ptr, prefix, prefixlen) != 0)
1345 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1350 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1352 ptr = strchr(ptr,
'\n');
1355 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1371 struct stat stat_buf;
1392 (
errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1393 errmsg(
"SET TRANSACTION SNAPSHOT must be called before any query")));
1401 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1402 errmsg(
"a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ")));
1408 if (strspn(idstr,
"0123456789ABCDEF-") != strlen(idstr))
1410 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1411 errmsg(
"invalid snapshot identifier: \"%s\"", idstr)));
1423 if (errno == ENOENT)
1425 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1426 errmsg(
"snapshot \"%s\" does not exist", idstr)));
1430 errmsg(
"could not open file \"%s\" for reading: %m",
1435 if (
fstat(fileno(f), &stat_buf))
1436 elog(
ERROR,
"could not stat file \"%s\": %m", path);
1440 if (fread(filebuf, stat_buf.
st_size, 1, f) != 1)
1441 elog(
ERROR,
"could not read file \"%s\": %m", path);
1443 filebuf[stat_buf.
st_size] =
'\0';
1450 memset(&snapshot, 0,
sizeof(snapshot));
1469 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1470 errmsg(
"invalid snapshot data in file \"%s\"", path)));
1473 for (
i = 0;
i < xcnt;
i++)
1485 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1486 errmsg(
"invalid snapshot data in file \"%s\"", path)));
1489 for (
i = 0;
i < xcnt;
i++)
1510 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1511 errmsg(
"invalid snapshot data in file \"%s\"", path)));
1523 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1524 errmsg(
"a serializable transaction cannot import a snapshot from a non-serializable transaction")));
1527 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1528 errmsg(
"a non-read-only serializable transaction cannot import a snapshot from a read-only transaction")));
1542 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1543 errmsg(
"cannot import a snapshot from a different database")));
1582 if (strcmp(s_de->
d_name,
".") == 0 ||
1583 strcmp(s_de->
d_name,
"..") == 0)
1588 if (unlink(
buf) != 0)
1591 errmsg(
"could not remove file \"%s\": %m",
buf)));
1651 Assert(historic_snapshot != NULL);
1723 serialized_snapshot.
xmin = snapshot->
xmin;
1724 serialized_snapshot.
xmax = snapshot->
xmax;
1725 serialized_snapshot.
xcnt = snapshot->
xcnt;
1731 serialized_snapshot.
lsn = snapshot->
lsn;
1739 serialized_snapshot.
subxcnt = 0;
1742 memcpy(start_address,
1746 if (snapshot->
xcnt > 0)
1757 if (serialized_snapshot.
subxcnt > 0)
1782 memcpy(&serialized_snapshot, start_address,
1795 snapshot->
xmin = serialized_snapshot.
xmin;
1796 snapshot->
xmax = serialized_snapshot.
xmax;
1797 snapshot->
xip = NULL;
1798 snapshot->
xcnt = serialized_snapshot.
xcnt;
1805 snapshot->
lsn = serialized_snapshot.
lsn;
1809 if (serialized_snapshot.
xcnt > 0)
1812 memcpy(snapshot->
xip, serialized_xids,
1817 if (serialized_snapshot.
subxcnt > 0)
1820 serialized_snapshot.
xcnt;
1821 memcpy(snapshot->
subxip, serialized_xids + serialized_snapshot.
xcnt,
#define Assert(condition)
#define OidIsValid(objectId)
static void PGresult * res
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
FILE * AllocateFile(const char *name, const char *mode)
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
DIR * AllocateDir(const char *dirname)
#define PG_RETURN_TEXT_P(x)
List * lappend(List *list, void *datum)
#define VirtualTransactionIdIsValid(vxid)
MemoryContext TopTransactionContext
char * pstrdup(const char *in)
void pfree(void *pointer)
void * MemoryContextAlloc(MemoryContext context, Size size)
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
pairingheap_node * pairingheap_first(pairingheap *heap)
#define pairingheap_is_empty(h)
#define pairingheap_is_singular(h)
#define pairingheap_container(type, membername, ptr)
#define pairingheap_const_container(type, membername, ptr)
#define pairingheap_reset(h)
static bool pg_lfind32(uint32 key, const uint32 *base, uint32 nelem)
static int list_length(const List *l)
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
void SetSerializableTransactionSnapshot(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
int GetMaxSnapshotSubxidCount(void)
Snapshot GetSnapshotData(Snapshot snapshot)
int GetMaxSnapshotXidCount(void)
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
MemoryContextSwitchTo(old_ctx)
ResourceOwner CurrentResourceOwner
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerEnlarge(ResourceOwner owner)
#define RELEASE_PRIO_SNAPSHOT_REFS
@ RESOURCE_RELEASE_AFTER_LOCKS
Size add_size(Size s1, Size s2)
Size mul_size(Size s1, Size s2)
static pg_noinline void Size size
static Snapshot HistoricSnapshot
static Snapshot FirstXactSnapshot
SnapshotData CatalogSnapshotData
void UnregisterSnapshotFromOwner(Snapshot snapshot, ResourceOwner owner)
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
void AtSubAbort_Snapshot(int level)
void SerializeSnapshot(Snapshot snapshot, char *start_address)
SnapshotData SnapshotSelfData
void AtEOXact_Snapshot(bool isCommit, bool resetXmin)
struct ActiveSnapshotElt ActiveSnapshotElt
static Snapshot CurrentSnapshot
static Snapshot SecondarySnapshot
bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
static List * exportedSnapshots
static pairingheap RegisteredSnapshots
static void UnregisterSnapshotNoOwner(Snapshot snapshot)
Snapshot GetTransactionSnapshot(void)
Snapshot GetLatestSnapshot(void)
void TeardownHistoricSnapshot(bool is_error)
Snapshot GetCatalogSnapshot(Oid relid)
void UnregisterSnapshot(Snapshot snapshot)
void PushActiveSnapshot(Snapshot snapshot)
static Snapshot CopySnapshot(Snapshot snapshot)
static ActiveSnapshotElt * OldestActiveSnapshot
Snapshot RestoreSnapshot(char *start_address)
HTAB * HistoricSnapshotGetTupleCids(void)
void AtSubCommit_Snapshot(int level)
static void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snap)
void UpdateActiveSnapshotCommandId(void)
static void SnapshotResetXmin(void)
static int parseIntFromText(const char *prefix, char **s, const char *filename)
static SnapshotData SecondarySnapshotData
char * ExportSnapshot(Snapshot snapshot)
static int xmin_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
TransactionId TransactionXmin
SnapshotData SnapshotAnyData
bool HistoricSnapshotActive(void)
void ImportSnapshot(const char *idstr)
bool ActiveSnapshotSet(void)
Snapshot RegisterSnapshot(Snapshot snapshot)
bool XactHasExportedSnapshots(void)
static const ResourceOwnerDesc snapshot_resowner_desc
void DeleteAllExportedSnapshotFiles(void)
static void parseVxidFromText(const char *prefix, char **s, const char *filename, VirtualTransactionId *vxid)
static void FreeSnapshot(Snapshot snapshot)
#define SNAPSHOT_EXPORT_DIR
bool HaveRegisteredOrActiveSnapshot(void)
void InvalidateCatalogSnapshotConditionally(void)
static SnapshotData CurrentSnapshotData
static void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snap)
bool ThereAreNoPriorRegisteredSnapshots(void)
void RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc)
void SnapshotSetCommandId(CommandId curcid)
struct SerializedSnapshotData SerializedSnapshotData
void PopActiveSnapshot(void)
void PushCopiedSnapshot(Snapshot snapshot)
Size EstimateSnapshotSpace(Snapshot snapshot)
static ActiveSnapshotElt * ActiveSnapshot
void SetupHistoricSnapshot(Snapshot historic_snapshot, HTAB *tuplecids)
static HTAB * tuplecid_data
Snapshot RegisterSnapshotOnOwner(Snapshot snapshot, ResourceOwner owner)
static TransactionId parseXidFromText(const char *prefix, char **s, const char *filename)
void InvalidateCatalogSnapshot(void)
void PushActiveSnapshotWithLevel(Snapshot snapshot, int snap_level)
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
struct ExportedSnapshot ExportedSnapshot
Snapshot GetOldestSnapshot(void)
static Snapshot CatalogSnapshot
Snapshot GetActiveSnapshot(void)
Datum pg_export_snapshot(PG_FUNCTION_ARGS)
static void ResOwnerReleaseSnapshot(Datum res)
struct SnapshotData * Snapshot
struct SnapshotData SnapshotData
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoString(StringInfo str, const char *s)
void initStringInfo(StringInfo str)
struct ActiveSnapshotElt * as_next
uint64 snapXactCompletionCount
SnapshotType snapshot_type
LocalTransactionId localTransactionId
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
bool RelationHasSysCache(Oid relid)
bool RelationInvalidatesSnapshotsOnly(Oid relid)
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
#define InvalidTransactionId
#define FirstNormalTransactionId
#define TransactionIdIsValid(xid)
#define TransactionIdIsNormal(xid)
text * cstring_to_text(const char *s)
int GetCurrentTransactionNestLevel(void)
TransactionId GetTopTransactionIdIfAny(void)
bool IsSubTransaction(void)
bool IsInParallelMode(void)
int xactGetCommittedChildren(TransactionId **ptr)
CommandId GetCurrentCommandId(bool used)
#define XACT_SERIALIZABLE
#define IsolationUsesXactSnapshot()
#define IsolationIsSerializable()
#define XLogRecPtrIsInvalid(r)
#define InvalidXLogRecPtr