mirror of
https://github.com/postgres/postgres.git
synced 2025-05-13 01:13:08 -04:00
Move generic snapshot related code from tqual.h to snapmgr.h.
The code in tqual.c is largely heap specific. Due to the upcoming pluggable storage work, it therefore makes sense to move it into access/heap/ (as the file's header notes, the tqual name isn't very good). But the various statically allocated snapshot and snapshot initialization functions are now (see previous commit) generic and do not depend on functions declared in tqual.h anymore. Therefore move. Also move XidInMVCCSnapshot as that's useful for future AMs, and already used outside of tqual.c. Author: Andres Freund Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
This commit is contained in:
parent
63746189b2
commit
b7eda3e0e3
@ -36,7 +36,6 @@
|
||||
#include "storage/lmgr.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "commands/seclabel.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/tqual.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "sepgsql.h"
|
||||
|
||||
/*
|
||||
|
@ -24,8 +24,8 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
#include "sepgsql.h"
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
#include "utils/catcache.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
#include "sepgsql.h"
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/tqual.h"
|
||||
#include "utils/snapmgr.h"
|
||||
|
||||
#include "sepgsql.h"
|
||||
|
||||
|
@ -72,7 +72,6 @@
|
||||
#include "utils/rel.h"
|
||||
#include "utils/sortsupport.h"
|
||||
#include "utils/tuplesort.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
/* Magic numbers for parallel state sharing */
|
||||
|
@ -47,8 +47,8 @@
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/fmgrprotos.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -139,7 +139,6 @@
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/timestamp.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "executor/executor.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/tqual.h"
|
||||
#include "utils/snapmgr.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -113,7 +113,7 @@
|
||||
#include "executor/executor.h"
|
||||
#include "nodes/nodeFuncs.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "utils/tqual.h"
|
||||
#include "utils/snapmgr.h"
|
||||
|
||||
/* waitMode argument to check_exclusion_or_unique_constraint() */
|
||||
typedef enum
|
||||
|
@ -95,7 +95,7 @@
|
||||
#include "utils/pg_lsn.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
#include "utils/snapmgr.h"
|
||||
|
||||
/*
|
||||
* Replay progress of a single remote node.
|
||||
|
@ -136,7 +136,6 @@
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/snapshot.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
#include "storage/block.h" /* debugging output */
|
||||
#include "storage/fd.h"
|
||||
|
@ -146,7 +146,6 @@
|
||||
#include "utils/spccache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/timestamp.h"
|
||||
#include "utils/tqual.h"
|
||||
#include "utils/typcache.h"
|
||||
#include "utils/varlena.h"
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "access/subtrans.h"
|
||||
#include "access/transam.h"
|
||||
#include "access/xact.h"
|
||||
#include "access/xlog.h"
|
||||
@ -66,7 +67,6 @@
|
||||
#include "utils/resowner_private.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -144,6 +144,8 @@ static volatile OldSnapshotControlData *oldSnapshotControl;
|
||||
static SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC};
|
||||
static SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC};
|
||||
SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC};
|
||||
SnapshotData SnapshotSelfData = {SNAPSHOT_SELF};
|
||||
SnapshotData SnapshotAnyData = {SNAPSHOT_ANY};
|
||||
|
||||
/* Pointers to valid snapshots */
|
||||
static Snapshot CurrentSnapshot = NULL;
|
||||
@ -2192,3 +2194,125 @@ RestoreTransactionSnapshot(Snapshot snapshot, void *master_pgproc)
|
||||
{
|
||||
SetTransactionSnapshot(snapshot, NULL, InvalidPid, master_pgproc);
|
||||
}
|
||||
|
||||
/*
|
||||
* XidInMVCCSnapshot
|
||||
* Is the given XID still-in-progress according to the snapshot?
|
||||
*
|
||||
* Note: GetSnapshotData never stores either top xid or subxids of our own
|
||||
* backend into a snapshot, so these xids will not be reported as "running"
|
||||
* by this function. This is OK for current uses, because we always check
|
||||
* TransactionIdIsCurrentTransactionId first, except when it's known the
|
||||
* XID could not be ours anyway.
|
||||
*/
|
||||
bool
|
||||
XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
/*
|
||||
* Make a quick range check to eliminate most XIDs without looking at the
|
||||
* xip arrays. Note that this is OK even if we convert a subxact XID to
|
||||
* its parent below, because a subxact with XID < xmin has surely also got
|
||||
* a parent with XID < xmin, while one with XID >= xmax must belong to a
|
||||
* parent that was not yet committed at the time of this snapshot.
|
||||
*/
|
||||
|
||||
/* Any xid < xmin is not in-progress */
|
||||
if (TransactionIdPrecedes(xid, snapshot->xmin))
|
||||
return false;
|
||||
/* Any xid >= xmax is in-progress */
|
||||
if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Snapshot information is stored slightly differently in snapshots taken
|
||||
* during recovery.
|
||||
*/
|
||||
if (!snapshot->takenDuringRecovery)
|
||||
{
|
||||
/*
|
||||
* If the snapshot contains full subxact data, the fastest way to
|
||||
* check things is just to compare the given XID against both subxact
|
||||
* XIDs and top-level XIDs. If the snapshot overflowed, we have to
|
||||
* use pg_subtrans to convert a subxact XID to its parent XID, but
|
||||
* then we need only look at top-level XIDs not subxacts.
|
||||
*/
|
||||
if (!snapshot->suboverflowed)
|
||||
{
|
||||
/* we have full data, so search subxip */
|
||||
int32 j;
|
||||
|
||||
for (j = 0; j < snapshot->subxcnt; j++)
|
||||
{
|
||||
if (TransactionIdEquals(xid, snapshot->subxip[j]))
|
||||
return true;
|
||||
}
|
||||
|
||||
/* not there, fall through to search xip[] */
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Snapshot overflowed, so convert xid to top-level. This is safe
|
||||
* because we eliminated too-old XIDs above.
|
||||
*/
|
||||
xid = SubTransGetTopmostTransaction(xid);
|
||||
|
||||
/*
|
||||
* If xid was indeed a subxact, we might now have an xid < xmin,
|
||||
* so recheck to avoid an array scan. No point in rechecking
|
||||
* xmax.
|
||||
*/
|
||||
if (TransactionIdPrecedes(xid, snapshot->xmin))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < snapshot->xcnt; i++)
|
||||
{
|
||||
if (TransactionIdEquals(xid, snapshot->xip[i]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 j;
|
||||
|
||||
/*
|
||||
* In recovery we store all xids in the subxact array because it is by
|
||||
* far the bigger array, and we mostly don't know which xids are
|
||||
* top-level and which are subxacts. The xip array is empty.
|
||||
*
|
||||
* We start by searching subtrans, if we overflowed.
|
||||
*/
|
||||
if (snapshot->suboverflowed)
|
||||
{
|
||||
/*
|
||||
* Snapshot overflowed, so convert xid to top-level. This is safe
|
||||
* because we eliminated too-old XIDs above.
|
||||
*/
|
||||
xid = SubTransGetTopmostTransaction(xid);
|
||||
|
||||
/*
|
||||
* If xid was indeed a subxact, we might now have an xid < xmin,
|
||||
* so recheck to avoid an array scan. No point in rechecking
|
||||
* xmax.
|
||||
*/
|
||||
if (TransactionIdPrecedes(xid, snapshot->xmin))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have either a top-level xid higher than xmin or an
|
||||
* indeterminate xid. We don't know whether it's top level or subxact
|
||||
* but it doesn't matter. If it's present, the xid is visible.
|
||||
*/
|
||||
for (j = 0; j < snapshot->subxcnt; j++)
|
||||
{
|
||||
if (TransactionIdEquals(xid, snapshot->subxip[j]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -77,11 +77,6 @@
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
/* Static variables representing various special snapshot semantics */
|
||||
SnapshotData SnapshotSelfData = {SNAPSHOT_SELF};
|
||||
SnapshotData SnapshotAnyData = {SNAPSHOT_ANY};
|
||||
|
||||
|
||||
/*
|
||||
* SetHintBits()
|
||||
*
|
||||
@ -1452,128 +1447,6 @@ HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin)
|
||||
return TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin);
|
||||
}
|
||||
|
||||
/*
|
||||
* XidInMVCCSnapshot
|
||||
* Is the given XID still-in-progress according to the snapshot?
|
||||
*
|
||||
* Note: GetSnapshotData never stores either top xid or subxids of our own
|
||||
* backend into a snapshot, so these xids will not be reported as "running"
|
||||
* by this function. This is OK for current uses, because we always check
|
||||
* TransactionIdIsCurrentTransactionId first, except when it's known the
|
||||
* XID could not be ours anyway.
|
||||
*/
|
||||
bool
|
||||
XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
/*
|
||||
* Make a quick range check to eliminate most XIDs without looking at the
|
||||
* xip arrays. Note that this is OK even if we convert a subxact XID to
|
||||
* its parent below, because a subxact with XID < xmin has surely also got
|
||||
* a parent with XID < xmin, while one with XID >= xmax must belong to a
|
||||
* parent that was not yet committed at the time of this snapshot.
|
||||
*/
|
||||
|
||||
/* Any xid < xmin is not in-progress */
|
||||
if (TransactionIdPrecedes(xid, snapshot->xmin))
|
||||
return false;
|
||||
/* Any xid >= xmax is in-progress */
|
||||
if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Snapshot information is stored slightly differently in snapshots taken
|
||||
* during recovery.
|
||||
*/
|
||||
if (!snapshot->takenDuringRecovery)
|
||||
{
|
||||
/*
|
||||
* If the snapshot contains full subxact data, the fastest way to
|
||||
* check things is just to compare the given XID against both subxact
|
||||
* XIDs and top-level XIDs. If the snapshot overflowed, we have to
|
||||
* use pg_subtrans to convert a subxact XID to its parent XID, but
|
||||
* then we need only look at top-level XIDs not subxacts.
|
||||
*/
|
||||
if (!snapshot->suboverflowed)
|
||||
{
|
||||
/* we have full data, so search subxip */
|
||||
int32 j;
|
||||
|
||||
for (j = 0; j < snapshot->subxcnt; j++)
|
||||
{
|
||||
if (TransactionIdEquals(xid, snapshot->subxip[j]))
|
||||
return true;
|
||||
}
|
||||
|
||||
/* not there, fall through to search xip[] */
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Snapshot overflowed, so convert xid to top-level. This is safe
|
||||
* because we eliminated too-old XIDs above.
|
||||
*/
|
||||
xid = SubTransGetTopmostTransaction(xid);
|
||||
|
||||
/*
|
||||
* If xid was indeed a subxact, we might now have an xid < xmin,
|
||||
* so recheck to avoid an array scan. No point in rechecking
|
||||
* xmax.
|
||||
*/
|
||||
if (TransactionIdPrecedes(xid, snapshot->xmin))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < snapshot->xcnt; i++)
|
||||
{
|
||||
if (TransactionIdEquals(xid, snapshot->xip[i]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 j;
|
||||
|
||||
/*
|
||||
* In recovery we store all xids in the subxact array because it is by
|
||||
* far the bigger array, and we mostly don't know which xids are
|
||||
* top-level and which are subxacts. The xip array is empty.
|
||||
*
|
||||
* We start by searching subtrans, if we overflowed.
|
||||
*/
|
||||
if (snapshot->suboverflowed)
|
||||
{
|
||||
/*
|
||||
* Snapshot overflowed, so convert xid to top-level. This is safe
|
||||
* because we eliminated too-old XIDs above.
|
||||
*/
|
||||
xid = SubTransGetTopmostTransaction(xid);
|
||||
|
||||
/*
|
||||
* If xid was indeed a subxact, we might now have an xid < xmin,
|
||||
* so recheck to avoid an array scan. No point in rechecking
|
||||
* xmax.
|
||||
*/
|
||||
if (TransactionIdPrecedes(xid, snapshot->xmin))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have either a top-level xid higher than xmin or an
|
||||
* indeterminate xid. We don't know whether it's top level or subxact
|
||||
* but it doesn't matter. If it's present, the xid is visible.
|
||||
*/
|
||||
for (j = 0; j < snapshot->subxcnt; j++)
|
||||
{
|
||||
if (TransactionIdEquals(xid, snapshot->subxip[j]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the tuple really only locked? That is, is it not updated?
|
||||
*
|
||||
|
@ -61,6 +61,45 @@ extern PGDLLIMPORT TransactionId RecentXmin;
|
||||
extern PGDLLIMPORT TransactionId RecentGlobalXmin;
|
||||
extern PGDLLIMPORT TransactionId RecentGlobalDataXmin;
|
||||
|
||||
/* Variables representing various special snapshot semantics */
|
||||
extern PGDLLIMPORT SnapshotData SnapshotSelfData;
|
||||
extern PGDLLIMPORT SnapshotData SnapshotAnyData;
|
||||
extern PGDLLIMPORT SnapshotData CatalogSnapshotData;
|
||||
|
||||
#define SnapshotSelf (&SnapshotSelfData)
|
||||
#define SnapshotAny (&SnapshotAnyData)
|
||||
|
||||
/*
|
||||
* We don't provide a static SnapshotDirty variable because it would be
|
||||
* non-reentrant. Instead, users of that snapshot type should declare a
|
||||
* local variable of type SnapshotData, and initialize it with this macro.
|
||||
*/
|
||||
#define InitDirtySnapshot(snapshotdata) \
|
||||
((snapshotdata).snapshot_type = SNAPSHOT_DIRTY)
|
||||
|
||||
/*
|
||||
* Similarly, some initialization is required for a NonVacuumable snapshot.
|
||||
* The caller must supply the xmin horizon to use (e.g., RecentGlobalXmin).
|
||||
*/
|
||||
#define InitNonVacuumableSnapshot(snapshotdata, xmin_horizon) \
|
||||
((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
|
||||
(snapshotdata).xmin = (xmin_horizon))
|
||||
|
||||
/*
|
||||
* Similarly, some initialization is required for SnapshotToast. We need
|
||||
* to set lsn and whenTaken correctly to support snapshot_too_old.
|
||||
*/
|
||||
#define InitToastSnapshot(snapshotdata, l, w) \
|
||||
((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \
|
||||
(snapshotdata).lsn = (l), \
|
||||
(snapshotdata).whenTaken = (w))
|
||||
|
||||
/* This macro encodes the knowledge of which snapshots are MVCC-safe */
|
||||
#define IsMVCCSnapshot(snapshot) \
|
||||
((snapshot)->snapshot_type == SNAPSHOT_MVCC || \
|
||||
(snapshot)->snapshot_type == SNAPSHOT_HISTORIC_MVCC)
|
||||
|
||||
|
||||
extern Snapshot GetTransactionSnapshot(void);
|
||||
extern Snapshot GetLatestSnapshot(void);
|
||||
extern void SnapshotSetCommandId(CommandId curcid);
|
||||
@ -98,6 +137,11 @@ extern void MaintainOldSnapshotTimeMapping(TimestampTz whenTaken,
|
||||
|
||||
extern char *ExportSnapshot(Snapshot snapshot);
|
||||
|
||||
/*
|
||||
* Utility functions for implementing visibility routines in table AMs.
|
||||
*/
|
||||
extern bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
|
||||
|
||||
/* Support for catalog timetravel for logical decoding */
|
||||
struct HTAB;
|
||||
extern struct HTAB *HistoricSnapshotGetTupleCids(void);
|
||||
|
@ -17,20 +17,6 @@
|
||||
|
||||
#include "utils/snapshot.h"
|
||||
|
||||
|
||||
/* Static variables representing various special snapshot semantics */
|
||||
extern PGDLLIMPORT SnapshotData SnapshotSelfData;
|
||||
extern PGDLLIMPORT SnapshotData SnapshotAnyData;
|
||||
extern PGDLLIMPORT SnapshotData CatalogSnapshotData;
|
||||
|
||||
#define SnapshotSelf (&SnapshotSelfData)
|
||||
#define SnapshotAny (&SnapshotAnyData)
|
||||
|
||||
/* This macro encodes the knowledge of which snapshots are MVCC-safe */
|
||||
#define IsMVCCSnapshot(snapshot) \
|
||||
((snapshot)->snapshot_type == SNAPSHOT_MVCC || \
|
||||
(snapshot)->snapshot_type == SNAPSHOT_HISTORIC_MVCC)
|
||||
|
||||
extern bool HeapTupleSatisfiesVisibility(HeapTuple stup, Snapshot snapshot,
|
||||
Buffer buffer);
|
||||
|
||||
@ -51,7 +37,6 @@ extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup,
|
||||
TransactionId OldestXmin, Buffer buffer);
|
||||
extern bool HeapTupleIsSurelyDead(HeapTuple htup,
|
||||
TransactionId OldestXmin);
|
||||
extern bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
|
||||
|
||||
extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
|
||||
uint16 infomask, TransactionId xid);
|
||||
@ -68,29 +53,4 @@ extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data,
|
||||
Buffer buffer,
|
||||
CommandId *cmin, CommandId *cmax);
|
||||
|
||||
/*
|
||||
* We don't provide a static SnapshotDirty variable because it would be
|
||||
* non-reentrant. Instead, users of that snapshot type should declare a
|
||||
* local variable of type SnapshotData, and initialize it with this macro.
|
||||
*/
|
||||
#define InitDirtySnapshot(snapshotdata) \
|
||||
((snapshotdata).snapshot_type = SNAPSHOT_DIRTY)
|
||||
|
||||
/*
|
||||
* Similarly, some initialization is required for a NonVacuumable snapshot.
|
||||
* The caller must supply the xmin horizon to use (e.g., RecentGlobalXmin).
|
||||
*/
|
||||
#define InitNonVacuumableSnapshot(snapshotdata, xmin_horizon) \
|
||||
((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
|
||||
(snapshotdata).xmin = (xmin_horizon))
|
||||
|
||||
/*
|
||||
* Similarly, some initialization is required for SnapshotToast. We need
|
||||
* to set lsn and whenTaken correctly to support snapshot_too_old.
|
||||
*/
|
||||
#define InitToastSnapshot(snapshotdata, l, w) \
|
||||
((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \
|
||||
(snapshotdata).lsn = (l), \
|
||||
(snapshotdata).whenTaken = (w))
|
||||
|
||||
#endif /* TQUAL_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user